Skip to content

Commit

Permalink
feat: support js workspaces
Browse files Browse the repository at this point in the history
chore: tweak default configs
  • Loading branch information
gabotechs committed Dec 26, 2023
1 parent 63181c9 commit d300569
Show file tree
Hide file tree
Showing 30 changed files with 447 additions and 81 deletions.
1 change: 1 addition & 0 deletions cmd/.root_test/.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Flags:
--follow-re-exports whether to follow re-exports or not while resolving imports between files (default true)
-h, --help help for dep-tree
--js-follow-ts-config-paths whether to follow the tsconfig.json paths while resolving imports or not (default false)
--js-follow-workspaces whether to take the workspaces attribute in the root package.json into account or not (default false)
--python-exclude-conditional-imports exclude conditional imports while calculating file dependencies, like imports wrapped inside if statements (default false)
-v, --version version for dep-tree

Expand Down
1 change: 1 addition & 0 deletions cmd/.root_test/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Flags:
--follow-re-exports whether to follow re-exports or not while resolving imports between files (default true)
-h, --help help for dep-tree
--js-follow-ts-config-paths whether to follow the tsconfig.json paths while resolving imports or not (default false)
--js-follow-workspaces whether to take the workspaces attribute in the root package.json into account or not (default false)
--python-exclude-conditional-imports exclude conditional imports while calculating file dependencies, like imports wrapped inside if statements (default false)
-v, --version version for dep-tree

Expand Down
9 changes: 0 additions & 9 deletions cmd/entropy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package cmd
import (
"github.com/spf13/cobra"

"github.com/gabotechs/dep-tree/internal/config"

"github.com/gabotechs/dep-tree/internal/entropy"
)

