Skip to content

Commit

Permalink
feat(common): Make ParseResult use generic Record type
Browse files Browse the repository at this point in the history
  • Loading branch information
Cobalt0s committed Jan 31, 2025
1 parent f241dbb commit 5365e73
Showing 1 changed file with 54 additions and 8 deletions.
62 changes: 54 additions & 8 deletions common/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,39 @@ import (
)

type (
// NextPageFunc extracts the next page token/URL from the response body.
NextPageFunc func(*ajson.Node) (string, error)
RecordsFunc func(*ajson.Node) ([]map[string]any, error)

// RecordsFunc extracts a list of records as map[string]any from the response body.
RecordsFunc func(*ajson.Node) ([]map[string]any, error)
// NodeRecordsFunc extracts a list of records as ajson.Node from the response body.
NodeRecordsFunc func(*ajson.Node) ([]*ajson.Node, error)

// RawReadRecordFunc processes a raw record, applying additional transformations if needed.
RawReadRecordFunc func(node *ajson.Node) (map[string]any, error)
// MarshalFunc converts a list of map[string]any records into ReadResultRow format.
MarshalFunc func(records []map[string]any, fields []string) ([]ReadResultRow, error)
// NodeMarshalFunc converts a list of ajson.Node records into ReadResultRow format.
NodeMarshalFunc func(records []*ajson.Node, fields []string) ([]ReadResultRow, error)
)

// RawReadRecord defines the types of records that ParseResult can process.
// It determines which callback function is used for parsing.
type RawReadRecord interface {
map[string]any | *ajson.Node
}

// ParseResult parses the response from a provider into a ReadResult. A 2xx return type is assumed.
// The sizeFunc returns the total number of records in the response.
// The recordsFunc returns the records in the response.
// The nextPageFunc returns the URL for the next page of results.
// The marshalFunc is used to structure the data into an array of ReadResultRows.
// The fields are used to populate ReadResultRow.Fields.
func ParseResult(
func ParseResult[R RawReadRecord](
resp *JSONHTTPResponse,
recordsFunc func(*ajson.Node) ([]map[string]any, error),
recordsFunc func(*ajson.Node) ([]R, error),
nextPageFunc func(*ajson.Node) (string, error),
marshalFunc func([]map[string]any, []string) ([]ReadResultRow, error),
marshalFunc func([]R, []string) ([]ReadResultRow, error),
fields datautils.Set[string],
) (*ReadResult, error) {
body, ok := resp.Body()
Expand Down Expand Up @@ -73,11 +91,11 @@ func ParseResult(

// ExtractLowercaseFieldsFromRaw returns a map of fields from a record.
// The fields are all returned in lowercase.
func ExtractLowercaseFieldsFromRaw(fields []string, record map[string]interface{}) map[string]interface{} {
out := make(map[string]interface{}, len(fields))
func ExtractLowercaseFieldsFromRaw(fields []string, record map[string]any) map[string]any {
out := make(map[string]any, len(fields))

// Modify all record keys to lowercase
lowercaseRecord := make(map[string]interface{}, len(record))
lowercaseRecord := make(map[string]any, len(record))
for key, value := range record {
lowercaseRecord[strings.ToLower(key)] = value
}
Expand Down Expand Up @@ -107,7 +125,35 @@ func GetMarshaledData(records []map[string]any, fields []string) ([]ReadResultRo
return data, nil
}

func GetRecordsUnderJSONPath(jsonPath string, nestedPath ...string) RecordsFunc {
// MakeMarshaledDataFunc produces ReadResultRow where raw record differs from the fields.
// This usually includes a set of actions to preprocess, usually to flatten the raw record and then extract
// fields requested by the user.
func MakeMarshaledDataFunc(nodeRecordFunc RawReadRecordFunc) NodeMarshalFunc {
return func(records []*ajson.Node, fields []string) ([]ReadResultRow, error) {
data := make([]ReadResultRow, len(records))

for index, nodeRecord := range records {
raw, err := jsonquery.Convertor.ObjectToMap(nodeRecord)
if err != nil {
return nil, err
}

record, err := nodeRecordFunc(nodeRecord)
if err != nil {
return nil, err
}

data[index] = ReadResultRow{
Fields: ExtractLowercaseFieldsFromRaw(fields, record),
Raw: raw,
}
}

return data, nil
}
}

func GetRecordsUnderJSONPath(jsonPath string, nestedPath ...string) func(*ajson.Node) ([]map[string]any, error) {
return getRecords(false, jsonPath, nestedPath...)
}

Expand Down

0 comments on commit 5365e73

Please sign in to comment.