From 1f8764c3d7ea7b76e6f4bd35bad37244c9754ba9 Mon Sep 17 00:00:00 2001 From: joshmossas Date: Tue, 10 Sep 2024 23:23:58 -0400 Subject: [PATCH] messing with services --- languages/go/go-server/app.go | 105 ++++++---------------- languages/go/go-server/encode_json.go | 9 +- languages/go/go-server/reflect_helpers.go | 18 ++-- languages/go/go-server/type_def.go | 10 ++- playground/go/arri.config.ts | 23 +++-- playground/go/main.go | 15 +--- 6 files changed, 71 insertions(+), 109 deletions(-) diff --git a/languages/go/go-server/app.go b/languages/go/go-server/app.go index d5f3e0f8..9149fdfa 100644 --- a/languages/go/go-server/app.go +++ b/languages/go/go-server/app.go @@ -8,6 +8,8 @@ import ( "os" "reflect" "strings" + + "github.com/iancoleman/strcase" ) type App[TContext any] struct { @@ -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) @@ -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 { @@ -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) { @@ -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, - }) -} diff --git a/languages/go/go-server/encode_json.go b/languages/go/go-server/encode_json.go index 93e6fc40..4701653e 100644 --- a/languages/go/go-server/encode_json.go +++ b/languages/go/go-server/encode_json.go @@ -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, "["...) @@ -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 { @@ -289,7 +289,7 @@ 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 @@ -297,12 +297,13 @@ func nullableTypeToJson(input reflect.Value, target *[]byte, context _EncodingCo 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 } diff --git a/languages/go/go-server/reflect_helpers.go b/languages/go/go-server/reflect_helpers.go index d4c6a6f7..9629b8cf 100644 --- a/languages/go/go-server/reflect_helpers.go +++ b/languages/go/go-server/reflect_helpers.go @@ -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 @@ -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 { @@ -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()) } diff --git a/languages/go/go-server/type_def.go b/languages/go/go-server/type_def.go index 1222df4b..568073ec 100644 --- a/languages/go/go-server/type_def.go +++ b/languages/go/go-server/type_def.go @@ -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"` @@ -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) { @@ -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 } diff --git a/playground/go/arri.config.ts b/playground/go/arri.config.ts index 205b2587..896970af 100644 --- a/playground/go/arri.config.ts +++ b/playground/go/arri.config.ts @@ -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() { @@ -46,6 +50,7 @@ const goServer = defineServerConfig({ return; default: { await closeChildProcess(); + childProcess = undefined; spawnProcess(); } } diff --git a/playground/go/main.go b/playground/go/main.go index 8ccde68d..356d9d60 100644 --- a/playground/go/main.go +++ b/playground/go/main.go @@ -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)