mirror of
https://github.com/hanzoai/pack.git
synced 2026-09-30 23:43:13 +00:00
- Migrate module path to github.com/hanzoai/pack across all Go packages - Remove legacy upstream docs and competitor brand references - Modernize LLM.md and mise.toml for pristine Hanzo Pack builder
80 lines
3.0 KiB
Go
80 lines
3.0 KiB
Go
package node
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/hanzoai/pack/core/generate"
|
|
)
|
|
|
|
const (
|
|
DefaultReactRouterOutputDirectory = "build/client/"
|
|
DefaultReactRouterStartCommand = "react-router-serve ./build/server/index.js"
|
|
ReactRouterConfigJS = "react-router.config.js"
|
|
ReactRouterConfigTS = "react-router.config.ts"
|
|
)
|
|
|
|
var reactRouterSPAConfigRegex = regexp.MustCompile(`(?m)(?:^|[{,])\s*['"]?ssr['"]?\s*:\s*false\b`)
|
|
|
|
func (p *NodeProvider) getReactRouterConfigFileContents(ctx *generate.GenerateContext) string {
|
|
_, contents, _ := ctx.App.ReadFirstFileOf(ReactRouterConfigJS, ReactRouterConfigTS)
|
|
return contents
|
|
}
|
|
|
|
// SPA mode requires an explicit opt-out because React Router enables SSR by default.
|
|
func (p *NodeProvider) isReactRouterSPA(ctx *generate.GenerateContext) bool {
|
|
if !p.isReactRouter(ctx) {
|
|
return false
|
|
}
|
|
|
|
configContent := p.getReactRouterConfigFileContents(ctx)
|
|
return reactRouterSPAConfigRegex.MatchString(configContent)
|
|
}
|
|
|
|
// getReactRouterOutputDirectory attempts to read the output directory from react-router.config.{ts,js} by extracting
|
|
// the buildDirectory option in the config object.
|
|
func (p *NodeProvider) getReactRouterOutputDirectory(ctx *generate.GenerateContext) string {
|
|
configContent := p.getReactRouterConfigFileContents(ctx)
|
|
|
|
if configContent != "" {
|
|
// TODO this field can be an expression `buildDirectory: "build/" + process.env.NODE_ENV,` so we should tighten
|
|
// up the regex here (and in the vite provider, since vite config can have expressions too)
|
|
// `buildDirectory: "custom-directory/"`
|
|
buildDirRegex := regexp.MustCompile(`buildDirectory:\s*['"](.+?)['"]`)
|
|
if matches := buildDirRegex.FindStringSubmatch(configContent); len(matches) > 1 {
|
|
return matches[1]
|
|
}
|
|
}
|
|
|
|
return DefaultReactRouterOutputDirectory
|
|
}
|
|
|
|
func (p *NodeProvider) isReactRouter(ctx *generate.GenerateContext) bool {
|
|
return p.isReactRouterPackage(p.workspace.Root, ctx)
|
|
}
|
|
|
|
// isReactRouterPackage detects React Router packages in workspace environments by checking for:
|
|
// - presence of a react-router.config.{ts,js} file in the package directory
|
|
// - a build script containing "react-router build"
|
|
// - having a dependency on "@react-router/dev"
|
|
// - ensuring a build script exists so there is an actual output directory
|
|
func (p *NodeProvider) isReactRouterPackage(pkg *WorkspacePackage, ctx *generate.GenerateContext) bool {
|
|
if pkg == nil || pkg.PackageJson == nil {
|
|
return false
|
|
}
|
|
|
|
rrConfigJS := ReactRouterConfigJS
|
|
rrConfigTS := ReactRouterConfigTS
|
|
if pkg.Path != "" {
|
|
rrConfigJS = pkg.Path + "/" + ReactRouterConfigJS
|
|
rrConfigTS = pkg.Path + "/" + ReactRouterConfigTS
|
|
}
|
|
|
|
hasRRConfig := ctx.App.HasFile(rrConfigJS) || ctx.App.HasFile(rrConfigTS)
|
|
hasBuildCommand := pkg.PackageJson.HasScript("build")
|
|
hasRRBuildCommand := strings.Contains(strings.ToLower(pkg.PackageJson.GetScript("build")), "react-router build")
|
|
hasRRPackage := pkg.PackageJson.hasDependency("@react-router/dev")
|
|
|
|
return hasBuildCommand && (hasRRConfig || hasRRBuildCommand || hasRRPackage)
|
|
}
|