Skip to content

Instantly share code, notes, and snippets.

@wesen
Created November 12, 2022 18:33
Show Gist options
  • Select an option

  • Save wesen/0fd6c01a1297e992b90d2dffca368ca4 to your computer and use it in GitHub Desktop.

Select an option

Save wesen/0fd6c01a1297e992b90d2dffca368ca4 to your computer and use it in GitHub Desktop.

I have the current setup to make it easy for a developer to output structured data in many formats. It currently uses a middleware schema that can transform a full Table.

❯ go run ./cmd/cli rum ls-actions --action filters-search --from 2022/11/10 --fields name,query.q,query.,pagination.total_hits --filter query.category --count 50 --table-format markdown  
| name           | query.q            | query.hardiness_zone | query.is_on_sale | query.pp | pagination.total_hits |
| -------------- | ------------------ | -------------------- | ---------------- | -------- | --------------------- |
| filters-search |                    |                      |                  | 2        | 688                   |
| filters-search | Japanese red maple |                      |                  | 3        | 67                    |
| filters-search | Japanese red maple |                      |                  | 4        | 67                    |
| filters-search | Japanese red maple |                      |                  | 5        | 67                    |
| filters-search | Japanese red maple |                      |                  | 4        | 67                    |
| filters-search | Japanese red maple |                      |                  | 3        | 67                    |
| filters-search | Japanese red maple |                      |                  | 2        | 67                    |
| filters-search |                    |                      | On sale          | 2        | 72                    |
| filters-search |                    | 5                    |                  | 26       | 432                   |
| filters-search |                    | 5                    |                  | 25       | 432                   |
| filters-search |                    | 5                    |                  | 24       | 432                   |
| filters-search |                    | 5                    |                  | 23       | 432                   |
| filters-search |                    | 5                    |                  | 22       | 432                   |
| filters-search |                    | 5                    |                  | 21       | 432                   |
| filters-search |                    | 5                    |                  | 20       | 432                   |
| filters-search |                    | 5                    |                  | 19       | 432                   |
| filters-search |                    | 5                    |                  | 18       | 432                   |
| filters-search |                    | 5                    |                  | 17       | 432                   |
| filters-search |                    | 5                    |                  | 16       | 432                   |
| filters-search |                    | 5                    |                  | 15       | 432                   |
| filters-search |                    | 5                    |                  | 14       | 432                   |
| filters-search |                    | 5                    |                  | 13       | 432                   |
| filters-search |                    | 5                    |                  | 12       | 432                   |
| filters-search |                    | 5                    |                  | 13       | 432                   |
| filters-search |                    | 5                    |                  | 12       | 432                   |
| filters-search |                    | 5                    |                  | 11       | 432                   |
| filters-search |                    | 5                    |                  | 10       | 432                   |
| filters-search |                    | 5                    |                  | 9        | 432                   |
| filters-search |                    | 5                    |                  | 8        | 432                   |
| filters-search |                    | 5                    |                  | 7        | 432                   |
| filters-search |                    | 5                    |                  | 6        | 432                   |
| filters-search |                    | 5                    |                  | 5        | 432                   |
| filters-search |                    | 5                    |                  | 4        | 432                   |
| filters-search |                    | 5                    |                  | 3        | 432                   |
| filters-search |                    | 5                    |                  | 2        | 432                   |
| filters-search |                    |                      | On sale          | 4        | 72                    |
| filters-search |                    |                      | On sale          | 3        | 72                    |
| filters-search |                    |                      | On sale          | 2        | 72                    |
| filters-search | burning bush       |                      |                  | 2        | 30                    |
| filters-search |                    |                      | On sale          | 5        | 72                    |
| filters-search |                    |                      | On sale          | 4        | 72                    |
| filters-search |                    |                      | On sale          | 3        | 72                    |
| filters-search |                    |                      | On sale          | 2        | 72                    |
| filters-search |                    |                      | On sale          | 4        | 72                    |
| filters-search |                    |                      | On sale          | 5        | 72                    |
| filters-search |                    |                      | On sale          | 4        | 72                    |
| filters-search |                    |                      | On sale          | 3        | 72                    |
| filters-search |                    |                      | On sale          | 2        | 72                    |
| filters-search |                    |                      |                  | 2        | 151                   |
| filters-search |                    |                      |                  | 3        | 151                   |
type TableName = string
type FieldName = string
type GenericCellValue = interface{}
type MapRow = map[FieldName]GenericCellValue

type Row interface {
	GetFields() []FieldName
	GetValues() MapRow
}

type TableMiddleware interface {
	// Process transform a single row into potential multiple rows split across multiple tables
	Process(table *Table) (*Table, error)
}

type Table struct {
	Columns []FieldName
	Rows    []Row
}
type TableOutputFormatter struct {
	table       *Table
	middlewares []TableMiddleware
	tableFormat string
}

func (tof *TableOutputFormatter) Output() (string, error) {
	for _, middleware := range tof.middlewares {
		newTable, err := middleware.Process(tof.table)
		if err != nil {
			return "", err
		}
		tof.table = newTable
	}
  
  ...
}
			of := cli.NewTableOutputFormatter(tableFormat)
			of.AddMiddleware(cli.NewFlattenObjectMiddleware())
			of.AddMiddleware(cli.NewFieldsFilterMiddleware(fields, filters))
			of.AddMiddleware(cli.NewSortColumnsMiddleware())
			if len(fields) == 0 {
				of.AddMiddleware(cli.NewReorderColumnOrderMiddleware([]cli.FieldName{"name"}))

			} else {
				of.AddMiddleware(cli.NewReorderColumnOrderMiddleware(fields))
			}

			flattenedActions := flattenActions(actions)
			for _, action := range flattenedActions {
				of.AddRow(&cli.SimpleRow{Hash: action})
			}

			s, err := of.Output()

I would like to make it possible to also pass in middlewares that only transform a single row. Should I make middleware a interface{} and do type dispatching?

Of course, I wonder if row processors should be called in front of table processors anyway. It's easy to transform a row processor into a table processor, so that if we need to "interleave" table processors with row processors, we can easily do that.

Row processors are useful for streaming data, where we want to transform rows as they come in, which means that while they can take a table, they only need to return a single row.

I guess I just answered my own question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment