From 25870387090cd329f1677d22c3c9a7f53b0f30f0 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 25 Aug 2022 14:42:32 -0700 Subject: [PATCH 1/9] Refactor pruned yarn lockfile writing Change so we build up the lockfile in memory as opposed to writing/reading an intermediate to disk. This should allow for better testing of the lockfile marshalling logic --- cli/internal/prune/prune.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cli/internal/prune/prune.go b/cli/internal/prune/prune.go index 163b1ea28a144..0116d6ae9910e 100644 --- a/cli/internal/prune/prune.go +++ b/cli/internal/prune/prune.go @@ -3,6 +3,10 @@ package prune import ( "bufio" "fmt" +<<<<<<< HEAD +======= + "strings" +>>>>>>> faed3ba1 (Refactor pruned yarn lockfile writing) "github.com/spf13/cobra" "github.com/spf13/pflag" From 49aa0c3d54380c05b26959039b5739cf15a4e227 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Fri, 26 Aug 2022 10:26:36 -0700 Subject: [PATCH 2/9] Move lockfile reading operation into package manager abstraction --- cli/internal/lockfile/berry_lockfile.go | 33 +++++++++++++ cli/internal/lockfile/yarn_lockfile.go | 61 +++++++++++++++++++++++++ cli/internal/packagemanager/yarn.go | 14 ++++++ cli/internal/prune/prune.go | 4 -- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/cli/internal/lockfile/berry_lockfile.go b/cli/internal/lockfile/berry_lockfile.go index 2bd10a1205239..e78d480c86c76 100644 --- a/cli/internal/lockfile/berry_lockfile.go +++ b/cli/internal/lockfile/berry_lockfile.go @@ -11,14 +11,26 @@ import ( "gopkg.in/yaml.v3" ) +<<<<<<< HEAD // BerryLockfile representation of berry lockfile +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) type BerryLockfile map[string]*YarnLockfileEntry var _ Lockfile = (*BerryLockfile)(nil) +<<<<<<< HEAD // ResolvePackage Given a package and version returns the key, resolved version, and if it was found func (l *BerryLockfile) ResolvePackage(name string, version string) (string, string, bool) { for _, key := range yarnPossibleKeys(name, version) { +======= +func (l *BerryLockfile) PossibleKeys(name string, version string) []string { + return yarnPossibleKeys(name, version) +} + +func (l *BerryLockfile) ResolvePackage(name string, version string) (string, string, bool) { + for _, key := range l.PossibleKeys(name, version) { +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) if entry, ok := (*l)[key]; ok { return key, entry.Version, true } @@ -27,7 +39,10 @@ func (l *BerryLockfile) ResolvePackage(name string, version string) (string, str return "", "", false } +<<<<<<< HEAD // AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *BerryLockfile) AllDependencies(key string) (map[string]string, bool) { deps := map[string]string{} entry, ok := (*l)[key] @@ -45,8 +60,12 @@ func (l *BerryLockfile) AllDependencies(key string) (map[string]string, bool) { return deps, true } +<<<<<<< HEAD // Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given func (l *BerryLockfile) Subgraph(packages []string) (Lockfile, error) { +======= +func (l *BerryLockfile) SubLockfile(packages []string) (Lockfile, error) { +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) lockfile := make(YarnLockfile, len(packages)) for _, key := range packages { entry, ok := (*l)[key] @@ -58,7 +77,10 @@ func (l *BerryLockfile) Subgraph(packages []string) (Lockfile, error) { return &lockfile, nil } +<<<<<<< HEAD // Encode encode the lockfile representation and write it to the given writer +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *BerryLockfile) Encode(w io.Writer) error { var tmp bytes.Buffer yamlEncoder := yaml.NewEncoder(&tmp) @@ -67,9 +89,13 @@ func (l *BerryLockfile) Encode(w io.Writer) error { return errors.Wrap(err, "failed to materialize sub-lockfile. This can happen if your lockfile contains merge conflicts or is somehow corrupted. Please report this if it occurs") } +<<<<<<< HEAD if _, err := io.WriteString(w, "# This file is generated by running \"yarn install\" inside your project.\n# Manual changes might be lost - proceed with caution!\n\n__metadata:\n version: 5\n cacheKey: 8\n\n"); err != nil { return errors.Wrap(err, "failed to write to buffer") } +======= + io.WriteString(w, "# This file is generated by running \"yarn install\" inside your project.\n# Manual changes might be lost - proceed with caution!\n\n__metadata:\n version: 5\n cacheKey: 8\n\n") +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) // because of yarn being yarn, we need to inject lines in between each block of YAML to make it "valid" SYML scan := bufio.NewScanner(&tmp) @@ -77,6 +103,7 @@ func (l *BerryLockfile) Encode(w io.Writer) error { scan.Buffer(buf, 10*1024*1024) for scan.Scan() { line := scan.Text() //Writing to Stdout +<<<<<<< HEAD var stringToWrite string if !strings.HasPrefix(line, " ") { stringToWrite = fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\"")) @@ -86,6 +113,12 @@ func (l *BerryLockfile) Encode(w io.Writer) error { if _, err := io.WriteString(w, stringToWrite); err != nil { return errors.Wrap(err, "failed to write to buffer") +======= + if !strings.HasPrefix(line, " ") { + io.WriteString(w, fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\""))) + } else { + io.WriteString(w, fmt.Sprintf("%v\n", strings.ReplaceAll(line, "'", "\""))) +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) } } diff --git a/cli/internal/lockfile/yarn_lockfile.go b/cli/internal/lockfile/yarn_lockfile.go index 35900a84af4bf..82845d73e000a 100644 --- a/cli/internal/lockfile/yarn_lockfile.go +++ b/cli/internal/lockfile/yarn_lockfile.go @@ -14,18 +14,29 @@ import ( var rnLineEnding = regexp.MustCompile("\"|:\r\n$") var nLineEnding = regexp.MustCompile("\"|:\n$") +<<<<<<< HEAD var lineStart = regexp.MustCompile(`^[\w"]`) var double = regexp.MustCompile(`\:\"\:`) var quotedWhitespace = regexp.MustCompile(`\"\s\"`) +======= +var r = regexp.MustCompile(`^[\w"]`) +var double = regexp.MustCompile(`\:\"\:`) +var o = regexp.MustCompile(`\"\s\"`) +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) // deals with colons // integrity sha-... -> integrity: sha-... // "@apollo/client" latest -> "@apollo/client": latest // "@apollo/client" "0.0.0" -> "@apollo/client": "0.0.0" // apollo-client "0.0.0" -> apollo-client: "0.0.0" +<<<<<<< HEAD var spaceDelimitedChars = regexp.MustCompile(`(\w|\")\s(\"|\w)`) // YarnLockfileEntry package information from yarn lockfile +======= +var a = regexp.MustCompile(`(\w|\")\s(\"|\w)`) + +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) type YarnLockfileEntry struct { // resolved version for the particular entry based on the provided semver revision Version string `yaml:"version"` @@ -37,14 +48,26 @@ type YarnLockfileEntry struct { OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` } +<<<<<<< HEAD // YarnLockfile representation of yarn lockfile +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) type YarnLockfile map[string]*YarnLockfileEntry var _ Lockfile = (*YarnLockfile)(nil) +<<<<<<< HEAD // ResolvePackage Given a package and version returns the key, resolved version, and if it was found func (l *YarnLockfile) ResolvePackage(name string, version string) (string, string, bool) { for _, key := range yarnPossibleKeys(name, version) { +======= +func (l *YarnLockfile) PossibleKeys(name string, version string) []string { + return yarnPossibleKeys(name, version) +} + +func (l *YarnLockfile) ResolvePackage(name string, version string) (string, string, bool) { + for _, key := range l.PossibleKeys(name, version) { +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) if entry, ok := (*l)[key]; ok { return key, entry.Version, true } @@ -53,7 +76,10 @@ func (l *YarnLockfile) ResolvePackage(name string, version string) (string, stri return "", "", false } +<<<<<<< HEAD // AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *YarnLockfile) AllDependencies(key string) (map[string]string, bool) { deps := map[string]string{} entry, ok := (*l)[key] @@ -71,8 +97,12 @@ func (l *YarnLockfile) AllDependencies(key string) (map[string]string, bool) { return deps, true } +<<<<<<< HEAD // Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given func (l *YarnLockfile) Subgraph(packages []string) (Lockfile, error) { +======= +func (l *YarnLockfile) SubLockfile(packages []string) (Lockfile, error) { +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) lockfile := make(YarnLockfile, len(packages)) for _, key := range packages { entry, ok := (*l)[key] @@ -84,7 +114,10 @@ func (l *YarnLockfile) Subgraph(packages []string) (Lockfile, error) { return &lockfile, nil } +<<<<<<< HEAD // Encode encode the lockfile representation and write it to the given writer +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *YarnLockfile) Encode(w io.Writer) error { var tmp bytes.Buffer yamlEncoder := yaml.NewEncoder(&tmp) @@ -93,9 +126,13 @@ func (l *YarnLockfile) Encode(w io.Writer) error { return errors.Wrap(err, "failed to materialize sub-lockfile. This can happen if your lockfile contains merge conflicts or is somehow corrupted. Please report this if it occurs") } +<<<<<<< HEAD if _, err := io.WriteString(w, "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n# yarn lockfile v1\n\n"); err != nil { return errors.Wrap(err, "failed to write to buffer") } +======= + io.WriteString(w, "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n# yarn lockfile v1\n\n") +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) // because of yarn being yarn, we need to inject lines in between each block of YAML to make it "valid" SYML scan := bufio.NewScanner(&tmp) @@ -103,6 +140,7 @@ func (l *YarnLockfile) Encode(w io.Writer) error { scan.Buffer(buf, 10*1024*1024) for scan.Scan() { line := scan.Text() //Writing to Stdout +<<<<<<< HEAD var stringToWrite string if !strings.HasPrefix(line, " ") { stringToWrite = fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\"")) @@ -111,6 +149,12 @@ func (l *YarnLockfile) Encode(w io.Writer) error { } if _, err := io.WriteString(w, stringToWrite); err != nil { return errors.Wrap(err, "failed to write to buffer") +======= + if !strings.HasPrefix(line, " ") { + io.WriteString(w, fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\""))) + } else { + io.WriteString(w, fmt.Sprintf("%v\n", strings.ReplaceAll(line, "'", "\""))) +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) } } @@ -136,13 +180,18 @@ func DecodeYarnLockfile(contents []byte) (*YarnLockfile, error) { } for i, line := range lines { +<<<<<<< HEAD if lineStart.MatchString(line) { +======= + if r.MatchString(line) { +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) first := fmt.Sprintf("\"%v\":", l.ReplaceAllString(line, "")) lines[i] = double.ReplaceAllString(first, "\":") } } if hasLF { +<<<<<<< HEAD output = quotedWhitespace.ReplaceAllString(strings.Join(lines, "\n"), "\": \"") } else { output = quotedWhitespace.ReplaceAllString(strings.Join(lines, "\r\n"), "\": \"") @@ -150,6 +199,15 @@ func DecodeYarnLockfile(contents []byte) (*YarnLockfile, error) { next = []byte(spaceDelimitedChars.ReplaceAllStringFunc(output, func(m string) string { parts := spaceDelimitedChars.FindStringSubmatch(m) +======= + output = o.ReplaceAllString(strings.Join(lines, "\n"), "\": \"") + } else { + output = o.ReplaceAllString(strings.Join(lines, "\r\n"), "\": \"") + } + + next = []byte(a.ReplaceAllStringFunc(output, func(m string) string { + parts := a.FindStringSubmatch(m) +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) return fmt.Sprintf("%s: %s", parts[1], parts[2]) })) @@ -166,9 +224,12 @@ func yarnPossibleKeys(name string, version string) []string { return []string{ fmt.Sprintf("%v@%v", name, version), fmt.Sprintf("%v@npm:%v", name, version), +<<<<<<< HEAD fmt.Sprintf("%v@file:%v", name, version), fmt.Sprintf("%v@workspace:%v", name, version), fmt.Sprintf("%v@yarn:%v", name, version), +======= +>>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) } } diff --git a/cli/internal/packagemanager/yarn.go b/cli/internal/packagemanager/yarn.go index 01cfe103aaebe..1387b30f0030b 100644 --- a/cli/internal/packagemanager/yarn.go +++ b/cli/internal/packagemanager/yarn.go @@ -4,6 +4,7 @@ import ( "fmt" "os/exec" "path/filepath" + "regexp" "strings" "github.com/Masterminds/semver" @@ -12,6 +13,19 @@ import ( "github.com/vercel/turborepo/cli/internal/turbopath" ) +var rnLineEnding = regexp.MustCompile("\"|:\r\n$") +var nLineEnding = regexp.MustCompile("\"|:\n$") +var r = regexp.MustCompile(`^[\w"]`) +var double = regexp.MustCompile(`\:\"\:`) +var o = regexp.MustCompile(`\"\s\"`) + +// deals with colons +// integrity sha-... -> integrity: sha-... +// "@apollo/client" latest -> "@apollo/client": latest +// "@apollo/client" "0.0.0" -> "@apollo/client": "0.0.0" +// apollo-client "0.0.0" -> apollo-client: "0.0.0" +var a = regexp.MustCompile(`(\w|\")\s(\"|\w)`) + var nodejsYarn = PackageManager{ Name: "nodejs-yarn", Slug: "yarn", diff --git a/cli/internal/prune/prune.go b/cli/internal/prune/prune.go index 0116d6ae9910e..163b1ea28a144 100644 --- a/cli/internal/prune/prune.go +++ b/cli/internal/prune/prune.go @@ -3,10 +3,6 @@ package prune import ( "bufio" "fmt" -<<<<<<< HEAD -======= - "strings" ->>>>>>> faed3ba1 (Refactor pruned yarn lockfile writing) "github.com/spf13/cobra" "github.com/spf13/pflag" From 5180af61fb5ce653c2c16386e9e8795bf996fe40 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Fri, 26 Aug 2022 11:27:57 -0700 Subject: [PATCH 3/9] fixup lints --- cli/internal/lockfile/berry_lockfile.go | 33 ------------- cli/internal/lockfile/yarn_lockfile.go | 61 ------------------------- cli/internal/packagemanager/yarn.go | 14 ------ 3 files changed, 108 deletions(-) diff --git a/cli/internal/lockfile/berry_lockfile.go b/cli/internal/lockfile/berry_lockfile.go index e78d480c86c76..2bd10a1205239 100644 --- a/cli/internal/lockfile/berry_lockfile.go +++ b/cli/internal/lockfile/berry_lockfile.go @@ -11,26 +11,14 @@ import ( "gopkg.in/yaml.v3" ) -<<<<<<< HEAD // BerryLockfile representation of berry lockfile -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) type BerryLockfile map[string]*YarnLockfileEntry var _ Lockfile = (*BerryLockfile)(nil) -<<<<<<< HEAD // ResolvePackage Given a package and version returns the key, resolved version, and if it was found func (l *BerryLockfile) ResolvePackage(name string, version string) (string, string, bool) { for _, key := range yarnPossibleKeys(name, version) { -======= -func (l *BerryLockfile) PossibleKeys(name string, version string) []string { - return yarnPossibleKeys(name, version) -} - -func (l *BerryLockfile) ResolvePackage(name string, version string) (string, string, bool) { - for _, key := range l.PossibleKeys(name, version) { ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) if entry, ok := (*l)[key]; ok { return key, entry.Version, true } @@ -39,10 +27,7 @@ func (l *BerryLockfile) ResolvePackage(name string, version string) (string, str return "", "", false } -<<<<<<< HEAD // AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *BerryLockfile) AllDependencies(key string) (map[string]string, bool) { deps := map[string]string{} entry, ok := (*l)[key] @@ -60,12 +45,8 @@ func (l *BerryLockfile) AllDependencies(key string) (map[string]string, bool) { return deps, true } -<<<<<<< HEAD // Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given func (l *BerryLockfile) Subgraph(packages []string) (Lockfile, error) { -======= -func (l *BerryLockfile) SubLockfile(packages []string) (Lockfile, error) { ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) lockfile := make(YarnLockfile, len(packages)) for _, key := range packages { entry, ok := (*l)[key] @@ -77,10 +58,7 @@ func (l *BerryLockfile) SubLockfile(packages []string) (Lockfile, error) { return &lockfile, nil } -<<<<<<< HEAD // Encode encode the lockfile representation and write it to the given writer -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *BerryLockfile) Encode(w io.Writer) error { var tmp bytes.Buffer yamlEncoder := yaml.NewEncoder(&tmp) @@ -89,13 +67,9 @@ func (l *BerryLockfile) Encode(w io.Writer) error { return errors.Wrap(err, "failed to materialize sub-lockfile. This can happen if your lockfile contains merge conflicts or is somehow corrupted. Please report this if it occurs") } -<<<<<<< HEAD if _, err := io.WriteString(w, "# This file is generated by running \"yarn install\" inside your project.\n# Manual changes might be lost - proceed with caution!\n\n__metadata:\n version: 5\n cacheKey: 8\n\n"); err != nil { return errors.Wrap(err, "failed to write to buffer") } -======= - io.WriteString(w, "# This file is generated by running \"yarn install\" inside your project.\n# Manual changes might be lost - proceed with caution!\n\n__metadata:\n version: 5\n cacheKey: 8\n\n") ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) // because of yarn being yarn, we need to inject lines in between each block of YAML to make it "valid" SYML scan := bufio.NewScanner(&tmp) @@ -103,7 +77,6 @@ func (l *BerryLockfile) Encode(w io.Writer) error { scan.Buffer(buf, 10*1024*1024) for scan.Scan() { line := scan.Text() //Writing to Stdout -<<<<<<< HEAD var stringToWrite string if !strings.HasPrefix(line, " ") { stringToWrite = fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\"")) @@ -113,12 +86,6 @@ func (l *BerryLockfile) Encode(w io.Writer) error { if _, err := io.WriteString(w, stringToWrite); err != nil { return errors.Wrap(err, "failed to write to buffer") -======= - if !strings.HasPrefix(line, " ") { - io.WriteString(w, fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\""))) - } else { - io.WriteString(w, fmt.Sprintf("%v\n", strings.ReplaceAll(line, "'", "\""))) ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) } } diff --git a/cli/internal/lockfile/yarn_lockfile.go b/cli/internal/lockfile/yarn_lockfile.go index 82845d73e000a..35900a84af4bf 100644 --- a/cli/internal/lockfile/yarn_lockfile.go +++ b/cli/internal/lockfile/yarn_lockfile.go @@ -14,29 +14,18 @@ import ( var rnLineEnding = regexp.MustCompile("\"|:\r\n$") var nLineEnding = regexp.MustCompile("\"|:\n$") -<<<<<<< HEAD var lineStart = regexp.MustCompile(`^[\w"]`) var double = regexp.MustCompile(`\:\"\:`) var quotedWhitespace = regexp.MustCompile(`\"\s\"`) -======= -var r = regexp.MustCompile(`^[\w"]`) -var double = regexp.MustCompile(`\:\"\:`) -var o = regexp.MustCompile(`\"\s\"`) ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) // deals with colons // integrity sha-... -> integrity: sha-... // "@apollo/client" latest -> "@apollo/client": latest // "@apollo/client" "0.0.0" -> "@apollo/client": "0.0.0" // apollo-client "0.0.0" -> apollo-client: "0.0.0" -<<<<<<< HEAD var spaceDelimitedChars = regexp.MustCompile(`(\w|\")\s(\"|\w)`) // YarnLockfileEntry package information from yarn lockfile -======= -var a = regexp.MustCompile(`(\w|\")\s(\"|\w)`) - ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) type YarnLockfileEntry struct { // resolved version for the particular entry based on the provided semver revision Version string `yaml:"version"` @@ -48,26 +37,14 @@ type YarnLockfileEntry struct { OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` } -<<<<<<< HEAD // YarnLockfile representation of yarn lockfile -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) type YarnLockfile map[string]*YarnLockfileEntry var _ Lockfile = (*YarnLockfile)(nil) -<<<<<<< HEAD // ResolvePackage Given a package and version returns the key, resolved version, and if it was found func (l *YarnLockfile) ResolvePackage(name string, version string) (string, string, bool) { for _, key := range yarnPossibleKeys(name, version) { -======= -func (l *YarnLockfile) PossibleKeys(name string, version string) []string { - return yarnPossibleKeys(name, version) -} - -func (l *YarnLockfile) ResolvePackage(name string, version string) (string, string, bool) { - for _, key := range l.PossibleKeys(name, version) { ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) if entry, ok := (*l)[key]; ok { return key, entry.Version, true } @@ -76,10 +53,7 @@ func (l *YarnLockfile) ResolvePackage(name string, version string) (string, stri return "", "", false } -<<<<<<< HEAD // AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *YarnLockfile) AllDependencies(key string) (map[string]string, bool) { deps := map[string]string{} entry, ok := (*l)[key] @@ -97,12 +71,8 @@ func (l *YarnLockfile) AllDependencies(key string) (map[string]string, bool) { return deps, true } -<<<<<<< HEAD // Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given func (l *YarnLockfile) Subgraph(packages []string) (Lockfile, error) { -======= -func (l *YarnLockfile) SubLockfile(packages []string) (Lockfile, error) { ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) lockfile := make(YarnLockfile, len(packages)) for _, key := range packages { entry, ok := (*l)[key] @@ -114,10 +84,7 @@ func (l *YarnLockfile) SubLockfile(packages []string) (Lockfile, error) { return &lockfile, nil } -<<<<<<< HEAD // Encode encode the lockfile representation and write it to the given writer -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) func (l *YarnLockfile) Encode(w io.Writer) error { var tmp bytes.Buffer yamlEncoder := yaml.NewEncoder(&tmp) @@ -126,13 +93,9 @@ func (l *YarnLockfile) Encode(w io.Writer) error { return errors.Wrap(err, "failed to materialize sub-lockfile. This can happen if your lockfile contains merge conflicts or is somehow corrupted. Please report this if it occurs") } -<<<<<<< HEAD if _, err := io.WriteString(w, "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n# yarn lockfile v1\n\n"); err != nil { return errors.Wrap(err, "failed to write to buffer") } -======= - io.WriteString(w, "# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n# yarn lockfile v1\n\n") ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) // because of yarn being yarn, we need to inject lines in between each block of YAML to make it "valid" SYML scan := bufio.NewScanner(&tmp) @@ -140,7 +103,6 @@ func (l *YarnLockfile) Encode(w io.Writer) error { scan.Buffer(buf, 10*1024*1024) for scan.Scan() { line := scan.Text() //Writing to Stdout -<<<<<<< HEAD var stringToWrite string if !strings.HasPrefix(line, " ") { stringToWrite = fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\"")) @@ -149,12 +111,6 @@ func (l *YarnLockfile) Encode(w io.Writer) error { } if _, err := io.WriteString(w, stringToWrite); err != nil { return errors.Wrap(err, "failed to write to buffer") -======= - if !strings.HasPrefix(line, " ") { - io.WriteString(w, fmt.Sprintf("\n%v\n", strings.ReplaceAll(line, "'", "\""))) - } else { - io.WriteString(w, fmt.Sprintf("%v\n", strings.ReplaceAll(line, "'", "\""))) ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) } } @@ -180,18 +136,13 @@ func DecodeYarnLockfile(contents []byte) (*YarnLockfile, error) { } for i, line := range lines { -<<<<<<< HEAD if lineStart.MatchString(line) { -======= - if r.MatchString(line) { ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) first := fmt.Sprintf("\"%v\":", l.ReplaceAllString(line, "")) lines[i] = double.ReplaceAllString(first, "\":") } } if hasLF { -<<<<<<< HEAD output = quotedWhitespace.ReplaceAllString(strings.Join(lines, "\n"), "\": \"") } else { output = quotedWhitespace.ReplaceAllString(strings.Join(lines, "\r\n"), "\": \"") @@ -199,15 +150,6 @@ func DecodeYarnLockfile(contents []byte) (*YarnLockfile, error) { next = []byte(spaceDelimitedChars.ReplaceAllStringFunc(output, func(m string) string { parts := spaceDelimitedChars.FindStringSubmatch(m) -======= - output = o.ReplaceAllString(strings.Join(lines, "\n"), "\": \"") - } else { - output = o.ReplaceAllString(strings.Join(lines, "\r\n"), "\": \"") - } - - next = []byte(a.ReplaceAllStringFunc(output, func(m string) string { - parts := a.FindStringSubmatch(m) ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) return fmt.Sprintf("%s: %s", parts[1], parts[2]) })) @@ -224,12 +166,9 @@ func yarnPossibleKeys(name string, version string) []string { return []string{ fmt.Sprintf("%v@%v", name, version), fmt.Sprintf("%v@npm:%v", name, version), -<<<<<<< HEAD fmt.Sprintf("%v@file:%v", name, version), fmt.Sprintf("%v@workspace:%v", name, version), fmt.Sprintf("%v@yarn:%v", name, version), -======= ->>>>>>> df744a10 (Move lockfile reading operation into package manager abstraction) } } diff --git a/cli/internal/packagemanager/yarn.go b/cli/internal/packagemanager/yarn.go index 1387b30f0030b..01cfe103aaebe 100644 --- a/cli/internal/packagemanager/yarn.go +++ b/cli/internal/packagemanager/yarn.go @@ -4,7 +4,6 @@ import ( "fmt" "os/exec" "path/filepath" - "regexp" "strings" "github.com/Masterminds/semver" @@ -13,19 +12,6 @@ import ( "github.com/vercel/turborepo/cli/internal/turbopath" ) -var rnLineEnding = regexp.MustCompile("\"|:\r\n$") -var nLineEnding = regexp.MustCompile("\"|:\n$") -var r = regexp.MustCompile(`^[\w"]`) -var double = regexp.MustCompile(`\:\"\:`) -var o = regexp.MustCompile(`\"\s\"`) - -// deals with colons -// integrity sha-... -> integrity: sha-... -// "@apollo/client" latest -> "@apollo/client": latest -// "@apollo/client" "0.0.0" -> "@apollo/client": "0.0.0" -// apollo-client "0.0.0" -> apollo-client: "0.0.0" -var a = regexp.MustCompile(`(\w|\")\s(\"|\w)`) - var nodejsYarn = PackageManager{ Name: "nodejs-yarn", Slug: "yarn", From f787c24c4e0fd30dba2deab747638ae86639c32a Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 17 Aug 2022 16:41:05 -0700 Subject: [PATCH 4/9] Add pnpm lockfile parsing and writing --- cli/internal/lockfile/pnpm_lockfile.go | 280 ++++ cli/internal/lockfile/pnpm_lockfile_test.go | 78 ++ .../pnpm-lockfiles/pnpm6-workspace.yaml | 1187 ++++++++++++++++ .../pnpm-lockfiles/pnpm7-workspace.yaml | 1202 +++++++++++++++++ 4 files changed, 2747 insertions(+) create mode 100644 cli/internal/lockfile/pnpm_lockfile.go create mode 100644 cli/internal/lockfile/pnpm_lockfile_test.go create mode 100644 cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm6-workspace.yaml create mode 100644 cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm7-workspace.yaml diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go new file mode 100644 index 0000000000000..296bc3cde7bc6 --- /dev/null +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -0,0 +1,280 @@ +package lockfile + +import ( + "bytes" + "fmt" + "io" + "strings" + + "text/template" + + "github.com/pkg/errors" + "gopkg.in/yaml.v3" +) + +const pnpmLockfileTemplate = `lockfileVersion: {{ .Version }} + +importers: +{{ range $key, $val := .Importers }} + {{ $key }}: +{{ displayProjectSnapshot $val }} +{{ end }} +packages: +{{ range $key, $val := .Packages }} + {{ $key }}: +{{ displayPackageSnapshot $val }} +{{ end }}{{ if (eq .Version 5.4) }} +{{ end }}` + +// PnpmLockfile Go representation of the contents of 'pnpm-lock.yaml' +// Reference https://github.com/pnpm/pnpm/blob/main/packages/lockfile-types/src/index.ts +type PnpmLockfile struct { + Version float32 `yaml:"lockfileVersion"` + Importers map[string]ProjectSnapshot `yaml:"importers"` + // Keys are of the form '/$PACKAGE/$VERSION' + Packages map[string]PackageSnapshot `yaml:"packages,omitempty"` + NeverBuiltDeps []string `yaml:"neverBuiltDependencies,omitempty"` + OnlyBuiltDeps []string `yaml:"onlyBuiltDependencies,omitempty"` + Overrides map[string]string `yaml:"overrides,omitempty"` + PackageExtChecksum string `yaml:"packageExtensionsChecksum,omitempty"` + PatchedDeps map[string]PatchFile `yaml:"patchedDependencies,omitempty"` +} + +var _ Lockfile = (*PnpmLockfile)(nil) + +// ProjectSnapshot Snapshot used to represent projects in the importers section +type ProjectSnapshot struct { + Specifiers map[string]string `yaml:"specifiers"` + Dependencies map[string]string `yaml:"dependencies,omitempty"` + OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` + DevDependencies map[string]string `yaml:"devDependencies,omitempty"` + DependenciesMeta map[string]DependencyMeta `yaml:"dependenciesMeta,omitempty"` + PublishDirectory string `yaml:"publishDirectory,omitempty"` +} + +// PackageSnapshot Snapshot used to represent a package in the packages setion +type PackageSnapshot struct { + ID string `yaml:"id,omitempty"` + + Resolution PackageResolution `yaml:"resolution,flow"` + Engines struct { + Node string `yaml:"node"` + NPM string `yaml:"npm,omitempty"` + } `yaml:"engines,omitempty,flow"` + HasBin bool `yaml:"hasBin,omitempty"` + + PeerDependencies map[string]string `yaml:"peerDependencies,omitempty"` + PeerDependenciesMeta map[string]struct { + Optional bool `yaml:"optional"` + } `yaml:"peerDependenciesMeta,omitempty"` + Dependencies map[string]string `yaml:"dependencies,omitempty"` + OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` + TransitivePeerDeps []string `yaml:"transitivePeerDependencies,omitempty"` + BundledDependencies []string `yaml:"bundledDependencies,omitempty"` + + Dev bool `yaml:"dev"` + Optional bool `yaml:"optional,omitempty"` + RequiresBuild bool `yaml:"requiresBuild,omitempty"` + Patched bool `yaml:"patched,omitempty"` + Prepare bool `yaml:"prepare,omitempty"` + + // only needed for packages that aren't in npm + Name string `yaml:"name,omitempty"` + Version string `yaml:"version,omitempty"` + + Os []string `yaml:"os,omitempty"` + CPU []string `yaml:"cpu,omitempty"` + LibC []string `yaml:"libc,omitempty"` + Deprecated string `yaml:"deprecated,omitempty"` +} + +// PackageResolution Various resolution strategies for packages +type PackageResolution struct { + Type string `yaml:"type,omitempty"` + // For npm or tarball + Integrity string `yaml:"integrity,omitempty"` + + // For tarball + Tarball string `yaml:"tarball,omitempty"` + + // For local directory + Dir string `yaml:"directory,omitempty"` + + // For git repo + Repo string `yaml:"repo,omitempty"` + Commit string `yaml:"commit,omitempty"` +} + +// PatchFile represent a patch applied to a package +type PatchFile struct { + Path string `yaml:"path"` + Hash string `yaml:"hash"` +} + +func isSupportedVersion(version float32) error { + if version != 5.3 && version != 5.4 { + return errors.Errorf("Unable to generate pnpm-lock.yaml with lockfileVersion: %f", version) + } + return nil +} + +// DependencyMeta metadata for dependencies +type DependencyMeta struct { + Injected bool `yaml:"injected,omitempty"` + Node string `yaml:"node,omitempty"` + Patch string `yaml:"string,omitempty"` +} + +// DecodePnpmLockfile parse a pnpm lockfile +func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { + var lockfile PnpmLockfile + if err := yaml.Unmarshal(contents, &lockfile); err != nil { + return nil, errors.Wrap(err, "could not unmarshal lockfile: ") + } + + if err := isSupportedVersion(lockfile.Version); err != nil { + return nil, err + } + + return &lockfile, nil +} + +// PossibleKeys Given a package name and version return all of the keys it might appear as in the lockfile +func (p *PnpmLockfile) PossibleKeys(name string, version string) []string { + return []string{fmt.Sprintf("/%s/%s", name, version)} +} + +// ResolvePackage Given a package and version returns the key, resolved version, and if it was found +func (p *PnpmLockfile) ResolvePackage(name string, version string) (string, string, bool) { + resolvedVersion, ok := p.resolveSpecifier(name, version) + if !ok { + // @nocommit should we panic if not found? + return "", "", false + } + for _, key := range p.PossibleKeys(name, resolvedVersion) { + if entry, ok := (p.Packages)[key]; ok { + return key, entry.Version, true + } + } + + return "", "", false +} + +// AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package +func (p *PnpmLockfile) AllDependencies(key string) (map[string]string, bool) { + deps := map[string]string{} + entry, ok := (p.Packages)[key] + if !ok { + return deps, false + } + + for name, version := range entry.Dependencies { + deps[name] = version + } + + for name, version := range entry.OptionalDependencies { + deps[name] = version + } + + for name, version := range entry.PeerDependencies { + deps[name] = version + } + + return deps, true +} + +// SubLockfile Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given +func (p *PnpmLockfile) SubLockfile(packages []string) (Lockfile, error) { + lockfilePackages := make(map[string]PackageSnapshot, len(packages)) + for _, key := range packages { + entry, ok := p.Packages[key] + if ok { + lockfilePackages[key] = entry + } else { + return nil, fmt.Errorf("Unable to find lockfile entry for %s", key) + } + } + + lockfile := PnpmLockfile{ + Version: p.Version, + Importers: p.Importers, + Packages: lockfilePackages, + NeverBuiltDeps: p.NeverBuiltDeps, + OnlyBuiltDeps: p.OnlyBuiltDeps, + Overrides: p.Overrides, + PackageExtChecksum: p.PackageExtChecksum, + PatchedDeps: p.PatchedDeps, + } + + return &lockfile, nil +} + +// Encode encode the lockfile representation and write it to the given writer +func (p *PnpmLockfile) Encode(w io.Writer) error { + // will need custom serial logic since 5.3 vs 5.4 will change how we serialize + if err := isSupportedVersion(p.Version); err != nil { + return err + } + + funcMap := template.FuncMap{ + "displayProjectSnapshot": displayProjectSnapshot, + "displayPackageSnapshot": displayPackageSnapshot, + } + t, err := template.New("pnpm lockfile").Funcs(funcMap).Parse(pnpmLockfileTemplate) + if err != nil { + return errors.Wrap(err, "unable to parse pnpm-lock.yaml template") + } + + return t.Execute(w, p) +} + +func (p *PnpmLockfile) resolveSpecifier(name string, specifier string) (string, bool) { + for _, importer := range p.Importers { + for pkgName, pkgSpecifier := range importer.Specifiers { + if name == pkgName && specifier == pkgSpecifier { + resolvedVersion, ok := importer.Dependencies[name] + if !ok { + panic(fmt.Sprintf("Unable to find resolved version for %s@%s", name, specifier)) + } + return resolvedVersion, true + } + } + } + return "", false +} + +func displayProjectSnapshot(projectSnapshot ProjectSnapshot) string { + var b bytes.Buffer + encoder := yaml.NewEncoder(&b) + encoder.SetIndent(2) + if err := encoder.Encode(projectSnapshot); err != nil { + panic("failed to encode importers") + } + + return indentLines(b.String()) +} + +func displayPackageSnapshot(packageSnapshot PackageSnapshot) string { + var b bytes.Buffer + encoder := yaml.NewEncoder(&b) + encoder.SetIndent(2) + if err := encoder.Encode(packageSnapshot); err != nil { + panic("failed to encode importers") + } + return indentLines(b.String()) +} + +func indentLines(text string) string { + lines := strings.Split(strings.TrimRight(text, "\n"), "\n") + indentedLines := make([]string, len(lines)) + for i, line := range lines { + if line == "" { + // Don't indent empty lines + indentedLines[i] = "" + } else { + indentedLines[i] = fmt.Sprintf(" %s", line) + } + } + + return strings.Join(indentedLines, "\n") +} diff --git a/cli/internal/lockfile/pnpm_lockfile_test.go b/cli/internal/lockfile/pnpm_lockfile_test.go new file mode 100644 index 0000000000000..82dad235a3ee3 --- /dev/null +++ b/cli/internal/lockfile/pnpm_lockfile_test.go @@ -0,0 +1,78 @@ +package lockfile + +import ( + "bytes" + "os" + "testing" + + "github.com/pkg/errors" + "github.com/vercel/turborepo/cli/internal/fs" + "gotest.tools/v3/assert" +) + +func getFixture(t *testing.T, name string) ([]byte, error) { + defaultCwd, err := os.Getwd() + if err != nil { + t.Errorf("failed to get cwd: %v", err) + } + cwd, err := fs.CheckedToAbsolutePath(defaultCwd) + if err != nil { + t.Fatalf("cwd is not an absolute directory %v: %v", defaultCwd, err) + } + lockfilePath := cwd.Join("testdata", "pnpm-lockfiles", name) + if !lockfilePath.FileExists() { + return nil, errors.Errorf("unable to find 'testdata/%s'", name) + } + return os.ReadFile(lockfilePath.ToStringDuringMigration()) +} + +func Test_Roundtrip(t *testing.T) { + lockfiles := []string{"pnpm6-workspace.yaml", "pnpm7-workspace.yaml"} + + for _, lockfilePath := range lockfiles { + lockfileContent, err := getFixture(t, lockfilePath) + if err != nil { + t.Errorf("failure getting fixture: %s", err) + } + lockfile, err := DecodePnpmLockfile(lockfileContent) + if err != nil { + t.Errorf("decoding failed %s", err) + } + var b bytes.Buffer + if err := lockfile.Encode(&b); err != nil { + t.Errorf("encoding failed %s", err) + } + + assert.DeepEqual(t, string(lockfileContent), b.String()) + } +} + +func Test_SpecifierResolution(t *testing.T) { + contents, err := getFixture(t, "pnpm7-workspace.yaml") + if err != nil { + t.Error(err) + } + lockfile, err := DecodePnpmLockfile(contents) + if err != nil { + t.Errorf("failure decoding lockfile: %v", err) + } + + type Case struct { + pkg string + specifier string + version string + found bool + } + + cases := []Case{ + {pkg: "lodash", specifier: "latest", version: "4.17.21", found: true}, + {pkg: "express", specifier: "^4.18.1", version: "4.18.1", found: true}, + {pkg: "lodash", specifier: "other-tag", version: "", found: false}, + } + + for _, testCase := range cases { + actualVersion, actualFound := lockfile.resolveSpecifier(testCase.pkg, testCase.specifier) + assert.Equal(t, actualFound, testCase.found, "%s@%s", testCase.pkg, testCase.version) + assert.Equal(t, actualVersion, testCase.version, "%s@%s", testCase.pkg, testCase.version) + } +} diff --git a/cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm6-workspace.yaml b/cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm6-workspace.yaml new file mode 100644 index 0000000000000..28472753bd084 --- /dev/null +++ b/cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm6-workspace.yaml @@ -0,0 +1,1187 @@ +lockfileVersion: 5.3 + +importers: + + .: + specifiers: + '@pnpm/make-dedicated-lockfile': ^0.3.19 + devDependencies: + '@pnpm/make-dedicated-lockfile': 0.3.19 + + packages/a: + specifiers: + b: workspace:* + express: ^4.18.1 + dependencies: + b: link:../b + express: 4.18.1 + + packages/b: + specifiers: + c: workspace:* + lodash: ^4.17.21 + dependencies: + c: link:../c + lodash: 4.17.21 + + packages/c: + specifiers: + chalk: ^5.0.1 + dependencies: + chalk: 5.0.1 + +packages: + + /@babel/code-frame/7.18.6: + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.18.6 + dev: true + + /@babel/helper-validator-identifier/7.18.6: + resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight/7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.18.6 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@pnpm/constants/6.1.0: + resolution: {integrity: sha512-L6AiU3OXv9kjKGTJN9j8n1TeJGDcLX9atQlZvAkthlvbXjvKc5SKNWESc/eXhr5nEfuMWhQhiKHDJCpYejmeCQ==} + engines: {node: '>=14.19'} + dev: true + + /@pnpm/crypto.base32-hash/1.0.1: + resolution: {integrity: sha512-pzAXNn6KxTA3kbcI3iEnYs4vtH51XEVqmK/1EiD18MaPKylhqy8UvMJK3zKG+jeP82cqQbozcTGm4yOQ8i3vNw==} + engines: {node: '>=14.6'} + dependencies: + rfc4648: 1.5.2 + dev: true + + /@pnpm/error/3.0.1: + resolution: {integrity: sha512-hMlbWbFcfcfolNfSjKjpeaZFow71kNg438LZ8rAd01swiVIYRUf/sRv8gGySru6AijYfz5UqslpIJRDbYBkgQA==} + engines: {node: '>=14.19'} + dependencies: + '@pnpm/constants': 6.1.0 + dev: true + + /@pnpm/exec/2.0.0: + resolution: {integrity: sha512-b5ALfWEOFQprWKntN7MF8XWCyslBk2c8u20GEDcDDQOs6c0HyHlWxX5lig8riQKdS000U6YyS4L4b32NOleXAQ==} + engines: {node: '>=10'} + dependencies: + '@pnpm/self-installer': 2.2.1 + command-exists: 1.2.9 + cross-spawn: 7.0.3 + dev: true + + /@pnpm/exportable-manifest/3.1.2: + resolution: {integrity: sha512-IvTBwt3n73pXsU6iS1Y4OipBg3GBN37I/mUR8t3q5N0c5TkVxj9xAsra5/m7mX4dsYCv9BPL6Rw+MuKSV5P1hA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/error': 3.0.1 + '@pnpm/read-project-manifest': 3.0.9 + '@pnpm/types': 8.5.0 + ramda: /@pnpm/ramda/0.28.1 + dev: true + + /@pnpm/find-workspace-dir/4.0.2: + resolution: {integrity: sha512-gU7ycFSWuEGJh7RE/STa33Ch27geODTXIfc+ntiE1BietxfpJIAk34zz51kTUuCFthBkpHlO6yV7jgHD2Tuc3g==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/error': 3.0.1 + find-up: 5.0.0 + dev: true + + /@pnpm/git-utils/0.1.0: + resolution: {integrity: sha512-W3zsG9585cKL+FqgcT+IfTgZX5C+CbNkFjOnJN+qbysT1N30+BbvEByCcDMsTy7QDrAk6oS7WU1Rym3U2xlh2Q==} + engines: {node: '>=14.6'} + dependencies: + execa: /safe-execa/0.1.2 + dev: true + + /@pnpm/graceful-fs/2.0.0: + resolution: {integrity: sha512-ogUZCGf0/UILZt6d8PsO4gA4pXh7f0BumXeFkcCe4AQ65PXPKfAkHC0C30Lheh2EgFOpLZm3twDP1Eiww18gew==} + engines: {node: '>=14.19'} + dependencies: + graceful-fs: 4.2.10 + dev: true + + /@pnpm/lockfile-file/5.3.3_@pnpm+logger@4.0.0: + resolution: {integrity: sha512-IOvjeMRX+++osG9VsfSd7+hVa/sIzhqdrm/nFcL7AexFhC7wjXbWW3YMlN5Cw4v0fwm93fgRZlikIKJ7BmkBBA==} + engines: {node: '>=14.6'} + peerDependencies: + '@pnpm/logger': ^4.0.0 + dependencies: + '@pnpm/constants': 6.1.0 + '@pnpm/error': 3.0.1 + '@pnpm/git-utils': 0.1.0 + '@pnpm/lockfile-types': 4.3.1 + '@pnpm/logger': 4.0.0 + '@pnpm/merge-lockfile-changes': 3.0.9 + '@pnpm/types': 8.5.0 + '@zkochan/rimraf': 2.1.2 + comver-to-semver: 1.0.0 + js-yaml: /@zkochan/js-yaml/0.0.6 + normalize-path: 3.0.0 + ramda: /@pnpm/ramda/0.28.1 + semver: 7.3.7 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + write-file-atomic: 3.0.3 + dev: true + + /@pnpm/lockfile-types/4.3.1: + resolution: {integrity: sha512-xoorF+CuuUvpjfi8Uw/xkf8LI9VDzs9W1gjSxkKS8UwK60zU5fu4agILJfVVGlHO1tnjJeGRuspBjp7UZ8ufMA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/types': 8.5.0 + dev: true + + /@pnpm/logger/4.0.0: + resolution: {integrity: sha512-SIShw+k556e7S7tLZFVSIHjCdiVog1qWzcKW2RbLEHPItdisAFVNIe34kYd9fMSswTlSRLS/qRjw3ZblzWmJ9Q==} + engines: {node: '>=12.17'} + dependencies: + bole: 4.0.1 + ndjson: 2.0.0 + dev: true + + /@pnpm/make-dedicated-lockfile/0.3.19: + resolution: {integrity: sha512-VHllqMh5zviSHds2kOlWSiwmxos3LLGWCVIHpo+HX45D3TXx+oMOgE8k6WB0dSOTVIuGKduoCNTGeSW4p2bD2w==} + engines: {node: '>=14.6'} + hasBin: true + dependencies: + '@pnpm/error': 3.0.1 + '@pnpm/exec': 2.0.0 + '@pnpm/exportable-manifest': 3.1.2 + '@pnpm/find-workspace-dir': 4.0.2 + '@pnpm/lockfile-file': 5.3.3_@pnpm+logger@4.0.0 + '@pnpm/logger': 4.0.0 + '@pnpm/prune-lockfile': 4.0.14 + '@pnpm/read-project-manifest': 3.0.9 + '@pnpm/types': 8.5.0 + ramda: /@pnpm/ramda/0.28.1 + rename-overwrite: 4.0.2 + dev: true + + /@pnpm/merge-lockfile-changes/3.0.9: + resolution: {integrity: sha512-UOl3AYsi13R8bvQNJPNUml8sZYKBRns0xjAcPQomoX3WTU0dv+KzVyv86Iv86YlApP0aJj9MS8Vq++JOC10RKg==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/lockfile-types': 4.3.1 + comver-to-semver: 1.0.0 + ramda: /@pnpm/ramda/0.28.1 + semver: 7.3.7 + dev: true + + /@pnpm/prune-lockfile/4.0.14: + resolution: {integrity: sha512-lICCgm9j3e2Bu75zK4PA1FKjpu9pCcagRbZWruONBf44byyEkHcnTf8b8a9M1MvtoiArhmKOmyOVJ2OFyBBRyA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/constants': 6.1.0 + '@pnpm/lockfile-types': 4.3.1 + '@pnpm/types': 8.5.0 + dependency-path: 9.2.4 + ramda: /@pnpm/ramda/0.28.1 + dev: true + + /@pnpm/ramda/0.28.1: + resolution: {integrity: sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==} + dev: true + + /@pnpm/read-project-manifest/3.0.9: + resolution: {integrity: sha512-27j40C48hA/tqsCiqk9ApJxp2g6WGrrj2RSs0NKhsSHynxAuA1tIvwatNISQbAiMjZiu1lfhzhq8m1QdblyNmA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/error': 3.0.1 + '@pnpm/graceful-fs': 2.0.0 + '@pnpm/types': 8.5.0 + '@pnpm/write-project-manifest': 3.0.7 + detect-indent: 6.1.0 + fast-deep-equal: 3.1.3 + is-windows: 1.0.2 + json5: 2.2.1 + parse-json: 5.2.0 + read-yaml-file: 2.1.0 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + dev: true + + /@pnpm/self-installer/2.2.1: + resolution: {integrity: sha512-aefLe96wAWghkx6q1PwbVS1Iz1iGE+HKwkTmtzWLFXeGhbknaIdG2voMwaBGIYGCSxm8sDKR1uLO4aRRAYuc+Q==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /@pnpm/types/8.5.0: + resolution: {integrity: sha512-PSKnhkwgiZtp9dcWZR9mPz2W9UopmADr9o8FTqazo5kjUSh2xQmDUSJOJ/ZWcfNziO64Ix/VbcxKIZeplhog1Q==} + engines: {node: '>=14.6'} + dev: true + + /@pnpm/write-project-manifest/3.0.7: + resolution: {integrity: sha512-rMgIWR52asESg1D7Cp/vBi3dBsv18iUWPvvtYNynrcOjRdE3NsH5CAdfZP/XN6HJF6CSY8rS9W4YC5Q3JGtxiw==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/types': 8.5.0 + json5: 2.2.1 + write-file-atomic: 3.0.3 + write-yaml-file: 4.2.0 + dev: true + + /@zkochan/js-yaml/0.0.6: + resolution: {integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /@zkochan/rimraf/2.1.2: + resolution: {integrity: sha512-Lc2oK51J6aQWcLWTloobJun5ZF41BbTDdLvE+aMcexoVWFoFqvZmnZoyXR2IZk6NJEVoZW8tjgtvQLfTsmRs2Q==} + engines: {node: '>=12.10'} + dependencies: + rimraf: 3.0.2 + dev: true + + /@zkochan/which/2.0.3: + resolution: {integrity: sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /accepts/1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-flatten/1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /body-parser/1.20.0: + resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.4 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.10.3 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + dev: false + + /bole/4.0.1: + resolution: {integrity: sha512-42r0aSOJFJti2l6LasBHq2BuWJzohGs349olQnH/ETlJo87XnoWw7UT8pGE6UstjxzOKkwz7tjoFcmSr6L16vg==} + dependencies: + fast-safe-stringify: 2.1.1 + individual: 3.0.0 + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /bytes/3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.1.2 + dev: false + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/5.0.1: + resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /command-exists/1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + dev: true + + /comver-to-semver/1.0.0: + resolution: {integrity: sha512-gcGtbRxjwROQOdXLUWH1fQAXqThUVRZ219aAwgtX3KfYw429/Zv6EIJRf5TBSzWdAGwePmqH7w70WTaX4MDqag==} + engines: {node: '>=12.17'} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /content-disposition/0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type/1.0.4: + resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature/1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie/0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + dependencies: + ms: 2.0.0 + dev: false + + /depd/2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /dependency-path/9.2.4: + resolution: {integrity: sha512-bH29ZcKyo/i5nr4SgnVZGksuoZzroOWpHtKbq8fKdKgJDr0SdUIPu2EwjJkjzbw9SqRzWd912e0opHYJTkFf6w==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/crypto.base32-hash': 1.0.1 + '@pnpm/types': 8.5.0 + encode-registry: 3.0.0 + semver: 7.3.7 + dev: true + + /destroy/1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /ee-first/1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encode-registry/3.0.0: + resolution: {integrity: sha512-2fRYji8K6FwYuQ6EPBKR/J9mcqb7kIoNqt1vGvJr3NrvKfncRiNm00Oxo6gi/YJF8R5Sp2bNFSFdGKTG0rje1Q==} + engines: {node: '>=10'} + dependencies: + mem: 8.1.1 + dev: true + + /encodeurl/1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /escape-html/1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /etag/1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /execa/5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /express/4.18.1: + resolution: {integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.0 + content-disposition: 0.5.4 + content-type: 1.0.4 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.10.3 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + dev: false + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-safe-stringify/2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + dev: true + + /finalhandler/1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + dev: false + + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /forwarded/0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh/0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /get-intrinsic/1.1.2: + resolution: {integrity: sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: false + + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: false + + /http-errors/2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /human-signals/2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /individual/3.0.0: + resolution: {integrity: sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js/1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-plain-obj/2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-typedarray/1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-stringify-safe/5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /map-age-cleaner/0.1.3: + resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} + engines: {node: '>=6'} + dependencies: + p-defer: 1.0.0 + dev: true + + /media-typer/0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /mem/8.1.1: + resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==} + engines: {node: '>=10'} + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 3.1.0 + dev: true + + /merge-descriptors/1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /methods/1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn/3.1.0: + resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} + engines: {node: '>=8'} + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /ndjson/2.0.0: + resolution: {integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + json-stringify-safe: 5.0.1 + minimist: 1.2.6 + readable-stream: 3.6.0 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /negotiator/0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /object-inspect/1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + dev: false + + /on-finished/2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /p-defer/1.0.0: + resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} + engines: {node: '>=4'} + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.18.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parseurl/1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-name/1.0.0: + resolution: {integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==} + dev: true + + /path-to-regexp/0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /proxy-addr/2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs/6.10.3: + resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser/1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body/2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /read-yaml-file/2.1.0: + resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==} + engines: {node: '>=10.13'} + dependencies: + js-yaml: 4.1.0 + strip-bom: 4.0.0 + dev: true + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /rename-overwrite/4.0.2: + resolution: {integrity: sha512-L1sgBgagVgOgb1Z6QZr1yJgSMHI4SXQqAH0l/UbeyHnLKxECvKIlyVEmBo4BqsCAZGg0SBSyjCh68lis5PgC7g==} + engines: {node: '>=12.10'} + dependencies: + '@zkochan/rimraf': 2.1.2 + dev: true + + /rfc4648/1.5.2: + resolution: {integrity: sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==} + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-execa/0.1.2: + resolution: {integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==} + engines: {node: '>=12'} + dependencies: + '@zkochan/which': 2.0.3 + execa: 5.1.1 + path-name: 1.0.0 + dev: true + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /send/0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + dev: false + + /serve-static/1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + dev: false + + /setprototypeof/1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.2 + object-inspect: 1.12.2 + dev: false + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /sort-keys/4.2.0: + resolution: {integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==} + engines: {node: '>=8'} + dependencies: + is-plain-obj: 2.1.0 + dev: true + + /split2/3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /statuses/2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /through2/4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /toidentifier/1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /type-is/1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typedarray-to-buffer/3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + + /unpipe/1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /utils-merge/1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /vary/1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic/3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + dev: true + + /write-yaml-file/4.2.0: + resolution: {integrity: sha512-LwyucHy0uhWqbrOkh9cBluZBeNVxzHjDaE9mwepZG3n3ZlbM4v3ndrFw51zW/NXYFFqP+QWZ72ihtLWTh05e4Q==} + engines: {node: '>=10.13'} + dependencies: + js-yaml: 4.1.0 + write-file-atomic: 3.0.3 + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm7-workspace.yaml b/cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm7-workspace.yaml new file mode 100644 index 0000000000000..301768d4f318f --- /dev/null +++ b/cli/internal/lockfile/testdata/pnpm-lockfiles/pnpm7-workspace.yaml @@ -0,0 +1,1202 @@ +lockfileVersion: 5.4 + +importers: + + .: + specifiers: + '@pnpm/make-dedicated-lockfile': ^0.3.19 + devDependencies: + '@pnpm/make-dedicated-lockfile': 0.3.19 + + packages/a: + specifiers: + b: workspace:* + express: ^4.18.1 + dependencies: + b: link:../b + express: 4.18.1 + + packages/b: + specifiers: + c: workspace:* + lodash: latest + dependencies: + c: link:../c + lodash: 4.17.21 + + packages/c: + specifiers: + chalk: ^5.0.1 + dependencies: + chalk: 5.0.1 + +packages: + + /@babel/code-frame/7.18.6: + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.18.6 + dev: true + + /@babel/helper-validator-identifier/7.18.6: + resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight/7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.18.6 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@pnpm/constants/6.1.0: + resolution: {integrity: sha512-L6AiU3OXv9kjKGTJN9j8n1TeJGDcLX9atQlZvAkthlvbXjvKc5SKNWESc/eXhr5nEfuMWhQhiKHDJCpYejmeCQ==} + engines: {node: '>=14.19'} + dev: true + + /@pnpm/crypto.base32-hash/1.0.1: + resolution: {integrity: sha512-pzAXNn6KxTA3kbcI3iEnYs4vtH51XEVqmK/1EiD18MaPKylhqy8UvMJK3zKG+jeP82cqQbozcTGm4yOQ8i3vNw==} + engines: {node: '>=14.6'} + dependencies: + rfc4648: 1.5.2 + dev: true + + /@pnpm/error/3.0.1: + resolution: {integrity: sha512-hMlbWbFcfcfolNfSjKjpeaZFow71kNg438LZ8rAd01swiVIYRUf/sRv8gGySru6AijYfz5UqslpIJRDbYBkgQA==} + engines: {node: '>=14.19'} + dependencies: + '@pnpm/constants': 6.1.0 + dev: true + + /@pnpm/exec/2.0.0: + resolution: {integrity: sha512-b5ALfWEOFQprWKntN7MF8XWCyslBk2c8u20GEDcDDQOs6c0HyHlWxX5lig8riQKdS000U6YyS4L4b32NOleXAQ==} + engines: {node: '>=10'} + dependencies: + '@pnpm/self-installer': 2.2.1 + command-exists: 1.2.9 + cross-spawn: 7.0.3 + dev: true + + /@pnpm/exportable-manifest/3.1.2: + resolution: {integrity: sha512-IvTBwt3n73pXsU6iS1Y4OipBg3GBN37I/mUR8t3q5N0c5TkVxj9xAsra5/m7mX4dsYCv9BPL6Rw+MuKSV5P1hA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/error': 3.0.1 + '@pnpm/read-project-manifest': 3.0.9 + '@pnpm/types': 8.5.0 + ramda: /@pnpm/ramda/0.28.1 + dev: true + + /@pnpm/find-workspace-dir/4.0.2: + resolution: {integrity: sha512-gU7ycFSWuEGJh7RE/STa33Ch27geODTXIfc+ntiE1BietxfpJIAk34zz51kTUuCFthBkpHlO6yV7jgHD2Tuc3g==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/error': 3.0.1 + find-up: 5.0.0 + dev: true + + /@pnpm/git-utils/0.1.0: + resolution: {integrity: sha512-W3zsG9585cKL+FqgcT+IfTgZX5C+CbNkFjOnJN+qbysT1N30+BbvEByCcDMsTy7QDrAk6oS7WU1Rym3U2xlh2Q==} + engines: {node: '>=14.6'} + dependencies: + execa: /safe-execa/0.1.2 + dev: true + + /@pnpm/graceful-fs/2.0.0: + resolution: {integrity: sha512-ogUZCGf0/UILZt6d8PsO4gA4pXh7f0BumXeFkcCe4AQ65PXPKfAkHC0C30Lheh2EgFOpLZm3twDP1Eiww18gew==} + engines: {node: '>=14.19'} + dependencies: + graceful-fs: 4.2.10 + dev: true + + /@pnpm/lockfile-file/5.3.3_@pnpm+logger@4.0.0: + resolution: {integrity: sha512-IOvjeMRX+++osG9VsfSd7+hVa/sIzhqdrm/nFcL7AexFhC7wjXbWW3YMlN5Cw4v0fwm93fgRZlikIKJ7BmkBBA==} + engines: {node: '>=14.6'} + peerDependencies: + '@pnpm/logger': ^4.0.0 + dependencies: + '@pnpm/constants': 6.1.0 + '@pnpm/error': 3.0.1 + '@pnpm/git-utils': 0.1.0 + '@pnpm/lockfile-types': 4.3.1 + '@pnpm/logger': 4.0.0 + '@pnpm/merge-lockfile-changes': 3.0.9 + '@pnpm/types': 8.5.0 + '@zkochan/rimraf': 2.1.2 + comver-to-semver: 1.0.0 + js-yaml: /@zkochan/js-yaml/0.0.6 + normalize-path: 3.0.0 + ramda: /@pnpm/ramda/0.28.1 + semver: 7.3.7 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + write-file-atomic: 3.0.3 + dev: true + + /@pnpm/lockfile-types/4.3.1: + resolution: {integrity: sha512-xoorF+CuuUvpjfi8Uw/xkf8LI9VDzs9W1gjSxkKS8UwK60zU5fu4agILJfVVGlHO1tnjJeGRuspBjp7UZ8ufMA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/types': 8.5.0 + dev: true + + /@pnpm/logger/4.0.0: + resolution: {integrity: sha512-SIShw+k556e7S7tLZFVSIHjCdiVog1qWzcKW2RbLEHPItdisAFVNIe34kYd9fMSswTlSRLS/qRjw3ZblzWmJ9Q==} + engines: {node: '>=12.17'} + dependencies: + bole: 4.0.1 + ndjson: 2.0.0 + dev: true + + /@pnpm/make-dedicated-lockfile/0.3.19: + resolution: {integrity: sha512-VHllqMh5zviSHds2kOlWSiwmxos3LLGWCVIHpo+HX45D3TXx+oMOgE8k6WB0dSOTVIuGKduoCNTGeSW4p2bD2w==} + engines: {node: '>=14.6'} + hasBin: true + dependencies: + '@pnpm/error': 3.0.1 + '@pnpm/exec': 2.0.0 + '@pnpm/exportable-manifest': 3.1.2 + '@pnpm/find-workspace-dir': 4.0.2 + '@pnpm/lockfile-file': 5.3.3_@pnpm+logger@4.0.0 + '@pnpm/logger': 4.0.0 + '@pnpm/prune-lockfile': 4.0.14 + '@pnpm/read-project-manifest': 3.0.9 + '@pnpm/types': 8.5.0 + ramda: /@pnpm/ramda/0.28.1 + rename-overwrite: 4.0.2 + dev: true + + /@pnpm/merge-lockfile-changes/3.0.9: + resolution: {integrity: sha512-UOl3AYsi13R8bvQNJPNUml8sZYKBRns0xjAcPQomoX3WTU0dv+KzVyv86Iv86YlApP0aJj9MS8Vq++JOC10RKg==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/lockfile-types': 4.3.1 + comver-to-semver: 1.0.0 + ramda: /@pnpm/ramda/0.28.1 + semver: 7.3.7 + dev: true + + /@pnpm/prune-lockfile/4.0.14: + resolution: {integrity: sha512-lICCgm9j3e2Bu75zK4PA1FKjpu9pCcagRbZWruONBf44byyEkHcnTf8b8a9M1MvtoiArhmKOmyOVJ2OFyBBRyA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/constants': 6.1.0 + '@pnpm/lockfile-types': 4.3.1 + '@pnpm/types': 8.5.0 + dependency-path: 9.2.4 + ramda: /@pnpm/ramda/0.28.1 + dev: true + + /@pnpm/ramda/0.28.1: + resolution: {integrity: sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==} + dev: true + + /@pnpm/read-project-manifest/3.0.9: + resolution: {integrity: sha512-27j40C48hA/tqsCiqk9ApJxp2g6WGrrj2RSs0NKhsSHynxAuA1tIvwatNISQbAiMjZiu1lfhzhq8m1QdblyNmA==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/error': 3.0.1 + '@pnpm/graceful-fs': 2.0.0 + '@pnpm/types': 8.5.0 + '@pnpm/write-project-manifest': 3.0.7 + detect-indent: 6.1.0 + fast-deep-equal: 3.1.3 + is-windows: 1.0.2 + json5: 2.2.1 + parse-json: 5.2.0 + read-yaml-file: 2.1.0 + sort-keys: 4.2.0 + strip-bom: 4.0.0 + dev: true + + /@pnpm/self-installer/2.2.1: + resolution: {integrity: sha512-aefLe96wAWghkx6q1PwbVS1Iz1iGE+HKwkTmtzWLFXeGhbknaIdG2voMwaBGIYGCSxm8sDKR1uLO4aRRAYuc+Q==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /@pnpm/types/8.5.0: + resolution: {integrity: sha512-PSKnhkwgiZtp9dcWZR9mPz2W9UopmADr9o8FTqazo5kjUSh2xQmDUSJOJ/ZWcfNziO64Ix/VbcxKIZeplhog1Q==} + engines: {node: '>=14.6'} + dev: true + + /@pnpm/write-project-manifest/3.0.7: + resolution: {integrity: sha512-rMgIWR52asESg1D7Cp/vBi3dBsv18iUWPvvtYNynrcOjRdE3NsH5CAdfZP/XN6HJF6CSY8rS9W4YC5Q3JGtxiw==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/types': 8.5.0 + json5: 2.2.1 + write-file-atomic: 3.0.3 + write-yaml-file: 4.2.0 + dev: true + + /@zkochan/js-yaml/0.0.6: + resolution: {integrity: sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /@zkochan/rimraf/2.1.2: + resolution: {integrity: sha512-Lc2oK51J6aQWcLWTloobJun5ZF41BbTDdLvE+aMcexoVWFoFqvZmnZoyXR2IZk6NJEVoZW8tjgtvQLfTsmRs2Q==} + engines: {node: '>=12.10'} + dependencies: + rimraf: 3.0.2 + dev: true + + /@zkochan/which/2.0.3: + resolution: {integrity: sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /accepts/1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-flatten/1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /body-parser/1.20.0: + resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.4 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.10.3 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /bole/4.0.1: + resolution: {integrity: sha512-42r0aSOJFJti2l6LasBHq2BuWJzohGs349olQnH/ETlJo87XnoWw7UT8pGE6UstjxzOKkwz7tjoFcmSr6L16vg==} + dependencies: + fast-safe-stringify: 2.1.1 + individual: 3.0.0 + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /bytes/3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.1.2 + dev: false + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk/5.0.1: + resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /command-exists/1.2.9: + resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} + dev: true + + /comver-to-semver/1.0.0: + resolution: {integrity: sha512-gcGtbRxjwROQOdXLUWH1fQAXqThUVRZ219aAwgtX3KfYw429/Zv6EIJRf5TBSzWdAGwePmqH7w70WTaX4MDqag==} + engines: {node: '>=12.17'} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /content-disposition/0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type/1.0.4: + resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature/1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie/0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug/2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /depd/2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /dependency-path/9.2.4: + resolution: {integrity: sha512-bH29ZcKyo/i5nr4SgnVZGksuoZzroOWpHtKbq8fKdKgJDr0SdUIPu2EwjJkjzbw9SqRzWd912e0opHYJTkFf6w==} + engines: {node: '>=14.6'} + dependencies: + '@pnpm/crypto.base32-hash': 1.0.1 + '@pnpm/types': 8.5.0 + encode-registry: 3.0.0 + semver: 7.3.7 + dev: true + + /destroy/1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /ee-first/1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /encode-registry/3.0.0: + resolution: {integrity: sha512-2fRYji8K6FwYuQ6EPBKR/J9mcqb7kIoNqt1vGvJr3NrvKfncRiNm00Oxo6gi/YJF8R5Sp2bNFSFdGKTG0rje1Q==} + engines: {node: '>=10'} + dependencies: + mem: 8.1.1 + dev: true + + /encodeurl/1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /escape-html/1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /etag/1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /execa/5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /express/4.18.1: + resolution: {integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.0 + content-disposition: 0.5.4 + content-type: 1.0.4 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.10.3 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-safe-stringify/2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + dev: true + + /finalhandler/1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /forwarded/0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh/0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: false + + /get-intrinsic/1.1.2: + resolution: {integrity: sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: false + + /get-stream/6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: false + + /http-errors/2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /human-signals/2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /iconv-lite/0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /individual/3.0.0: + resolution: {integrity: sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ipaddr.js/1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-plain-obj/2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: true + + /is-stream/2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-typedarray/1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-stringify-safe/5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /lines-and-columns/1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /map-age-cleaner/0.1.3: + resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} + engines: {node: '>=6'} + dependencies: + p-defer: 1.0.0 + dev: true + + /media-typer/0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /mem/8.1.1: + resolution: {integrity: sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==} + engines: {node: '>=10'} + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 3.1.0 + dev: true + + /merge-descriptors/1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /merge-stream/2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /methods/1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mimic-fn/2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn/3.1.0: + resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} + engines: {node: '>=8'} + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + dev: true + + /ms/2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /ndjson/2.0.0: + resolution: {integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + json-stringify-safe: 5.0.1 + minimist: 1.2.6 + readable-stream: 3.6.0 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /negotiator/0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-run-path/4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /object-inspect/1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + dev: false + + /on-finished/2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime/5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /p-defer/1.0.0: + resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} + engines: {node: '>=4'} + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.18.6 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parseurl/1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-name/1.0.0: + resolution: {integrity: sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==} + dev: true + + /path-to-regexp/0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /proxy-addr/2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /qs/6.10.3: + resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser/1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body/2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /read-yaml-file/2.1.0: + resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==} + engines: {node: '>=10.13'} + dependencies: + js-yaml: 4.1.0 + strip-bom: 4.0.0 + dev: true + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /rename-overwrite/4.0.2: + resolution: {integrity: sha512-L1sgBgagVgOgb1Z6QZr1yJgSMHI4SXQqAH0l/UbeyHnLKxECvKIlyVEmBo4BqsCAZGg0SBSyjCh68lis5PgC7g==} + engines: {node: '>=12.10'} + dependencies: + '@zkochan/rimraf': 2.1.2 + dev: true + + /rfc4648/1.5.2: + resolution: {integrity: sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==} + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-execa/0.1.2: + resolution: {integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==} + engines: {node: '>=12'} + dependencies: + '@zkochan/which': 2.0.3 + execa: 5.1.1 + path-name: 1.0.0 + dev: true + + /safer-buffer/2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /send/0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /serve-static/1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /setprototypeof/1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.1.2 + object-inspect: 1.12.2 + dev: false + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /sort-keys/4.2.0: + resolution: {integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==} + engines: {node: '>=8'} + dependencies: + is-plain-obj: 2.1.0 + dev: true + + /split2/3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /statuses/2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline/2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /through2/4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.0 + dev: true + + /toidentifier/1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /type-is/1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typedarray-to-buffer/3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + + /unpipe/1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /utils-merge/1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /vary/1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic/3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + dev: true + + /write-yaml-file/4.2.0: + resolution: {integrity: sha512-LwyucHy0uhWqbrOkh9cBluZBeNVxzHjDaE9mwepZG3n3ZlbM4v3ndrFw51zW/NXYFFqP+QWZ72ihtLWTh05e4Q==} + engines: {node: '>=10.13'} + dependencies: + js-yaml: 4.1.0 + write-file-atomic: 3.0.3 + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true From 1978cb717306a1cca5e7fb3479b6412ebd870079 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Mon, 29 Aug 2022 13:07:35 -0700 Subject: [PATCH 5/9] Hookup pnpm lockfile to pnpm package managers --- cli/internal/context/context.go | 4 ++-- cli/internal/packagemanager/pnpm.go | 5 +++++ cli/internal/packagemanager/pnpm6.go | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cli/internal/context/context.go b/cli/internal/context/context.go index 48b6392cfafaf..e8476c669bcb4 100644 --- a/cli/internal/context/context.go +++ b/cli/internal/context/context.go @@ -202,7 +202,7 @@ func (c *Context) resolveWorkspaceRootDeps(rootPackageJSON *fs.PackageJSON) erro for dep, version := range pkg.Dependencies { pkg.UnresolvedExternalDeps[dep] = version } - if util.IsYarn(c.PackageManager.Name) { + if c.Lockfile != nil { pkg.TransitiveDeps = []string{} c.resolveDepGraph(&lockfileWg, pkg.UnresolvedExternalDeps, depSet, seen, pkg) lockfileWg.Wait() @@ -326,7 +326,7 @@ func (c *Context) parsePackageJSON(repoRoot turbopath.AbsolutePath, pkgJSONPath } func (c *Context) resolveDepGraph(wg *sync.WaitGroup, unresolvedDirectDeps map[string]string, resolvedDepsSet mapset.Set, seen mapset.Set, pkg *fs.PackageJSON) { - if !util.IsYarn(c.PackageManager.Name) { + if c.Lockfile == nil { return } for directDepName, unresolvedVersion := range unresolvedDirectDeps { diff --git a/cli/internal/packagemanager/pnpm.go b/cli/internal/packagemanager/pnpm.go index 050500cb77097..2e6b39a4f54e7 100644 --- a/cli/internal/packagemanager/pnpm.go +++ b/cli/internal/packagemanager/pnpm.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "github.com/Masterminds/semver" + "github.com/vercel/turborepo/cli/internal/lockfile" "github.com/vercel/turborepo/cli/internal/turbopath" "gopkg.in/yaml.v3" ) @@ -81,4 +82,8 @@ var nodejsPnpm = PackageManager{ return (specfileExists && lockfileExists), nil }, + + readLockfile: func(contents []byte) (lockfile.Lockfile, error) { + return lockfile.DecodePnpmLockfile(contents) + }, } diff --git a/cli/internal/packagemanager/pnpm6.go b/cli/internal/packagemanager/pnpm6.go index 1ca7aac16cbf5..61b5eb787218f 100644 --- a/cli/internal/packagemanager/pnpm6.go +++ b/cli/internal/packagemanager/pnpm6.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "github.com/Masterminds/semver" + "github.com/vercel/turborepo/cli/internal/lockfile" "github.com/vercel/turborepo/cli/internal/turbopath" "gopkg.in/yaml.v3" ) @@ -75,4 +76,8 @@ var nodejsPnpm6 = PackageManager{ return (specfileExists && lockfileExists), nil }, + + readLockfile: func(contents []byte) (lockfile.Lockfile, error) { + return lockfile.DecodePnpmLockfile(contents) + }, } From b55d94b70be87d79c1443797059f7895a8d02d5e Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Tue, 30 Aug 2022 19:19:08 -0700 Subject: [PATCH 6/9] rebase and add e2e tests for pnpm prune --- cli/internal/lockfile/pnpm_lockfile.go | 73 +++++++++++-------- cli/internal/packagemanager/packagemanager.go | 3 + .../packagemanager/packagemanager_test.go | 4 +- cli/internal/packagemanager/pnpm.go | 7 +- cli/internal/packagemanager/pnpm6.go | 19 +++-- cli/internal/prune/prune.go | 6 ++ cli/scripts/e2e/e2e.ts | 14 ++-- cli/scripts/monorepo.ts | 1 + 8 files changed, 81 insertions(+), 46 deletions(-) diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index 296bc3cde7bc6..d29344fd32cfa 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -29,9 +29,8 @@ packages: // PnpmLockfile Go representation of the contents of 'pnpm-lock.yaml' // Reference https://github.com/pnpm/pnpm/blob/main/packages/lockfile-types/src/index.ts type PnpmLockfile struct { - Version float32 `yaml:"lockfileVersion"` - Importers map[string]ProjectSnapshot `yaml:"importers"` - // Keys are of the form '/$PACKAGE/$VERSION' + Version float32 `yaml:"lockfileVersion"` + Importers map[string]ProjectSnapshot `yaml:"importers"` Packages map[string]PackageSnapshot `yaml:"packages,omitempty"` NeverBuiltDeps []string `yaml:"neverBuiltDependencies,omitempty"` OnlyBuiltDeps []string `yaml:"onlyBuiltDependencies,omitempty"` @@ -61,7 +60,10 @@ type PackageSnapshot struct { Node string `yaml:"node"` NPM string `yaml:"npm,omitempty"` } `yaml:"engines,omitempty,flow"` - HasBin bool `yaml:"hasBin,omitempty"` + CPU []string `yaml:"cpu,omitempty,flow"` + Os []string `yaml:"os,omitempty,flow"` + HasBin bool `yaml:"hasBin,omitempty"` + RequiresBuild bool `yaml:"requiresBuild,omitempty"` PeerDependencies map[string]string `yaml:"peerDependencies,omitempty"` PeerDependenciesMeta map[string]struct { @@ -72,18 +74,15 @@ type PackageSnapshot struct { TransitivePeerDeps []string `yaml:"transitivePeerDependencies,omitempty"` BundledDependencies []string `yaml:"bundledDependencies,omitempty"` - Dev bool `yaml:"dev"` - Optional bool `yaml:"optional,omitempty"` - RequiresBuild bool `yaml:"requiresBuild,omitempty"` - Patched bool `yaml:"patched,omitempty"` - Prepare bool `yaml:"prepare,omitempty"` + Dev bool `yaml:"dev"` + Optional bool `yaml:"optional,omitempty"` + Patched bool `yaml:"patched,omitempty"` + Prepare bool `yaml:"prepare,omitempty"` // only needed for packages that aren't in npm Name string `yaml:"name,omitempty"` Version string `yaml:"version,omitempty"` - Os []string `yaml:"os,omitempty"` - CPU []string `yaml:"cpu,omitempty"` LibC []string `yaml:"libc,omitempty"` Deprecated string `yaml:"deprecated,omitempty"` } @@ -112,10 +111,13 @@ type PatchFile struct { } func isSupportedVersion(version float32) error { - if version != 5.3 && version != 5.4 { - return errors.Errorf("Unable to generate pnpm-lock.yaml with lockfileVersion: %f", version) + supportedVersions := []float32{5.3, 5.4} + for _, supportedVersion := range supportedVersions { + if version == supportedVersion { + return nil + } } - return nil + return errors.Errorf("Unable to generate pnpm-lock.yaml with lockfileVersion: %f. Supported lockfile versions are %v", version, supportedVersions) } // DependencyMeta metadata for dependencies @@ -139,22 +141,21 @@ func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { return &lockfile, nil } -// PossibleKeys Given a package name and version return all of the keys it might appear as in the lockfile -func (p *PnpmLockfile) PossibleKeys(name string, version string) []string { - return []string{fmt.Sprintf("/%s/%s", name, version)} -} - // ResolvePackage Given a package and version returns the key, resolved version, and if it was found func (p *PnpmLockfile) ResolvePackage(name string, version string) (string, string, bool) { resolvedVersion, ok := p.resolveSpecifier(name, version) if !ok { - // @nocommit should we panic if not found? return "", "", false } - for _, key := range p.PossibleKeys(name, resolvedVersion) { - if entry, ok := (p.Packages)[key]; ok { - return key, entry.Version, true + key := fmt.Sprintf("/%s/%s", name, resolvedVersion) + if entry, ok := (p.Packages)[key]; ok { + var version string + if entry.Version != "" { + version = entry.Version + } else { + version = resolvedVersion } + return key, version, true } return "", "", false @@ -183,8 +184,8 @@ func (p *PnpmLockfile) AllDependencies(key string) (map[string]string, bool) { return deps, true } -// SubLockfile Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given -func (p *PnpmLockfile) SubLockfile(packages []string) (Lockfile, error) { +// Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given +func (p *PnpmLockfile) Subgraph(packages []string) (Lockfile, error) { lockfilePackages := make(map[string]PackageSnapshot, len(packages)) for _, key := range packages { entry, ok := p.Packages[key] @@ -211,7 +212,6 @@ func (p *PnpmLockfile) SubLockfile(packages []string) (Lockfile, error) { // Encode encode the lockfile representation and write it to the given writer func (p *PnpmLockfile) Encode(w io.Writer) error { - // will need custom serial logic since 5.3 vs 5.4 will change how we serialize if err := isSupportedVersion(p.Version); err != nil { return err } @@ -229,14 +229,25 @@ func (p *PnpmLockfile) Encode(w io.Writer) error { } func (p *PnpmLockfile) resolveSpecifier(name string, specifier string) (string, bool) { - for _, importer := range p.Importers { + // Check if the specifier is already a resolved version + _, ok := p.Packages[fmt.Sprintf("/%s/%s", name, specifier)] + if ok { + return specifier, true + } + for workspacePkg, importer := range p.Importers { for pkgName, pkgSpecifier := range importer.Specifiers { if name == pkgName && specifier == pkgSpecifier { - resolvedVersion, ok := importer.Dependencies[name] - if !ok { - panic(fmt.Sprintf("Unable to find resolved version for %s@%s", name, specifier)) + if resolvedVersion, ok := importer.Dependencies[name]; ok { + return resolvedVersion, true + } + if resolvedVersion, ok := importer.DevDependencies[name]; ok { + return resolvedVersion, true } - return resolvedVersion, true + if resolvedVersion, ok := importer.OptionalDependencies[name]; ok { + return resolvedVersion, true + } + + panic(fmt.Sprintf("Unable to find resolved version for %s@%s in %s", name, specifier, workspacePkg)) } } } diff --git a/cli/internal/packagemanager/packagemanager.go b/cli/internal/packagemanager/packagemanager.go index 58d94ef615565..ec2c0885b04b3 100644 --- a/cli/internal/packagemanager/packagemanager.go +++ b/cli/internal/packagemanager/packagemanager.go @@ -39,6 +39,9 @@ type PackageManager struct { // The directory in which package assets are stored by the Package Manager. PackageDir string + // The location of the file that defines the workspace. Empty if workspaces defined in package.json + WorkspacePath string + // The separator that the Package Manger uses to identify arguments that // should be passed through to the underlying script. ArgSeparator []string diff --git a/cli/internal/packagemanager/packagemanager_test.go b/cli/internal/packagemanager/packagemanager_test.go index 7e0930aaa0113..b066821b04400 100644 --- a/cli/internal/packagemanager/packagemanager_test.go +++ b/cli/internal/packagemanager/packagemanager_test.go @@ -374,8 +374,8 @@ func Test_CanPrune(t *testing.T) { "nodejs-npm": {false, false}, "nodejs-berry": {false, true}, "nodejs-yarn": {true, false}, - "nodejs-pnpm": {false, false}, - "nodejs-pnpm6": {false, false}, + "nodejs-pnpm": {true, false}, + "nodejs-pnpm6": {true, false}, } tests := make([]test, len(packageManagers)) diff --git a/cli/internal/packagemanager/pnpm.go b/cli/internal/packagemanager/pnpm.go index 2e6b39a4f54e7..25b3769286b31 100644 --- a/cli/internal/packagemanager/pnpm.go +++ b/cli/internal/packagemanager/pnpm.go @@ -29,7 +29,8 @@ var nodejsPnpm = PackageManager{ // We are allowed to use nil here because ArgSeparator already has a type, so it's a typed nil, // This could just as easily be []string{}, but the style guide says to prefer // nil for empty slices. - ArgSeparator: nil, + ArgSeparator: nil, + WorkspacePath: "pnpm-workspace.yaml", getWorkspaceGlobs: func(rootpath turbopath.AbsolutePath) ([]string, error) { bytes, err := ioutil.ReadFile(rootpath.Join("pnpm-workspace.yaml").ToStringDuringMigration()) @@ -83,6 +84,10 @@ var nodejsPnpm = PackageManager{ return (specfileExists && lockfileExists), nil }, + canPrune: func(cwd turbopath.AbsolutePath) (bool, error) { + return true, nil + }, + readLockfile: func(contents []byte) (lockfile.Lockfile, error) { return lockfile.DecodePnpmLockfile(contents) }, diff --git a/cli/internal/packagemanager/pnpm6.go b/cli/internal/packagemanager/pnpm6.go index 61b5eb787218f..082a4d2266be0 100644 --- a/cli/internal/packagemanager/pnpm6.go +++ b/cli/internal/packagemanager/pnpm6.go @@ -17,13 +17,14 @@ type Pnpm6Workspaces struct { } var nodejsPnpm6 = PackageManager{ - Name: "nodejs-pnpm6", - Slug: "pnpm", - Command: "pnpm", - Specfile: "package.json", - Lockfile: "pnpm-lock.yaml", - PackageDir: "node_modules", - ArgSeparator: []string{"--"}, + Name: "nodejs-pnpm6", + Slug: "pnpm", + Command: "pnpm", + Specfile: "package.json", + Lockfile: "pnpm-lock.yaml", + PackageDir: "node_modules", + ArgSeparator: []string{"--"}, + WorkspacePath: "pnpm-workspace.yaml", getWorkspaceGlobs: func(rootpath turbopath.AbsolutePath) ([]string, error) { bytes, err := ioutil.ReadFile(rootpath.Join("pnpm-workspace.yaml").ToStringDuringMigration()) @@ -77,6 +78,10 @@ var nodejsPnpm6 = PackageManager{ return (specfileExists && lockfileExists), nil }, + canPrune: func(cwd turbopath.AbsolutePath) (bool, error) { + return true, nil + }, + readLockfile: func(contents []byte) (lockfile.Lockfile, error) { return lockfile.DecodePnpmLockfile(contents) }, diff --git a/cli/internal/prune/prune.go b/cli/internal/prune/prune.go index 163b1ea28a144..aa60271ce1924 100644 --- a/cli/internal/prune/prune.go +++ b/cli/internal/prune/prune.go @@ -157,6 +157,12 @@ func (p *prune) prune(opts *opts) error { if err := packageJSONPath.EnsureDir(); err != nil { return errors.Wrap(err, "could not create output directory") } + if workspacePath := ctx.PackageManager.WorkspacePath; workspacePath != "" && fs.FileExists(p.config.Cwd.Join(workspacePath).ToStringDuringMigration()) { + workspaceFile := fs.LstatCachedFile{Path: p.config.Cwd.Join(workspacePath)} + if err := fs.CopyFile(&workspaceFile, outDir.Join(ctx.PackageManager.WorkspacePath).ToStringDuringMigration()); err != nil { + return errors.Wrapf(err, "could not copy %s", ctx.PackageManager.WorkspacePath) + } + } workspaces := []turbopath.AnchoredSystemPath{} targets := []interface{}{opts.scope} internalDeps, err := ctx.TopologicalGraph.Ancestors(opts.scope) diff --git a/cli/scripts/e2e/e2e.ts b/cli/scripts/e2e/e2e.ts index ec50ec89787c8..64640f7464d43 100644 --- a/cli/scripts/e2e/e2e.ts +++ b/cli/scripts/e2e/e2e.ts @@ -550,9 +550,13 @@ function runSmokeTests( } ); - if (["yarn"].includes(npmClient)) { + if (["yarn", "pnpm6", "pnpm"].includes(npmClient)) { // Test `turbo prune --scope=a` // @todo refactor with other package managers + const installArgs = ["--frozen-lockfile"]; + if (["pnpm6", "pnpm"].includes(npmClient)) { + installArgs.push("-r"); + } suite( `${npmClient} + turbo prune${options.cwd ? " from " + options.cwd : ""}`, async () => { @@ -587,7 +591,7 @@ function runSmokeTests( `Expected file ${file} to be generated` ); } - const install = repo.run("install", ["--frozen-lockfile"], { + const install = repo.run("install", installArgs, { cwd: options.cwd ? path.join(options.cwd, "out") : path.join(repo.root, "out"), @@ -595,7 +599,7 @@ function runSmokeTests( assert.is( install.exitCode, 0, - "Expected yarn install --frozen-lockfile to succeed" + `Expected ${npmClient} install --frozen-lockfile to succeed` ); } ); @@ -639,7 +643,7 @@ function runSmokeTests( `Expected file ${file} to be generated` ); } - const install = repo.run("install", ["--frozen-lockfile"], { + const install = repo.run("install", installArgs, { cwd: options.cwd ? path.join(options.cwd, "out") : path.join(repo.root, "out"), @@ -647,7 +651,7 @@ function runSmokeTests( assert.is( install.exitCode, 0, - "Expected yarn install --frozen-lockfile to succeed" + `Expected ${npmClient} install --frozen-lockfile to succeed` ); } ); diff --git a/cli/scripts/monorepo.ts b/cli/scripts/monorepo.ts index 7210d45f18fdd..c0d8f897f1c6c 100644 --- a/cli/scripts/monorepo.ts +++ b/cli/scripts/monorepo.ts @@ -348,6 +348,7 @@ fs.copyFileSync( shell: true, ...options, }); + case "pnpm6": case "pnpm": return execa.sync("pnpm", [command, ...(args || [])], { cwd: this.root, From 5288cb9153f92e18e76dc2bdca4306b2b1dc2f4d Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Wed, 31 Aug 2022 15:25:54 -0700 Subject: [PATCH 7/9] support windows newlines --- cli/internal/lockfile/pnpm_lockfile.go | 30 +++++++++++++++++++++ cli/internal/lockfile/pnpm_lockfile_test.go | 27 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index d29344fd32cfa..8ca8a0a9ed50d 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -1,6 +1,7 @@ package lockfile import ( + "bufio" "bytes" "fmt" "io" @@ -37,6 +38,9 @@ type PnpmLockfile struct { Overrides map[string]string `yaml:"overrides,omitempty"` PackageExtChecksum string `yaml:"packageExtensionsChecksum,omitempty"` PatchedDeps map[string]PatchFile `yaml:"patchedDependencies,omitempty"` + + // Used to track if CRLF should be used for newlines + hasCRLF bool } var _ Lockfile = (*PnpmLockfile)(nil) @@ -129,6 +133,7 @@ type DependencyMeta struct { // DecodePnpmLockfile parse a pnpm lockfile func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { + hasCRLF := bytes.HasSuffix(contents, []byte("\r\n")) var lockfile PnpmLockfile if err := yaml.Unmarshal(contents, &lockfile); err != nil { return nil, errors.Wrap(err, "could not unmarshal lockfile: ") @@ -138,6 +143,8 @@ func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { return nil, err } + lockfile.hasCRLF = hasCRLF + return &lockfile, nil } @@ -225,6 +232,29 @@ func (p *PnpmLockfile) Encode(w io.Writer) error { return errors.Wrap(err, "unable to parse pnpm-lock.yaml template") } + if p.hasCRLF { + var b bytes.Buffer + if err := t.Execute(&b, p); err != nil { + return err + } + scanner := bufio.NewScanner(&b) + crlf := []byte("\r\n") + for scanner.Scan() { + line := scanner.Bytes() + if _, err := w.Write(line); err != nil { + return errors.Wrap(err, "error copying lockfile line") + } + if _, err := w.Write(crlf); err != nil { + return errors.Wrap(err, "error copying lockfile line") + } + } + if err := scanner.Err(); err != nil { + return errors.Wrap(err, "error reading lockfile line from buffer") + } + + return nil + } + return t.Execute(w, p) } diff --git a/cli/internal/lockfile/pnpm_lockfile_test.go b/cli/internal/lockfile/pnpm_lockfile_test.go index 82dad235a3ee3..a62bdb54a0bd6 100644 --- a/cli/internal/lockfile/pnpm_lockfile_test.go +++ b/cli/internal/lockfile/pnpm_lockfile_test.go @@ -47,6 +47,33 @@ func Test_Roundtrip(t *testing.T) { } } +func Test_RoundtripCLRF(t *testing.T) { + lockfiles := []string{"pnpm6-workspace.yaml", "pnpm7-workspace.yaml"} + + for _, lockfilePath := range lockfiles { + lockfileContent, err := getFixture(t, lockfilePath) + var lockfileWithCLRF []byte + if bytes.HasSuffix(lockfileContent, []byte("\r\n")) { + lockfileWithCLRF = lockfileContent + } else { + lockfileWithCLRF = bytes.ReplaceAll(lockfileContent, []byte("\n"), []byte("\r\n")) + } + if err != nil { + t.Errorf("failure getting fixture: %s", err) + } + lockfile, err := DecodePnpmLockfile(lockfileWithCLRF) + if err != nil { + t.Errorf("decoding failed %s", err) + } + var b bytes.Buffer + if err := lockfile.Encode(&b); err != nil { + t.Errorf("encoding failed %s", err) + } + + assert.DeepEqual(t, string(lockfileWithCLRF), b.String()) + } +} + func Test_SpecifierResolution(t *testing.T) { contents, err := getFixture(t, "pnpm7-workspace.yaml") if err != nil { From d1f7137d22f6a978a10526ebbc155cdf2505bda2 Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Fri, 2 Sep 2022 11:34:01 -0700 Subject: [PATCH 8/9] remove additional whitespace in generated pnpm-lock.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Did a quick test of prune to make sure pnpm is still happy with the pruned lockfile: ``` olszewski@chriss-mbp pnpm-prune % turbo_dev prune --scope=docs Generating pruned monorepo for docs in /private/tmp/pnpm-prune/out - Added docs - Added ui - Added tsconfig - Added eslint-config-custom olszewski@chriss-mbp pnpm-prune % cd out olszewski@chriss-mbp out % pnpm install -r --frozen-lockfile Scope: all 5 workspace projects Lockfile is up-to-date, resolution step is skipped . | +300 ++++++++++++++++++++++++++++++ Packages are hard linked from the content-addressable store to the virtual store. Content-addressable store is at: /Users/olszewski/Library/pnpm/store/v3 Virtual store is at: node_modules/.pnpm Progress: resolved 300, reused 300, downloaded 0, added 300, done olszewski@chriss-mbp out % pnpm turbo run dev --filter=docs • Packages in scope: docs • Running dev in 1 packages docs:dev: cache bypass, force executing f63ed34e7a4cd20c docs:dev: docs:dev: > docs@0.0.0 dev /private/tmp/pnpm-prune/out/apps/docs docs:dev: > next dev --port 3001 docs:dev: docs:dev: ready - started server on 0.0.0.0:3001, url: http://localhost:3001 docs:dev: info - automatically enabled Fast Refresh for 1 custom loader docs:dev: event - compiled client and server successfully in 606 ms (154 modules) ``` --- cli/internal/lockfile/pnpm_lockfile.go | 97 +------------------ cli/internal/lockfile/pnpm_lockfile_test.go | 27 +----- cli/internal/packagemanager/packagemanager.go | 2 +- cli/internal/packagemanager/pnpm.go | 4 +- cli/internal/packagemanager/pnpm6.go | 16 +-- cli/internal/prune/prune.go | 6 +- 6 files changed, 21 insertions(+), 131 deletions(-) diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index 8ca8a0a9ed50d..9089bc8098c65 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -1,32 +1,13 @@ package lockfile import ( - "bufio" - "bytes" "fmt" "io" - "strings" - - "text/template" "github.com/pkg/errors" "gopkg.in/yaml.v3" ) -const pnpmLockfileTemplate = `lockfileVersion: {{ .Version }} - -importers: -{{ range $key, $val := .Importers }} - {{ $key }}: -{{ displayProjectSnapshot $val }} -{{ end }} -packages: -{{ range $key, $val := .Packages }} - {{ $key }}: -{{ displayPackageSnapshot $val }} -{{ end }}{{ if (eq .Version 5.4) }} -{{ end }}` - // PnpmLockfile Go representation of the contents of 'pnpm-lock.yaml' // Reference https://github.com/pnpm/pnpm/blob/main/packages/lockfile-types/src/index.ts type PnpmLockfile struct { @@ -38,9 +19,6 @@ type PnpmLockfile struct { Overrides map[string]string `yaml:"overrides,omitempty"` PackageExtChecksum string `yaml:"packageExtensionsChecksum,omitempty"` PatchedDeps map[string]PatchFile `yaml:"patchedDependencies,omitempty"` - - // Used to track if CRLF should be used for newlines - hasCRLF bool } var _ Lockfile = (*PnpmLockfile)(nil) @@ -133,7 +111,6 @@ type DependencyMeta struct { // DecodePnpmLockfile parse a pnpm lockfile func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { - hasCRLF := bytes.HasSuffix(contents, []byte("\r\n")) var lockfile PnpmLockfile if err := yaml.Unmarshal(contents, &lockfile); err != nil { return nil, errors.Wrap(err, "could not unmarshal lockfile: ") @@ -143,8 +120,6 @@ func DecodePnpmLockfile(contents []byte) (*PnpmLockfile, error) { return nil, err } - lockfile.hasCRLF = hasCRLF - return &lockfile, nil } @@ -223,39 +198,13 @@ func (p *PnpmLockfile) Encode(w io.Writer) error { return err } - funcMap := template.FuncMap{ - "displayProjectSnapshot": displayProjectSnapshot, - "displayPackageSnapshot": displayPackageSnapshot, - } - t, err := template.New("pnpm lockfile").Funcs(funcMap).Parse(pnpmLockfileTemplate) - if err != nil { - return errors.Wrap(err, "unable to parse pnpm-lock.yaml template") - } - - if p.hasCRLF { - var b bytes.Buffer - if err := t.Execute(&b, p); err != nil { - return err - } - scanner := bufio.NewScanner(&b) - crlf := []byte("\r\n") - for scanner.Scan() { - line := scanner.Bytes() - if _, err := w.Write(line); err != nil { - return errors.Wrap(err, "error copying lockfile line") - } - if _, err := w.Write(crlf); err != nil { - return errors.Wrap(err, "error copying lockfile line") - } - } - if err := scanner.Err(); err != nil { - return errors.Wrap(err, "error reading lockfile line from buffer") - } + encoder := yaml.NewEncoder(w) + encoder.SetIndent(2) - return nil + if err := encoder.Encode(p); err != nil { + return errors.Wrap(err, "unable to encode pnpm lockfile") } - - return t.Execute(w, p) + return nil } func (p *PnpmLockfile) resolveSpecifier(name string, specifier string) (string, bool) { @@ -283,39 +232,3 @@ func (p *PnpmLockfile) resolveSpecifier(name string, specifier string) (string, } return "", false } - -func displayProjectSnapshot(projectSnapshot ProjectSnapshot) string { - var b bytes.Buffer - encoder := yaml.NewEncoder(&b) - encoder.SetIndent(2) - if err := encoder.Encode(projectSnapshot); err != nil { - panic("failed to encode importers") - } - - return indentLines(b.String()) -} - -func displayPackageSnapshot(packageSnapshot PackageSnapshot) string { - var b bytes.Buffer - encoder := yaml.NewEncoder(&b) - encoder.SetIndent(2) - if err := encoder.Encode(packageSnapshot); err != nil { - panic("failed to encode importers") - } - return indentLines(b.String()) -} - -func indentLines(text string) string { - lines := strings.Split(strings.TrimRight(text, "\n"), "\n") - indentedLines := make([]string, len(lines)) - for i, line := range lines { - if line == "" { - // Don't indent empty lines - indentedLines[i] = "" - } else { - indentedLines[i] = fmt.Sprintf(" %s", line) - } - } - - return strings.Join(indentedLines, "\n") -} diff --git a/cli/internal/lockfile/pnpm_lockfile_test.go b/cli/internal/lockfile/pnpm_lockfile_test.go index a62bdb54a0bd6..c081d27880f9e 100644 --- a/cli/internal/lockfile/pnpm_lockfile_test.go +++ b/cli/internal/lockfile/pnpm_lockfile_test.go @@ -42,35 +42,12 @@ func Test_Roundtrip(t *testing.T) { if err := lockfile.Encode(&b); err != nil { t.Errorf("encoding failed %s", err) } - - assert.DeepEqual(t, string(lockfileContent), b.String()) - } -} - -func Test_RoundtripCLRF(t *testing.T) { - lockfiles := []string{"pnpm6-workspace.yaml", "pnpm7-workspace.yaml"} - - for _, lockfilePath := range lockfiles { - lockfileContent, err := getFixture(t, lockfilePath) - var lockfileWithCLRF []byte - if bytes.HasSuffix(lockfileContent, []byte("\r\n")) { - lockfileWithCLRF = lockfileContent - } else { - lockfileWithCLRF = bytes.ReplaceAll(lockfileContent, []byte("\n"), []byte("\r\n")) - } - if err != nil { - t.Errorf("failure getting fixture: %s", err) - } - lockfile, err := DecodePnpmLockfile(lockfileWithCLRF) + newLockfile, err := DecodePnpmLockfile(b.Bytes()) if err != nil { t.Errorf("decoding failed %s", err) } - var b bytes.Buffer - if err := lockfile.Encode(&b); err != nil { - t.Errorf("encoding failed %s", err) - } - assert.DeepEqual(t, string(lockfileWithCLRF), b.String()) + assert.DeepEqual(t, lockfile, newLockfile) } } diff --git a/cli/internal/packagemanager/packagemanager.go b/cli/internal/packagemanager/packagemanager.go index ec2c0885b04b3..780e1716d522c 100644 --- a/cli/internal/packagemanager/packagemanager.go +++ b/cli/internal/packagemanager/packagemanager.go @@ -40,7 +40,7 @@ type PackageManager struct { PackageDir string // The location of the file that defines the workspace. Empty if workspaces defined in package.json - WorkspacePath string + WorkspaceConfigurationPath string // The separator that the Package Manger uses to identify arguments that // should be passed through to the underlying script. diff --git a/cli/internal/packagemanager/pnpm.go b/cli/internal/packagemanager/pnpm.go index 25b3769286b31..886ea5a8dfb14 100644 --- a/cli/internal/packagemanager/pnpm.go +++ b/cli/internal/packagemanager/pnpm.go @@ -29,8 +29,8 @@ var nodejsPnpm = PackageManager{ // We are allowed to use nil here because ArgSeparator already has a type, so it's a typed nil, // This could just as easily be []string{}, but the style guide says to prefer // nil for empty slices. - ArgSeparator: nil, - WorkspacePath: "pnpm-workspace.yaml", + ArgSeparator: nil, + WorkspaceConfigurationPath: "pnpm-workspace.yaml", getWorkspaceGlobs: func(rootpath turbopath.AbsolutePath) ([]string, error) { bytes, err := ioutil.ReadFile(rootpath.Join("pnpm-workspace.yaml").ToStringDuringMigration()) diff --git a/cli/internal/packagemanager/pnpm6.go b/cli/internal/packagemanager/pnpm6.go index 082a4d2266be0..e227c8b780248 100644 --- a/cli/internal/packagemanager/pnpm6.go +++ b/cli/internal/packagemanager/pnpm6.go @@ -17,14 +17,14 @@ type Pnpm6Workspaces struct { } var nodejsPnpm6 = PackageManager{ - Name: "nodejs-pnpm6", - Slug: "pnpm", - Command: "pnpm", - Specfile: "package.json", - Lockfile: "pnpm-lock.yaml", - PackageDir: "node_modules", - ArgSeparator: []string{"--"}, - WorkspacePath: "pnpm-workspace.yaml", + Name: "nodejs-pnpm6", + Slug: "pnpm", + Command: "pnpm", + Specfile: "package.json", + Lockfile: "pnpm-lock.yaml", + PackageDir: "node_modules", + ArgSeparator: []string{"--"}, + WorkspaceConfigurationPath: "pnpm-workspace.yaml", getWorkspaceGlobs: func(rootpath turbopath.AbsolutePath) ([]string, error) { bytes, err := ioutil.ReadFile(rootpath.Join("pnpm-workspace.yaml").ToStringDuringMigration()) diff --git a/cli/internal/prune/prune.go b/cli/internal/prune/prune.go index aa60271ce1924..c15972f90fad2 100644 --- a/cli/internal/prune/prune.go +++ b/cli/internal/prune/prune.go @@ -157,10 +157,10 @@ func (p *prune) prune(opts *opts) error { if err := packageJSONPath.EnsureDir(); err != nil { return errors.Wrap(err, "could not create output directory") } - if workspacePath := ctx.PackageManager.WorkspacePath; workspacePath != "" && fs.FileExists(p.config.Cwd.Join(workspacePath).ToStringDuringMigration()) { + if workspacePath := ctx.PackageManager.WorkspaceConfigurationPath; workspacePath != "" && fs.FileExists(p.config.Cwd.Join(workspacePath).ToStringDuringMigration()) { workspaceFile := fs.LstatCachedFile{Path: p.config.Cwd.Join(workspacePath)} - if err := fs.CopyFile(&workspaceFile, outDir.Join(ctx.PackageManager.WorkspacePath).ToStringDuringMigration()); err != nil { - return errors.Wrapf(err, "could not copy %s", ctx.PackageManager.WorkspacePath) + if err := fs.CopyFile(&workspaceFile, outDir.Join(ctx.PackageManager.WorkspaceConfigurationPath).ToStringDuringMigration()); err != nil { + return errors.Wrapf(err, "could not copy %s", ctx.PackageManager.WorkspaceConfigurationPath) } } workspaces := []turbopath.AnchoredSystemPath{} From 677bcb6173a4e16b25aa1b5628bfb69c3b33445c Mon Sep 17 00:00:00 2001 From: Chris Olszewski Date: Thu, 8 Sep 2022 11:45:13 -0700 Subject: [PATCH 9/9] fixups for PR --- cli/internal/lockfile/pnpm_lockfile.go | 92 +++++++++++++------------- cli/scripts/e2e/e2e.ts | 3 - 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/cli/internal/lockfile/pnpm_lockfile.go b/cli/internal/lockfile/pnpm_lockfile.go index 9089bc8098c65..7bf14408d78ed 100644 --- a/cli/internal/lockfile/pnpm_lockfile.go +++ b/cli/internal/lockfile/pnpm_lockfile.go @@ -11,62 +11,64 @@ import ( // PnpmLockfile Go representation of the contents of 'pnpm-lock.yaml' // Reference https://github.com/pnpm/pnpm/blob/main/packages/lockfile-types/src/index.ts type PnpmLockfile struct { - Version float32 `yaml:"lockfileVersion"` - Importers map[string]ProjectSnapshot `yaml:"importers"` - Packages map[string]PackageSnapshot `yaml:"packages,omitempty"` - NeverBuiltDeps []string `yaml:"neverBuiltDependencies,omitempty"` - OnlyBuiltDeps []string `yaml:"onlyBuiltDependencies,omitempty"` - Overrides map[string]string `yaml:"overrides,omitempty"` - PackageExtChecksum string `yaml:"packageExtensionsChecksum,omitempty"` - PatchedDeps map[string]PatchFile `yaml:"patchedDependencies,omitempty"` + Version float32 `yaml:"lockfileVersion"` + NeverBuiltDependencies []string `yaml:"neverBuiltDependencies,omitempty"` + OnlyBuiltDependencies []string `yaml:"onlyBuiltDependencies,omitempty"` + Overrides map[string]string `yaml:"overrides,omitempty"` + PackageExtensionsChecksum string `yaml:"packageExtensionsChecksum,omitempty"` + PatchedDependencies map[string]PatchFile `yaml:"patchedDependencies,omitempty"` + Importers map[string]ProjectSnapshot `yaml:"importers"` + Packages map[string]PackageSnapshot `yaml:"packages,omitempty"` + Time map[string]string `yaml:"time,omitempty"` } var _ Lockfile = (*PnpmLockfile)(nil) // ProjectSnapshot Snapshot used to represent projects in the importers section type ProjectSnapshot struct { - Specifiers map[string]string `yaml:"specifiers"` - Dependencies map[string]string `yaml:"dependencies,omitempty"` - OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` - DevDependencies map[string]string `yaml:"devDependencies,omitempty"` - DependenciesMeta map[string]DependencyMeta `yaml:"dependenciesMeta,omitempty"` - PublishDirectory string `yaml:"publishDirectory,omitempty"` + Specifiers map[string]string `yaml:"specifiers"` + Dependencies map[string]string `yaml:"dependencies,omitempty"` + OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` + DevDependencies map[string]string `yaml:"devDependencies,omitempty"` + DependenciesMeta map[string]DependenciesMeta `yaml:"dependenciesMeta,omitempty"` + PublishDirectory string `yaml:"publishDirectory,omitempty"` } // PackageSnapshot Snapshot used to represent a package in the packages setion type PackageSnapshot struct { - ID string `yaml:"id,omitempty"` - Resolution PackageResolution `yaml:"resolution,flow"` - Engines struct { + ID string `yaml:"id,omitempty"` + + // only needed for packages that aren't in npm + Name string `yaml:"name,omitempty"` + Version string `yaml:"version,omitempty"` + + Engines struct { Node string `yaml:"node"` NPM string `yaml:"npm,omitempty"` } `yaml:"engines,omitempty,flow"` - CPU []string `yaml:"cpu,omitempty,flow"` - Os []string `yaml:"os,omitempty,flow"` - HasBin bool `yaml:"hasBin,omitempty"` - RequiresBuild bool `yaml:"requiresBuild,omitempty"` + CPU []string `yaml:"cpu,omitempty,flow"` + Os []string `yaml:"os,omitempty,flow"` + LibC []string `yaml:"libc,omitempty"` + Deprecated string `yaml:"deprecated,omitempty"` + HasBin bool `yaml:"hasBin,omitempty"` + Prepare bool `yaml:"prepare,omitempty"` + RequiresBuild bool `yaml:"requiresBuild,omitempty"` + + BundledDependencies []string `yaml:"bundledDependencies,omitempty"` PeerDependencies map[string]string `yaml:"peerDependencies,omitempty"` PeerDependenciesMeta map[string]struct { Optional bool `yaml:"optional"` } `yaml:"peerDependenciesMeta,omitempty"` + Dependencies map[string]string `yaml:"dependencies,omitempty"` OptionalDependencies map[string]string `yaml:"optionalDependencies,omitempty"` - TransitivePeerDeps []string `yaml:"transitivePeerDependencies,omitempty"` - BundledDependencies []string `yaml:"bundledDependencies,omitempty"` - - Dev bool `yaml:"dev"` - Optional bool `yaml:"optional,omitempty"` - Patched bool `yaml:"patched,omitempty"` - Prepare bool `yaml:"prepare,omitempty"` - - // only needed for packages that aren't in npm - Name string `yaml:"name,omitempty"` - Version string `yaml:"version,omitempty"` - LibC []string `yaml:"libc,omitempty"` - Deprecated string `yaml:"deprecated,omitempty"` + TransitivePeerDependencies []string `yaml:"transitivePeerDependencies,omitempty"` + Dev bool `yaml:"dev"` + Optional bool `yaml:"optional,omitempty"` + Patched bool `yaml:"patched,omitempty"` } // PackageResolution Various resolution strategies for packages @@ -102,11 +104,11 @@ func isSupportedVersion(version float32) error { return errors.Errorf("Unable to generate pnpm-lock.yaml with lockfileVersion: %f. Supported lockfile versions are %v", version, supportedVersions) } -// DependencyMeta metadata for dependencies -type DependencyMeta struct { +// DependenciesMeta metadata for dependencies +type DependenciesMeta struct { Injected bool `yaml:"injected,omitempty"` Node string `yaml:"node,omitempty"` - Patch string `yaml:"string,omitempty"` + Patch string `yaml:"patch,omitempty"` } // DecodePnpmLockfile parse a pnpm lockfile @@ -179,14 +181,14 @@ func (p *PnpmLockfile) Subgraph(packages []string) (Lockfile, error) { } lockfile := PnpmLockfile{ - Version: p.Version, - Importers: p.Importers, - Packages: lockfilePackages, - NeverBuiltDeps: p.NeverBuiltDeps, - OnlyBuiltDeps: p.OnlyBuiltDeps, - Overrides: p.Overrides, - PackageExtChecksum: p.PackageExtChecksum, - PatchedDeps: p.PatchedDeps, + Version: p.Version, + Importers: p.Importers, + Packages: lockfilePackages, + NeverBuiltDependencies: p.NeverBuiltDependencies, + OnlyBuiltDependencies: p.OnlyBuiltDependencies, + Overrides: p.Overrides, + PackageExtensionsChecksum: p.PackageExtensionsChecksum, + PatchedDependencies: p.PatchedDependencies, } return &lockfile, nil diff --git a/cli/scripts/e2e/e2e.ts b/cli/scripts/e2e/e2e.ts index 64640f7464d43..c536c63f1556f 100644 --- a/cli/scripts/e2e/e2e.ts +++ b/cli/scripts/e2e/e2e.ts @@ -554,9 +554,6 @@ function runSmokeTests( // Test `turbo prune --scope=a` // @todo refactor with other package managers const installArgs = ["--frozen-lockfile"]; - if (["pnpm6", "pnpm"].includes(npmClient)) { - installArgs.push("-r"); - } suite( `${npmClient} + turbo prune${options.cwd ? " from " + options.cwd : ""}`, async () => {