diff --git a/cmd/dsk/main.go b/cmd/dsk/main.go index 1a77e48..f67b3d3 100644 --- a/cmd/dsk/main.go +++ b/cmd/dsk/main.go @@ -147,7 +147,7 @@ func main() { if componentsPath != "" { if err := app.OpenComponents(ctx); err != nil { - log.Print(red.Sprintf("Failed to start application: %s", err)) + log.Fatal(red.Sprintf("Failed to start application: %s", err)) } } diff --git a/internal/plex/app.go b/internal/plex/app.go index 49404db..80a081d 100644 --- a/internal/plex/app.go +++ b/internal/plex/app.go @@ -216,6 +216,10 @@ func (app *App) OpenVersions(ctx context.Context) error { func (app *App) OpenComponents(ctx context.Context) error { cmps, err := NewComponents(app.componentsPath) + if err != nil { + return err + } + cmps.Detect() app.Components = cmps return err diff --git a/internal/plex/components.go b/internal/plex/components.go index ad12ba7..7916b9d 100644 --- a/internal/plex/components.go +++ b/internal/plex/components.go @@ -6,6 +6,8 @@ package plex import ( + "encoding/json" + "io/ioutil" "log" "net/http" "os" @@ -24,23 +26,58 @@ var ( } ) -func NewComponents(path string) (*Components, error) { - log.Printf("Initializing components from path %s...", path) - // Allow node module resolution for component paths. - orgFp := filepath.Dir(path) +type packageJsonFields struct { + Name string `json:"name"` +} + +// NewComponents sniffs around to make sure that a package.json is found +// at the path provided by env var. If it is, and its name doesn't match +// the path (in node module's resolution), we fudge the path by +// dropping it at a symlinked path instead. +func NewComponents(pathEnvVar string) (*Components, error) { + log.Printf("Initializing components from path %s...", pathEnvVar) + nodePath := filepath.Clean(pathEnvVar) + + rawPkgJson, err := ioutil.ReadFile(filepath.Join(nodePath, packageJson)) + if err != nil { + return nil, err + } + + var pkgJson packageJsonFields + json.Unmarshal(rawPkgJson, &pkgJson) + + if err != nil { + return nil, err + } - nodePath := path + if filepath.Base(nodePath) != pkgJson.Name { + dir := filepath.Join("dist", pkgJson.Name) - // given /@rundsk/example-component-library, this sets NODE_PATH to be - if strings.HasPrefix(filepath.Base(orgFp), "@") { - nodePath = filepath.Dir(orgFp) + nodePath = "dist" + if err := os.Remove(dir); err != nil && !os.IsNotExist(err) { + return nil, err + } + + splitName := strings.Split(pkgJson.Name, "/") + + if len(splitName) > 1 { + os.MkdirAll(filepath.Dir(dir), os.ModePerm) + } + + err = os.Symlink(filepath.Clean(pathEnvVar), dir) + + if err != nil { + return nil, err + } } - path, err := filepath.Abs(path) + path, err := filepath.Abs(nodePath) + log.Printf("Using path %s as JS entry point", path) return &Components{ - FS: http.Dir(path), - Path: path, - JSEntryPoint: nodePath, + FS: http.Dir(pathEnvVar), + // This is different because the CSS entrypoint doesn't use ESBuild's package.json lookup and NODE_ENV. + Path: filepath.Clean(pathEnvVar), + JSEntryPoint: path, }, err }