diff --git a/cmd/npm/common.go b/cmd/npm/common.go index 60a40d7..8b114cd 100644 --- a/cmd/npm/common.go +++ b/cmd/npm/common.go @@ -5,13 +5,18 @@ import ( "fmt" "github.com/safedep/pmg/analyzer" + "github.com/safedep/pmg/config" "github.com/safedep/pmg/guard" "github.com/safedep/pmg/internal/ui" "github.com/safedep/pmg/packagemanager" ) -func executeCommonFlow(pm packagemanager.PackageManager, args []string) error { - packageResolver, err := packagemanager.NewNpmDependencyResolver(packagemanager.NewDefaultNpmDependencyResolverConfig()) +func executeCommonFlow(ctx context.Context, config config.Config, pm packagemanager.PackageManager, args []string) error { + packageResolverConfig := packagemanager.NewDefaultNpmDependencyResolverConfig() + packageResolverConfig.IncludeTransitiveDependencies = config.Transitive + packageResolverConfig.TransitiveDepth = config.TransitiveDepth + + packageResolver, err := packagemanager.NewNpmDependencyResolver(packageResolverConfig) if err != nil { return fmt.Errorf("failed to create npm dependency resolver: %w", err) } @@ -34,23 +39,23 @@ func executeCommonFlow(pm packagemanager.PackageManager, args []string) error { return fmt.Errorf("failed to create package manager guard: %w", err) } - return proxy.Run(context.Background(), args) + return proxy.Run(ctx, args) } -func executeNpmFlow(args []string) error { +func executeNpmFlow(ctx context.Context, config config.Config, args []string) error { packageManager, err := packagemanager.NewNpmPackageManager(packagemanager.DefaultNpmPackageManagerConfig()) if err != nil { return fmt.Errorf("failed to create npm package manager: %w", err) } - return executeCommonFlow(packageManager, args) + return executeCommonFlow(ctx, config, packageManager, args) } -func executePnpmFlow(args []string) error { +func executePnpmFlow(ctx context.Context, config config.Config, args []string) error { packageManager, err := packagemanager.NewNpmPackageManager(packagemanager.DefaultPnpmPackageManagerConfig()) if err != nil { return fmt.Errorf("failed to create pnpm package manager: %w", err) } - return executeCommonFlow(packageManager, args) + return executeCommonFlow(ctx, config, packageManager, args) } diff --git a/cmd/npm/npm.go b/cmd/npm/npm.go index 9016ac4..234b9af 100644 --- a/cmd/npm/npm.go +++ b/cmd/npm/npm.go @@ -2,7 +2,9 @@ package npm import ( _ "embed" + "fmt" + "github.com/safedep/pmg/config" "github.com/spf13/cobra" ) @@ -12,7 +14,12 @@ func NewNpmCommand() *cobra.Command { Short: "Guard npm package manager", DisableFlagParsing: true, RunE: func(cmd *cobra.Command, args []string) error { - return executeNpmFlow(args) + config, err := config.FromContext(cmd.Context()) + if err != nil { + return fmt.Errorf("failed to get config: %w", err) + } + + return executeNpmFlow(cmd.Context(), config, args) }, } } diff --git a/cmd/npm/pnpm.go b/cmd/npm/pnpm.go index 5019c72..e849f12 100644 --- a/cmd/npm/pnpm.go +++ b/cmd/npm/pnpm.go @@ -2,7 +2,9 @@ package npm import ( _ "embed" + "fmt" + "github.com/safedep/pmg/config" "github.com/spf13/cobra" ) @@ -12,7 +14,12 @@ func NewPnpmCommand() *cobra.Command { Short: "Guard pnpm package manager", DisableFlagParsing: true, RunE: func(cmd *cobra.Command, args []string) error { - return executePnpmFlow(args) + config, err := config.FromContext(cmd.Context()) + if err != nil { + return fmt.Errorf("failed to get config: %w", err) + } + + return executePnpmFlow(cmd.Context(), config, args) }, } } diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..8196c72 --- /dev/null +++ b/config/config.go @@ -0,0 +1,32 @@ +package config + +import ( + "context" + "fmt" +) + +type configKey struct{} +type contextValue struct { + Config Config +} + +// Global configuration +type Config struct { + Transitive bool + TransitiveDepth int +} + +// Inject config into context while protecting against context poisoning +func (c Config) Inject(ctx context.Context) context.Context { + return context.WithValue(ctx, configKey{}, &contextValue{Config: c}) +} + +// Extract config from context +func FromContext(ctx context.Context) (Config, error) { + c, ok := ctx.Value(configKey{}).(*contextValue) + if !ok { + return Config{}, fmt.Errorf("config not found in context") + } + + return c.Config, nil +} diff --git a/main.go b/main.go index adaed60..7b8ed68 100644 --- a/main.go +++ b/main.go @@ -6,11 +6,13 @@ import ( "github.com/safedep/dry/log" "github.com/safedep/pmg/cmd/npm" + "github.com/safedep/pmg/config" "github.com/spf13/cobra" ) var ( - debug bool + debug bool + globalConfig config.Config ) func main() { @@ -23,6 +25,8 @@ func main() { } log.InitZapLogger("pmg", "") + + cmd.SetContext(globalConfig.Inject(cmd.Context())) }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { @@ -35,6 +39,9 @@ func main() { } cmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug logging") + cmd.PersistentFlags().BoolVar(&globalConfig.Transitive, "transitive", true, "Resolve transitive dependencies") + cmd.PersistentFlags().IntVar(&globalConfig.TransitiveDepth, "transitive-depth", 20, + "Maximum depth of transitive dependencies to resolve") cmd.AddCommand(npm.NewNpmCommand()) cmd.AddCommand(npm.NewPnpmCommand()) diff --git a/packagemanager/npm_resolver.go b/packagemanager/npm_resolver.go index f0bafd5..4ce30d2 100644 --- a/packagemanager/npm_resolver.go +++ b/packagemanager/npm_resolver.go @@ -21,7 +21,7 @@ type NpmDependencyResolverConfig struct { func NewDefaultNpmDependencyResolverConfig() NpmDependencyResolverConfig { return NpmDependencyResolverConfig{ IncludeDevDependencies: true, - IncludeTransitiveDependencies: false, + IncludeTransitiveDependencies: true, TransitiveDepth: 5, FailFast: false, }