Skip to content

Commit

Permalink
messing with services
Browse files Browse the repository at this point in the history
  • Loading branch information
joshmossas committed Sep 11, 2024
1 parent 17188aa commit 1f8764c
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 109 deletions.
105 changes: 29 additions & 76 deletions languages/go/go-server/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"os"
"reflect"
"strings"

"github.com/iancoleman/strcase"
)

type App[TContext any] struct {
Expand Down Expand Up @@ -236,23 +238,27 @@ type RpcOptions struct {
IsDeprecated bool
}

func rpc[TParams, TResponse, TContext any](app *App[TContext], options *RpcOptions, handler func(TParams, TContext) (TResponse, RpcError)) {
func rpc[TParams, TResponse, TContext any](app *App[TContext], serviceName Option[string], options Option[RpcOptions], handler func(TParams, TContext) (TResponse, RpcError)) {
handlerType := reflect.TypeOf(handler)
rpcSchema, rpcError := ToRpcDef(handler, ArriHttpRpcOptions{})
rpcSchema.Http.Path = app.Options.RpcRoutePrefix + rpcSchema.Http.Path
if serviceName.IsSome() {
rpcSchema.Http.Path = app.Options.RpcRoutePrefix + "/" + strcase.ToKebab(serviceName.Value) + rpcSchema.Http.Path
} else {
rpcSchema.Http.Path = app.Options.RpcRoutePrefix + rpcSchema.Http.Path
}
if rpcError != nil {
panic(rpcError)
}
if options != nil {
rpcSchema.Http.Method = options.Method
if len(options.Path) > 0 {
rpcSchema.Http.Path = app.Options.RpcRoutePrefix + options.Path
if options.IsSome() {
rpcSchema.Http.Method = options.Value.Method
if len(options.Value.Path) > 0 {
rpcSchema.Http.Path = app.Options.RpcRoutePrefix + options.Value.Path
}
if len(options.Description) > 0 {
rpcSchema.Http.Description = Some(options.Description)
if len(options.Value.Description) > 0 {
rpcSchema.Http.Description = Some(options.Value.Description)
}
if options.IsDeprecated {
rpcSchema.Http.IsDeprecated = Some(options.IsDeprecated)
if options.Value.IsDeprecated {
rpcSchema.Http.IsDeprecated = Some(options.Value.IsDeprecated)
}
}
params := reflect.TypeOf(handler).In(0)
Expand All @@ -263,6 +269,9 @@ func rpc[TParams, TResponse, TContext any](app *App[TContext], options *RpcOptio
responseSchema, _ := typeToTypeDef(response.Elem(), typeDefContext)
*app.Definitions = __updateAOrderedMap__(*app.Definitions, __orderedMapEntry__[TypeDef]{Key: responseSchema.Metadata.Unwrap().Id, Value: *responseSchema})
rpcName := rpcNameFromFunctionName(GetFunctionName(handler))
if serviceName.IsSome() {
rpcName = serviceName.Value + "." + rpcName
}
*app.Procedures = __updateAOrderedMap__(*app.Procedures, __orderedMapEntry__[RpcDef]{Key: rpcName, Value: *rpcSchema})
onRequest := app.Options.OnRequest
if onRequest == nil {
Expand Down Expand Up @@ -355,11 +364,19 @@ func rpc[TParams, TResponse, TContext any](app *App[TContext], options *RpcOptio
}

func Rpc[TParams, TResponse, TContext any](app *App[TContext], handler func(TParams, TContext) (TResponse, RpcError)) {
rpc(app, nil, handler)
rpc(app, None[string](), None[RpcOptions](), handler)
}

func RpcWithOptions[TParams, TResponse, TContext any](app *App[TContext], options RpcOptions, handler func(TParams, TContext) (TResponse, RpcError)) {
rpc(app, &options, handler)
rpc(app, None[string](), Some(options), handler)
}

func ServiceRpc[TParams, TResponse, TContext any](app *App[TContext], serviceName string, handler func(TParams, TContext) (TResponse, RpcError)) {
rpc(app, Some(serviceName), None[RpcOptions](), handler)
}

func ServiceRpcWithOptions[TParams, TResponse, TContext any](app *App[TContext], serviceName string, options RpcOptions, handler func(TParams, TContext) (TResponse, RpcError)) {
rpc(app, Some(serviceName), Some(options), handler)
}

func RegisterDef[TContext any](app *App[TContext], input any) {
Expand All @@ -372,67 +389,3 @@ func RegisterDef[TContext any](app *App[TContext], input any) {
Value: *def,
})
}

func RegisterService[TContext any](app *App[TContext], input Service) {

}

type Service struct {
Name string
Procedures []__orderedMapEntry__[RpcDef]
Definitions []__orderedMapEntry__[TypeDef]
rawProcedures []any
}

func NewService(name string) Service {
return Service{
Name: name,
Procedures: []__orderedMapEntry__[RpcDef]{},
Definitions: []__orderedMapEntry__[TypeDef]{},
rawProcedures: []any{},
}
}

func ServiceRpc[TParams, TResponse, TContext any](service *Service, handler func(TParams, TContext) (TResponse, RpcError)) {
if service.Procedures == nil {
service.Procedures = []__orderedMapEntry__[RpcDef]{}
}
def, defErr := ToRpcDef(handler, ArriHttpRpcOptions{})
if defErr != nil {
panic(defErr)
}
service.rawProcedures = append(service.rawProcedures, handler)
rpcName := rpcNameFromFunctionName(GetFunctionName(handler))
__updateAOrderedMap__(service.Procedures, __orderedMapEntry__[RpcDef]{
Key: rpcName,
Value: *def,
})
}

func ServiceRpcWithOptions[TParams, TResponse, TContext any](service *Service, options RpcOptions, handler func(TParams, TContext) (TResponse, RpcError)) {
if service.Procedures == nil {
service.Procedures = []__orderedMapEntry__[RpcDef]{}
}
def, defErr := ToRpcDef(handler, ArriHttpRpcOptions{})
if defErr != nil {
panic(defErr)
}
if len(options.Method) > 0 {
def.Http.Method = strings.ToLower(options.Method)
}
if len(options.Path) > 0 {
def.Http.Path = options.Path
}
if len(options.Description) > 0 {
def.Http.Description = Some(options.Description)
}
if options.IsDeprecated {
def.Http.IsDeprecated = Some(true)
}
service.rawProcedures = append(service.rawProcedures, handler)
rpcName := rpcNameFromFunctionName(GetFunctionName(handler))
service.Procedures = __updateAOrderedMap__(service.Procedures, __orderedMapEntry__[RpcDef]{
Key: rpcName,
Value: *def,
})
}
9 changes: 5 additions & 4 deletions languages/go/go-server/encode_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func orderedMapEntryToJson(input reflect.Value, target *[]byte, context _Encodin

func listToJson(input reflect.Value, target *[]byte, context _EncodingContext) error {
slice := input.Slice(0, input.Len())
if strings.Contains(input.Type().Elem().Name(), "__aOrderedMapEntry__[") {
if strings.Contains(input.Type().Elem().Name(), "__orderedMapEntry__[") {
return orderedMapEntryToJson(input, target, context)
}
*target = append(*target, "["...)
Expand Down Expand Up @@ -269,7 +269,7 @@ func structToJson(input reflect.Value, target *[]byte, context _EncodingContext)
}
isNullable := isNullableType(fieldType)
if isNullable {
*target = append(*target, "\""+key+"\":null"...)
*target = append(*target, "\""+key+"\":"...)
return nullableTypeToJson(field, target, ctx)
}
if numFields > 0 {
Expand All @@ -289,20 +289,21 @@ func structToJson(input reflect.Value, target *[]byte, context _EncodingContext)
func nullableTypeToJson(input reflect.Value, target *[]byte, context _EncodingContext) error {
innerVal := extractNullableValue(&input)
if innerVal != nil {
return typeToJson(input, target, context)
return typeToJson(*innerVal, target, context)
}
*target = append(*target, "null"...)
return nil
}

func optionalTypeToJson(input reflect.Value, target *[]byte, context _EncodingContext, keyName string, hasPreviousKeys bool) (didAdd bool, err error) {
innerVal := extractOptionalValue(&input)
fmt.Println("OPTIONAL VAL", innerVal)
if innerVal != nil {
if hasPreviousKeys {
*target = append(*target, ","...)
}
*target = append(*target, "\""+keyName+"\":"...)
return true, typeToJson(input, target, context)
return true, typeToJson(*innerVal, target, context)
}
return false, nil
}
Expand Down
18 changes: 13 additions & 5 deletions languages/go/go-server/reflect_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import (
)

func extractOptionalValue(input *reflect.Value) *reflect.Value {
if input.IsZero() {
return nil
}
kind := input.Kind()
if kind == reflect.Ptr {
if input.IsNil() {
return nil
}
el := input.Elem()
return &el
}
if input.IsZero() {
return nil
}
isSet := input.FieldByName("IsSet").Bool()
if !isSet {
return nil
Expand All @@ -23,7 +26,11 @@ func extractOptionalValue(input *reflect.Value) *reflect.Value {
}

func isOptionalType(input reflect.Type) bool {
return input.Kind() == reflect.Ptr || input.Kind() == reflect.Struct && strings.Contains(input.Name(), "Option[")
return (input.Kind() == reflect.Ptr &&
input.Kind() == reflect.Struct &&
strings.Contains(input.Name(), "Option[")) ||
input.Kind() == reflect.Struct &&
strings.Contains(input.Name(), "Option[")
}

func extractNullableValue(input *reflect.Value) *reflect.Value {
Expand All @@ -36,5 +43,6 @@ func extractNullableValue(input *reflect.Value) *reflect.Value {
}

func isNullableType(input reflect.Type) bool {
return input.Kind() == reflect.Struct && input != nil && strings.Contains(input.Name(), "Nullable[")
return (input.Kind() == reflect.Struct && input != nil && strings.Contains(input.Name(), "Nullable[")) ||
input.Kind() == reflect.Ptr && isNullableType(input.Elem())
}
10 changes: 6 additions & 4 deletions languages/go/go-server/type_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ type TypeDef struct {
Nullable Option[bool] `key:"nullable"`
Type Option[Type] `key:"type"`
Enum Option[[]string] `key:"enum"`
Elements *TypeDef `key:"elements"`
Elements *Option[TypeDef] `key:"elements"`
Properties Option[[]__orderedMapEntry__[TypeDef]] `key:"properties"`
OptionalProperties Option[[]__orderedMapEntry__[TypeDef]] `key:"optionalProperties"`
Strict Option[bool] `key:"strict"`
Values *TypeDef `key:"values"`
Values *Option[TypeDef] `key:"values"`
Discriminator Option[string] `key:"discriminator"`
Mapping Option[map[string]TypeDef] `key:"mapping"`
Ref Option[string] `key:"ref"`
Expand Down Expand Up @@ -476,7 +476,8 @@ func arrayToTypeDef(input reflect.Type, context _TypeDefContext) (*TypeDef, erro
if err != nil {
return nil, err
}
return &TypeDef{Elements: subTypeResult}, nil
r := Some(*subTypeResult)
return &TypeDef{Elements: &r}, nil
}

func mapToTypeDef(input reflect.Type, context _TypeDefContext) (*TypeDef, error) {
Expand Down Expand Up @@ -507,5 +508,6 @@ func mapToTypeDef(input reflect.Type, context _TypeDefContext) (*TypeDef, error)
if err != nil {
return nil, err
}
return &TypeDef{Values: subTypeResult}, nil
r := Some(*subTypeResult)
return &TypeDef{Values: &r}, nil
}
23 changes: 14 additions & 9 deletions playground/go/arri.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ const goServer = defineServerConfig({
const watcher = chokidar.watch(["**/*.go"], { ignoreInitial: true });
let childProcess: ChildProcess | undefined;
async function spawnProcess() {
execSync("go build -o .output/server", {
stdio: "inherit",
});
childProcess = spawn(
".output/server",
["--def-out=.output/__definition.json"],
{
try {
execSync("go build -o .output/server", {
stdio: "inherit",
},
);
});
childProcess = spawn(
".output/server",
["--def-out=.output/__definition.json"],
{
stdio: "inherit",
},
);
} catch (err) {
logger.error(err);
}
}

async function closeChildProcess() {
Expand All @@ -46,6 +50,7 @@ const goServer = defineServerConfig({
return;
default: {
await closeChildProcess();
childProcess = undefined;
spawnProcess();
}
}
Expand Down
15 changes: 4 additions & 11 deletions playground/go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,14 @@ func main() {
}),
)
// register an RPC
arri.RpcWithOptions(
arri.ServiceRpcWithOptions(
&app,
"users",
arri.RpcOptions{Method: arri.HttpMethodGet},
GetUser,
)
arri.Rpc(&app, DeleteUser)
// register an RPC with a custom HTTP method and path
arri.RpcWithOptions(
&app,
arri.RpcOptions{
Method: arri.HttpMethodPatch,
Path: "/update-user",
},
UpdateUser,
)
arri.ServiceRpc(&app, "users", DeleteUser)
arri.ServiceRpc(&app, "users", UpdateUser)
appErr := app.Run(arri.RunOptions{})
if appErr != nil {
log.Fatal(appErr)
Expand Down

0 comments on commit 1f8764c

Please sign in to comment.