Skip to content

Commit

Permalink
Enable GraphQL endpoints to be defined in the manifest (#464)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattjohnsonpint authored Oct 15, 2024
1 parent b0f3605 commit 1b06fb5
Show file tree
Hide file tree
Showing 48 changed files with 604 additions and 294 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ In previous releases, the name "Hypermode" was used for all three._
- Update Sentry telemetry collection rules [#460](https://github.com/hypermodeinc/modus/pull/460)
- Fix entry alignment issue with AssemblyScript maps [#461](https://github.com/hypermodeinc/modus/pull/461)
- Update to use new Modus manifest [#462](https://github.com/hypermodeinc/modus/pull/462)
- Enable GraphQL endpoints to be defined in the manifest [#464](https://github.com/hypermodeinc/modus/pull/464)

## 2024-10-02 - Version 0.12.7

Expand Down
6 changes: 1 addition & 5 deletions cspell.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"version": "0.2",
"language": "en",
"flagWords": [
"hte",
"teh"
],
"flagWords": ["hte", "teh"],
"words": [
"abstractlogger",
"Albus",
Expand Down Expand Up @@ -71,7 +68,6 @@
"hostfns",
"hostfunctions",
"httpclient",
"hujson",
"hypbuild",
"hypermode",
"Hypermode",
Expand Down
4 changes: 3 additions & 1 deletion lib/manifest/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

package manifest

type ConnectionType string

type ConnectionInfo interface {
ConnectionName() string
ConnectionType() string
ConnectionType() ConnectionType
Hash() string
Variables() []string
}
12 changes: 6 additions & 6 deletions lib/manifest/dgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@

package manifest

const ConnectionTypeDgraph string = "dgraph"
const ConnectionTypeDgraph ConnectionType = "dgraph"

type DgraphConnectionInfo struct {
Name string `json:"-"`
Type string `json:"type"`
GrpcTarget string `json:"grpcTarget"`
Key string `json:"key"`
Name string `json:"-"`
Type ConnectionType `json:"type"`
GrpcTarget string `json:"grpcTarget"`
Key string `json:"key"`
}

func (info DgraphConnectionInfo) ConnectionName() string {
return info.Name
}

func (info DgraphConnectionInfo) ConnectionType() string {
func (info DgraphConnectionInfo) ConnectionType() ConnectionType {
return info.Type
}

Expand Down
48 changes: 48 additions & 0 deletions lib/manifest/endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2024 Hypermode Inc.
* Licensed under the terms of the Apache License, Version 2.0
* See the LICENSE file that accompanied this code for further details.
*
* SPDX-FileCopyrightText: 2024 Hypermode Inc. <hello@hypermode.com>
* SPDX-License-Identifier: Apache-2.0
*/

package manifest

type EndpointInfo interface {
EndpointName() string
EndpointType() EndpointType
EndpointAuth() EndpointAuthType
}

type EndpointType string

const (
EndpointTypeGraphQL EndpointType = "graphql"
)

type EndpointAuthType string

const (
EndpointAuthNone EndpointAuthType = "none"
EndpointAuthBearerToken EndpointAuthType = "bearer-token"
)

type GraphqlEndpointInfo struct {
Name string `json:"-"`
Type EndpointType `json:"type"`
Path string `json:"path"`
Auth EndpointAuthType `json:"auth"`
}

func (e GraphqlEndpointInfo) EndpointName() string {
return e.Name
}

func (e GraphqlEndpointInfo) EndpointType() EndpointType {
return e.Type
}

func (e GraphqlEndpointInfo) EndpointAuth() EndpointAuthType {
return e.Auth
}
2 changes: 1 addition & 1 deletion lib/manifest/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ go 1.23.0

require (
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a
github.com/tidwall/gjson v1.18.0
github.com/tidwall/jsonc v0.3.2
)

require (
Expand Down
6 changes: 2 additions & 4 deletions lib/manifest/go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/jsonc v0.3.2 h1:ZTKrmejRlAJYdn0kcaFqRAKlxxFIC21pYq8vLa4p2Wc=
github.com/tidwall/jsonc v0.3.2/go.mod h1:dw+3CIxqHi+t8eFSpzzMlcVYxKp08UP5CD8/uSFCyJE=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
Expand Down
6 changes: 3 additions & 3 deletions lib/manifest/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import (
"regexp"
)

const ConnectionTypeHTTP string = "http"
const ConnectionTypeHTTP ConnectionType = "http"

var templateRegex = regexp.MustCompile(`{{\s*(?:base64\((.+?):(.+?)\)|(.+?))\s*}}`)

type HTTPConnectionInfo struct {
Name string `json:"-"`
Type string `json:"type"`
Type ConnectionType `json:"type"`
Endpoint string `json:"endpoint"`
BaseURL string `json:"baseURL"`
Headers map[string]string `json:"headers"`
Expand All @@ -30,7 +30,7 @@ func (info HTTPConnectionInfo) ConnectionName() string {
return info.Name
}

func (info HTTPConnectionInfo) ConnectionType() string {
func (info HTTPConnectionInfo) ConnectionType() ConnectionType {
return info.Type
}

Expand Down
64 changes: 37 additions & 27 deletions lib/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
"fmt"

"github.com/santhosh-tekuri/jsonschema/v5"
"github.com/tailscale/hujson"
"github.com/tidwall/gjson"
"github.com/tidwall/jsonc"
)

// This version should only be incremented if there are major breaking changes
Expand All @@ -30,6 +30,7 @@ var schemaContent string

type Manifest struct {
Version int `json:"-"`
Endpoints map[string]EndpointInfo `json:"endpoints"`
Models map[string]ModelInfo `json:"models"`
Connections map[string]ConnectionInfo `json:"connections"`
Collections map[string]CollectionInfo `json:"collections"`
Expand Down Expand Up @@ -63,36 +64,33 @@ func ValidateManifest(content []byte) error {
return err
}

if content, err := standardizeJSON(content); err != nil {
return fmt.Errorf("failed to standardize manifest: %w", err)
} else {
var v interface{}
if err := json.Unmarshal(content, &v); err != nil {
return fmt.Errorf("failed to deserialize manifest: %w", err)
}
if err := sch.Validate(v); err != nil {
return fmt.Errorf("failed to validate manifest: %w", err)
}
content = jsonc.ToJSONInPlace(content)

var v interface{}
if err := json.Unmarshal(content, &v); err != nil {
return fmt.Errorf("failed to deserialize manifest: %w", err)
}
if err := sch.Validate(v); err != nil {
return fmt.Errorf("failed to validate manifest: %w", err)
}

return nil
}

func ReadManifest(content []byte) (*Manifest, error) {
data, err := standardizeJSON(content)
if err != nil {
return nil, err
}

content = jsonc.ToJSONInPlace(content)

var manifest Manifest
if err := parseManifestJson(data, &manifest); err != nil {
if err := parseManifestJson(content, &manifest); err != nil {
return nil, fmt.Errorf("failed to parse manifest: %w", err)
}
return &manifest, nil
}

func parseManifestJson(data []byte, manifest *Manifest) error {
var m struct {
Endpoints map[string]json.RawMessage `json:"endpoints"`
Models map[string]ModelInfo `json:"models"`
Connections map[string]json.RawMessage `json:"connections"`
Collections map[string]CollectionInfo `json:"collections"`
Expand All @@ -115,14 +113,36 @@ func parseManifestJson(data []byte, manifest *Manifest) error {
manifest.Collections[key] = collection
}

// Parse the endpoints by type
manifest.Endpoints = make(map[string]EndpointInfo, len(m.Endpoints))
for name, rawEp := range m.Endpoints {
t := gjson.GetBytes(rawEp, "type")
if !t.Exists() {
return fmt.Errorf("missing type for endpoint [%s]", name)
}
epType := EndpointType(t.String())

switch epType {
case EndpointTypeGraphQL:
var info GraphqlEndpointInfo
if err := json.Unmarshal(rawEp, &info); err != nil {
return fmt.Errorf("failed to parse graphql endpoint [%s]: %w", name, err)
}
info.Name = name
manifest.Endpoints[name] = info
default:
return fmt.Errorf("unknown type [%s] for endpoint [%s]", epType, name)
}
}

// Parse the connections by type
manifest.Connections = make(map[string]ConnectionInfo, len(m.Connections))
for name, rawCon := range m.Connections {
t := gjson.GetBytes(rawCon, "type")
if !t.Exists() {
return fmt.Errorf("missing type for connection [%s]", name)
}
conType := t.String()
conType := ConnectionType(t.String())

switch conType {
case ConnectionTypeHTTP:
Expand Down Expand Up @@ -153,13 +173,3 @@ func parseManifestJson(data []byte, manifest *Manifest) error {

return nil
}

// standardizeJSON removes comments and trailing commas to make the JSON valid
func standardizeJSON(b []byte) ([]byte, error) {
ast, err := hujson.Parse(b)
if err != nil {
return b, err
}
ast.Standardize()
return ast.Pack(), nil
}
Loading

0 comments on commit 1b06fb5

Please sign in to comment.