mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
channel: master
version: 1.2.0
source-ref: D:\code\open_source\ant-chrome master
source-commit: f3d7ec5
merged-public-base: 3d264eb
111 lines
3.2 KiB
Go
111 lines
3.2 KiB
Go
package automation
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"path"
|
|
)
|
|
|
|
func validateImportedBundle(record ScriptRecord, files []ImportedBundleFile) error {
|
|
fileIndex, err := buildImportedBundleFileIndex(record, files)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
entryFile, err := normalizeBundleFilePath(record.EntryFile)
|
|
if err != nil {
|
|
return fmt.Errorf("脚本入口文件无效: %w", err)
|
|
}
|
|
if !isSupportedScriptModuleFile(entryFile) {
|
|
return fmt.Errorf("脚本入口文件必须是 .js / .cjs / .mjs,当前为 %s", path.Ext(entryFile))
|
|
}
|
|
|
|
if err := validateImportedPackageJSONFiles(fileIndex); err != nil {
|
|
return err
|
|
}
|
|
return validateReachableScriptModules(entryFile, fileIndex)
|
|
}
|
|
|
|
func buildImportedBundleFileIndex(record ScriptRecord, files []ImportedBundleFile) (map[string][]byte, error) {
|
|
fileIndex := make(map[string][]byte, len(files)+1)
|
|
for _, file := range files {
|
|
relativePath, err := normalizeBundleFilePath(file.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if containsNodeModulesPath(relativePath) {
|
|
return nil, fmt.Errorf("脚本包不能包含 node_modules,请改成自包含脚本包")
|
|
}
|
|
fileIndex[relativePath] = file.Content
|
|
}
|
|
|
|
entryFile, err := normalizeBundleFilePath(record.EntryFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if _, exists := fileIndex[entryFile]; !exists {
|
|
fileIndex[entryFile] = []byte(record.ScriptText)
|
|
}
|
|
return fileIndex, nil
|
|
}
|
|
|
|
func validateImportedPackageJSONFiles(fileIndex map[string][]byte) error {
|
|
for filePath, content := range fileIndex {
|
|
if path.Base(filePath) != "package.json" {
|
|
continue
|
|
}
|
|
|
|
var pkg importedPackageJSON
|
|
if err := json.Unmarshal(content, &pkg); err != nil {
|
|
return fmt.Errorf("%s 不是合法的 package.json: %w", filePath, err)
|
|
}
|
|
|
|
switch {
|
|
case len(pkg.Dependencies) > 0:
|
|
return fmt.Errorf("%s 包含 dependencies,当前脚本包不支持外部 npm 依赖", filePath)
|
|
case len(pkg.DevDependencies) > 0:
|
|
return fmt.Errorf("%s 包含 devDependencies,当前脚本包不支持依赖安装流程", filePath)
|
|
case len(pkg.PeerDependencies) > 0:
|
|
return fmt.Errorf("%s 包含 peerDependencies,当前脚本包不支持外部 npm 依赖", filePath)
|
|
case len(pkg.OptionalDependencies) > 0:
|
|
return fmt.Errorf("%s 包含 optionalDependencies,当前脚本包不支持外部 npm 依赖", filePath)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateReachableScriptModules(entryFile string, fileIndex map[string][]byte) error {
|
|
queue := []string{entryFile}
|
|
visited := make(map[string]struct{}, len(fileIndex))
|
|
|
|
for len(queue) > 0 {
|
|
current := queue[len(queue)-1]
|
|
queue = queue[:len(queue)-1]
|
|
|
|
if _, seen := visited[current]; seen {
|
|
continue
|
|
}
|
|
visited[current] = struct{}{}
|
|
|
|
content, exists := fileIndex[current]
|
|
if !exists {
|
|
return fmt.Errorf("脚本入口 %s 不存在", current)
|
|
}
|
|
if !isSupportedScriptModuleFile(current) {
|
|
continue
|
|
}
|
|
|
|
for _, specifier := range extractImportedModuleSpecifiers(string(content)) {
|
|
resolved, err := validateImportedSpecifier(current, specifier, fileIndex)
|
|
if err != nil {
|
|
return fmt.Errorf("%s: %w", current, err)
|
|
}
|
|
if resolved != "" && isSupportedScriptModuleFile(resolved) {
|
|
queue = append(queue, resolved)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|