Expand All @@ -24,13 +22,6 @@ func EntropyCmd() *cobra.Command {
if err != nil {
return err
}
if cfg == nil {
cfg = &config.Config{}
}
if cfg.FollowReExports == nil {
v := false
cfg.FollowReExports = &v
}
parserBuilder, err := makeParserBuilder(entrypoint, cfg)
if err != nil {
return err
Expand Down
26 changes: 16 additions & 10 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

var configPath string
var jsFollowTsConfigPaths bool
var jsFollowWorkspaces bool
var pythonExcludeConditionalImports bool
var followReExports bool
var exclude []string
Expand Down Expand Up @@ -52,17 +53,24 @@ func NewRoot(args []string) *cobra.Command {
root.AddCommand(ConfigCmd())

root.PersistentFlags().StringVarP(&configPath, "config", "c", "", "path to dep-tree's config file (default .dep-tree.yml)")
// TODO: call this '--unwrap-exports'
root.PersistentFlags().BoolVar(&followReExports, "follow-re-exports", true, "whether to follow re-exports or not while resolving imports between files")
// TODO: call this '--js-tsconfig-paths'
root.PersistentFlags().BoolVar(&jsFollowTsConfigPaths, "js-follow-ts-config-paths", false, "whether to follow the tsconfig.json paths while resolving imports or not (default false)")
// TODO: call this '--js-workspaces'
root.PersistentFlags().BoolVar(&jsFollowWorkspaces, "js-follow-workspaces", false, "whether to take the workspaces attribute in the root package.json into account or not (default false)")
root.PersistentFlags().BoolVar(&pythonExcludeConditionalImports, "python-exclude-conditional-imports", false, "exclude conditional imports while calculating file dependencies, like imports wrapped inside if statements (default false)")
root.PersistentFlags().StringArrayVar(&exclude, "exclude", nil, "Files that match this glob pattern will be ignored. You can provide an arbitrary number of --exclude flags")

switch {
case len(args) > 0 && utils.InArray(args[0], []string{"help", "completion", "-v", "--version", "-h", "--help"}):
// do nothing.
case len(args) == 0:
// if not args where provided, default to help.
root.SetArgs([]string{"help"})
default:
// if some args where provided, but it's none of the root commands,
// choose a default command.
cmd, _, err := root.Find(args)
if err == nil && cmd.Use == root.Use && !errors.Is(cmd.Flags().Parse(args), pflag.ErrHelp) {
root.SetArgs(append([]string{"render"}, args...))
Expand All @@ -86,29 +94,27 @@ func makeParserBuilder(entrypoint string, cfg *config.Config) (language.NodePars

func loadConfig() (*config.Config, error) {
cfg, err := config.ParseConfig(configPath)
if err != nil {
return nil, err
}
if root.PersistentFlags().Changed("follow-re-exports") {
cfg.FollowReExports = &followReExports
cfg.FollowReExports = followReExports
}
if root.PersistentFlags().Changed("js-follow-ts-config-paths") {
cfg.Js.FollowTsConfigPaths = jsFollowTsConfigPaths
}
if root.PersistentFlags().Changed("js-follow-workspaces") {
cfg.Js.FollowWorkspaces = jsFollowWorkspaces
}
if root.PersistentFlags().Changed("python-exclude-conditional-imports") {
cfg.Python.ExcludeConditionalImports = pythonExcludeConditionalImports
}
cfg.Exclude = append(cfg.Exclude, exclude...)
// validate exclusion patterns.
for _, exclusion := range cfg.Exclude {
if _, err := utils.GlobstarMatch(exclusion, ""); err != nil {
return nil, fmt.Errorf("exclude pattern '%s' is not correctly formatted", exclusion)
}
}
// Config load fails if a path was explicitly specified but the path does not exist.
// If a path was not specified it's fine even if the default path does not exist.
if os.IsNotExist(err) {
if configPath != "" {
return nil, err
}
} else if err != nil {
return nil, err
}
return cfg, nil
}
40 changes: 24 additions & 16 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,48 +23,56 @@ var SampleConfig string
type Config struct {
Path string
Exclude []string `yaml:"exclude"`
FollowReExports *bool `yaml:"followReExports,omitempty"`
FollowReExports bool `yaml:"followReExports"`
Check check.Config `yaml:"check"`
Js js.Config `yaml:"js"`
Rust rust.Config `yaml:"rust"`
Python python.Config `yaml:"python"`
}

func (c *Config) UnwrapProxyExports() bool {
if c.FollowReExports == nil {
return true
}
return *c.FollowReExports
return c.FollowReExports
}

func (c *Config) IgnoreFiles() []string {
return c.Exclude
}

func ParseConfig(cfgPath string) (*Config, error) {
// Default values.
cfg := Config{
FollowReExports: false,
Js: js.Config{
FollowWorkspaces: true,
FollowTsConfigPaths: true,
},
Python: python.Config{
ExcludeConditionalImports: false,
},
Rust: rust.Config{},
}

isDefault := cfgPath == ""
if cfgPath == "" {
cfgPath = DefaultConfigPath
}

content, err := os.ReadFile(cfgPath)
if os.IsNotExist(err) {
return &Config{}, err
}
if err != nil {
return nil, err
if !isDefault {
return &cfg, err
}
} else if err != nil {
return &cfg, err
}
absCfgPath, err := filepath.Abs(cfgPath)
if err != nil {
return nil, err
}

cfg := Config{
Path: path.Dir(absCfgPath),
return &cfg, err
}
cfg.Path = path.Dir(absCfgPath)

err = yaml.Unmarshal(content, &cfg)
if err != nil {
return nil, fmt.Errorf(`config file "%s" is not a valid yml file`, cfgPath)
return &cfg, fmt.Errorf(`config file "%s" is not a valid yml file`, cfgPath)
}
cfg.Check.Init(path.Dir(absCfgPath))
return &cfg, nil
Expand Down
13 changes: 10 additions & 3 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ func TestParseConfig(t *testing.T) {
ExpectedWhiteList map[string][]string
ExpectedBlackList map[string][]string
}{
{
Name: "default file",
File: "",
},
{
Name: "Simple",
File: ".parse.yml",
Expand Down Expand Up @@ -54,7 +58,10 @@ func TestParseConfig(t *testing.T) {
t.Run(tt.Name, func(t *testing.T) {
a := require.New(t)

cfg, err := ParseConfig(path.Join(testFolder, tt.File))
if tt.File != "" {
tt.File = path.Join(testFolder, tt.File)
}
cfg, err := ParseConfig(tt.File)
a.NoError(err)

a.Equal(tt.ExpectedWhiteList, cfg.Check.WhiteList)
Expand All @@ -71,7 +78,7 @@ func TestConfig_ErrorHandling(t *testing.T) {
}{
{
Name: "No config file",
File: "",
File: ".non-existing.yml",
Expected: "no such file or directory",
},
{
Expand All @@ -85,7 +92,7 @@ func TestConfig_ErrorHandling(t *testing.T) {
t.Run(tt.Name, func(t *testing.T) {
a := require.New(t)
_, err := ParseConfig(tt.File)
a.Contains(err.Error(), tt.Expected)
a.ErrorContains(err, tt.Expected)
})
}
}
Expand Down
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/a/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "a"
}
Empty file.
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/foo/k/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "@foo/k"
}
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/nested/c/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "c"
}
Empty file.
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/nested/nested/d/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "d"
}
11 changes: 11 additions & 0 deletions internal/js/.workspaces_test/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "root",
"workspaces": [
"a",
"b",
"e",
"foo/k",
"nested/*",
"r-nested/**/*"
]
}
Empty file.
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/r-nested/1/f/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "f"
}
Empty file.
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/r-nested/2/3/g/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "g"
}
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/r-nested/h/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "h"
}
3 changes: 3 additions & 0 deletions internal/js/.workspaces_test/r-nested/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "r-nested"
}
1 change: 1 addition & 0 deletions internal/js/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package js

type Config struct {
FollowTsConfigPaths bool `yaml:"followTsConfigPaths"`
FollowWorkspaces bool `yaml:"followWorkspaces"`
}
2 changes: 1 addition & 1 deletion internal/js/js_grammar/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type AliasedName struct {
}

type ExportDeconstruction struct {
Names []AliasedName `"{" @@ ("," @@)* "}"`
Names []AliasedName `"{" @@ ("," @@)* ","? "}"`
}

type DeclarationExport struct {
Expand Down
15 changes: 9 additions & 6 deletions internal/js/js_grammar/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ func TestExport(t *testing.T) {
{
Name: `export { name1, nameN };`,
ExpectedList: []AliasedName{
{
Original: "name1",
},
{
Original: "nameN",
},
{Original: "name1"},
{Original: "nameN"},
},
},
{
Name: `export { name1, nameN, };`,
ExpectedList: []AliasedName{
{Original: "name1"},
{Original: "nameN"},
},
},
{
Expand Down
4 changes: 4 additions & 0 deletions internal/js/js_grammar/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ func TestImport(t *testing.T) {
Name: "import { One, Other } from 'file'",
ExpectedStatic: []string{"file"},
},
{
Name: "import { One, Other, } from 'file'",
ExpectedStatic: []string{"file"},
},
{
Name: "import { type One, Other } from 'file'",
ExpectedStatic: []string{"file"},
Expand Down
13 changes: 10 additions & 3 deletions internal/js/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ var Extensions = []string{
}

type Language struct {
PackageJsonPath string
Cfg *Config
Workspaces *Workspaces
Cfg *Config
}

var _ language.Language[js_grammar.File] = &Language{}
Expand Down Expand Up @@ -52,8 +52,15 @@ func MakeJsLanguage(ctx context.Context, entrypoint string, cfg *Config) (contex
if !utils.FileExists(entrypoint) {
return ctx, nil, fmt.Errorf("file %s does not exist", entrypoint)
}
workspaces, err := NewWorkspaces(entrypoint)
if err != nil {
return ctx, nil, err
}

return ctx, &Language{Cfg: cfg}, nil
return ctx, &Language{
Cfg: cfg,
Workspaces: workspaces,
}, nil
}

func (l *Language) ParseFile(id string) (*js_grammar.File, error) {
Expand Down
Loading

0 comments on commit d300569

Please sign in to comment.