Skip to content

Commit

Permalink
(BEDS-506) change node address type
Browse files Browse the repository at this point in the history
  • Loading branch information
LuccaBitfly committed Sep 23, 2024
1 parent d539c04 commit b8a9648
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 62 deletions.
124 changes: 70 additions & 54 deletions backend/cmd/typescript_converter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package typescript_converter
import (
"flag"
"go/ast"
"iter"
"maps"
"os"
"path/filepath"
"slices"
Expand All @@ -18,6 +20,8 @@ const (
fallbackType = "any"
commonFileName = "common"
lintDisable = "/* eslint-disable */\n"
goFileSuffix = ".go"
tsFileSuffix = ".ts"
)

// Files that should not be converted to TypeScript
Expand Down Expand Up @@ -65,24 +69,23 @@ func Run() {
log.Fatal(nil, "Failed to load package", 0)
}

// Find all common types
// Find all common types, i.e. types that are used in multiple files and must be imported in ts
commonTypes := getCommonTypes(pkgs)
// Find all usages of common types
usage := getCommonUsages(pkgs, commonTypes)

// Generate Tygo for common.go
tygos := []*tygo.Tygo{tygo.New(getTygoConfig(out, commonFileName, ""))}
// Generate Tygo for each file
for file, typesUsed := range usage {
importStr := ""
// Find imports (usages of common types) for each file
imports := getImports(pkgs, commonTypes)

var configs []*tygo.Tygo
// Generate Tygo config for each file
for fileName, typesUsed := range imports {
var importStr string
if len(typesUsed) > 0 {
importStr = "import type { " + strings.Join(typesUsed, ", ") + " } from './" + commonFileName + "'\n"
importStr = "import type { " + strings.Join(slices.Collect(maps.Keys(typesUsed)), ", ") + " } from './" + commonFileName + "'\n"
}
tygos = append(tygos, tygo.New(getTygoConfig(out, file, importStr)))
configs = append(configs, tygo.New(getTygoConfig(out, fileName, importStr)))
}

// Generate TypeScript
for _, tygo := range tygos {
for _, tygo := range configs {
err := tygo.Generate()
if err != nil {
log.Fatal(err, "Failed to generate TypeScript", 0)
Expand All @@ -93,7 +96,7 @@ func Run() {
}

func deleteFiles(out string) error {
files, err := filepath.Glob(out + "*.ts")
files, err := filepath.Glob(out + "*" + tsFileSuffix)
if err != nil {
return err
}
Expand All @@ -106,68 +109,81 @@ func deleteFiles(out string) error {
return nil
}

func getTygoConfig(out, file, frontmatter string) *tygo.Config {
func getTygoConfig(outDir, fileName, frontmatter string) *tygo.Config {
return &tygo.Config{
Packages: []*tygo.PackageConfig{
{
Path: packagePath,
TypeMappings: typeMappings,
FallbackType: fallbackType,
IncludeFiles: []string{file + ".go"},
OutputPath: out + file + ".ts",
IncludeFiles: []string{fileName + goFileSuffix},
OutputPath: outDir + fileName + tsFileSuffix,
Frontmatter: lintDisable + frontmatter,
},
},
}
}

// Parse common.go to find all common types
func getCommonTypes(pkgs []*packages.Package) map[string]bool {
commonTypes := make(map[string]bool)
for _, pkg := range pkgs {
for _, file := range pkg.Syntax {
filename := strings.TrimSuffix(filepath.Base(pkg.Fset.File(file.Pos()).Name()), ".go")
if filepath.Base(filename) != commonFileName {
continue
}
ast.Inspect(file, func(n ast.Node) bool {
if typeSpec, ok := n.(*ast.TypeSpec); ok {
commonTypes[typeSpec.Name.Name] = true
// Iterate over all file names and files in the packages
func allFiles(pkgs []*packages.Package) iter.Seq2[string, *ast.File] {
return func(yield func(string, *ast.File) bool) {
for _, pkg := range pkgs {
for _, file := range pkg.Syntax {
fileName := filepath.Base(pkg.Fset.File(file.Pos()).Name())
if !yield(fileName, file) {
return
}
return true
})
return commonTypes
}
}
}
return nil
}

// Parse common.go to find all common types
func getCommonTypes(pkgs []*packages.Package) map[string]struct{} {
var commonFile *ast.File
// find common file
for fileName, file := range allFiles(pkgs) {
fileName = strings.TrimSuffix(fileName, goFileSuffix)
if filepath.Base(fileName) == commonFileName {
commonFile = file
break
}
}
if commonFile == nil {
log.Fatal(nil, "common.go not found", 0)
}
commonTypes := make(map[string]struct{})
// iterate over all types in common file and add them to the map
for node := range ast.Preorder(commonFile) {
if typeSpec, ok := node.(*ast.TypeSpec); ok {
commonTypes[typeSpec.Name.Name] = struct{}{}
}
}
return commonTypes
}

// Parse all files to find used common types for each file
func getCommonUsages(pkgs []*packages.Package, commonTypes map[string]bool) map[string][]string {
usage := make(map[string][]string) // Map from file to list of commonTypes used
for _, pkg := range pkgs {
for _, file := range pkg.Syntax {
filename := strings.TrimSuffix(filepath.Base(pkg.Fset.File(file.Pos()).Name()), ".go")
if filepath.Base(filename) == commonFileName || slices.Contains(ignoredFiles, filename) {
// Returns a map with file name as key and a set of common types used in the file as value
func getImports(pkgs []*packages.Package, commonTypes map[string]struct{}) map[string]map[string]struct{} {
imports := make(map[string]map[string]struct{}) // Map from file to set of commonTypes used
imports[commonFileName] = make(map[string]struct{}) // Add common file to map with empty set
for fileName, file := range allFiles(pkgs) {
fileName = strings.TrimSuffix(fileName, goFileSuffix)
if filepath.Base(fileName) == commonFileName || slices.Contains(ignoredFiles, fileName) {
continue
}
imports[fileName] = make(map[string]struct{})
// iterate over all struct fields in the file
for node := range ast.Preorder(file) {
ident, ok := node.(*ast.Ident)
if !ok {
continue
}
if _, exists := usage[filename]; !exists {
usage[filename] = make([]string, 0)
if _, ok := commonTypes[ident.Name]; ok {
// field is a common type, add it to the map
imports[fileName][ident.Name] = struct{}{}
}
ast.Inspect(file, func(n ast.Node) bool {
ident, ok := n.(*ast.Ident)
if !ok {
return true
}
if !commonTypes[ident.Name] {
return true
}
if !slices.Contains(usage[filename], ident.Name) {
usage[filename] = append(usage[filename], ident.Name)
}
return true
})
}
}
return usage
return imports
}
8 changes: 4 additions & 4 deletions backend/pkg/api/types/notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ type InternalGetUserNotificationClientsResponse ApiPagingResponse[NotificationCl
// ------------------------------------------------------------
// Rocket Pool Table
type NotificationRocketPoolTableRow struct {
Timestamp int64 `json:"timestamp"`
EventType string `json:"event_type" tstype:"'reward_round' | 'collateral_max' | 'collateral_min'" faker:"oneof: reward_round, collateral_max, collateral_min"`
AlertValue float64 `json:"alert_value,omitempty"` // only for some notification types, e.g. max collateral
NodeAddress Hash `json:"node_address"`
Timestamp int64 `json:"timestamp"`
EventType string `json:"event_type" tstype:"'reward_round' | 'collateral_max' | 'collateral_min'" faker:"oneof: reward_round, collateral_max, collateral_min"`
AlertValue float64 `json:"alert_value,omitempty"` // only for some notification types, e.g. max collateral
Node Address `json:"node"`
}

type InternalGetUserNotificationRocketPoolResponse ApiPagingResponse[NotificationRocketPoolTableRow]
Expand Down
4 changes: 2 additions & 2 deletions frontend/types/api/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Code generated by tygo. DO NOT EDIT.
/* eslint-disable */
import type { ApiDataResponse, ApiPagingResponse, IndexBlocks, Address, Hash } from './common'
import type { Hash, ApiDataResponse, ApiPagingResponse, IndexBlocks, Address } from './common'

//////////
// source: notifications.go
Expand Down Expand Up @@ -119,7 +119,7 @@ export interface NotificationRocketPoolTableRow {
timestamp: number /* int64 */;
event_type: 'reward_round' | 'collateral_max' | 'collateral_min';
alert_value?: number /* float64 */; // only for some notification types, e.g. max collateral
node_address: Hash;
node: Address;
}
export type InternalGetUserNotificationRocketPoolResponse = ApiPagingResponse<NotificationRocketPoolTableRow>;
/**
Expand Down
2 changes: 1 addition & 1 deletion frontend/types/api/user.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Code generated by tygo. DO NOT EDIT.
/* eslint-disable */
import type { ApiDataResponse, ChartHistorySeconds } from './common'
import type { ChartHistorySeconds, ApiDataResponse } from './common'

//////////
// source: user.go
Expand Down
2 changes: 1 addition & 1 deletion frontend/types/api/validator_dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Code generated by tygo. DO NOT EDIT.
/* eslint-disable */
import type { ValidatorStateCounts, PeriodicValues, ClElValue, ChartHistorySeconds, ApiDataResponse, StatusCount, ApiPagingResponse, Luck, ChartData, ValidatorHistoryDuties, Address, PubKey, Hash, PercentageDetails } from './common'
import type { ApiDataResponse, Luck, PubKey, ValidatorStateCounts, PeriodicValues, ValidatorHistoryDuties, Address, ChartData, Hash, PercentageDetails, ClElValue, ChartHistorySeconds, StatusCount, ApiPagingResponse } from './common'

//////////
// source: validator_dashboard.go
Expand Down

0 comments on commit b8a9648

Please sign in to comment.