From 2889b562e64993482bd13fd806af8ed0865bab8b Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 14 Feb 2026 11:52:56 +0900 Subject: refactor: migrate API from GraphQL to REST (TypeSpec/OpenAPI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the entire GraphQL stack (gqlgen, urql, graphql-codegen) with a TypeSpec → OpenAPI 3.x pipeline using oapi-codegen for Go server stubs and openapi-fetch + openapi-typescript for the frontend client. Co-Authored-By: Claude Opus 4.6 --- backend/cmd/serve.go | 56 ++++++++++++++++++---------------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) (limited to 'backend/cmd') diff --git a/backend/cmd/serve.go b/backend/cmd/serve.go index e2d2df5..c65a19f 100644 --- a/backend/cmd/serve.go +++ b/backend/cmd/serve.go @@ -11,22 +11,16 @@ import ( "syscall" "time" - "github.com/99designs/gqlgen/graphql/handler" - "github.com/99designs/gqlgen/graphql/handler/extension" - "github.com/99designs/gqlgen/graphql/handler/lru" - "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/hashicorp/go-multierror" "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" - "github.com/vektah/gqlparser/v2/ast" + "undef.ninja/x/feedaka/api" "undef.ninja/x/feedaka/auth" "undef.ninja/x/feedaka/config" "undef.ninja/x/feedaka/db" "undef.ninja/x/feedaka/feed" - "undef.ninja/x/feedaka/graphql" - "undef.ninja/x/feedaka/graphql/resolver" ) func fetchOneFeed(feedID int64, url string, ctx context.Context, queries *db.Queries) error { @@ -113,41 +107,17 @@ func RunServe(database *sql.DB, cfg *config.Config, publicFS embed.FS) { Filesystem: http.FS(publicFS), })) - // Setup GraphQL server - srv := handler.New(graphql.NewExecutableSchema(graphql.Config{Resolvers: &resolver.Resolver{ + handler := &api.Handler{ DB: database, Queries: queries, SessionConfig: sessionConfig, - }})) - - srv.AddTransport(transport.Options{}) - srv.AddTransport(transport.GET{}) - srv.AddTransport(transport.POST{}) + } - srv.SetQueryCache(lru.New[*ast.QueryDocument](1000)) + strictHandler := api.NewStrictHandler(handler, nil) - srv.Use(extension.Introspection{}) - srv.Use(extension.AutomaticPersistedQuery{ - Cache: lru.New[string](100), - }) - - // GraphQL endpoints with authentication middleware - graphqlGroup := e.Group("/graphql") - graphqlGroup.Use(auth.SessionAuthMiddleware(sessionConfig)) - graphqlGroup.POST("", func(c echo.Context) error { - // Add Echo context to GraphQL context - ctx := context.WithValue(c.Request().Context(), "echo", c) - req := c.Request().WithContext(ctx) - srv.ServeHTTP(c.Response(), req) - return nil - }) - graphqlGroup.GET("", func(c echo.Context) error { - // Add Echo context to GraphQL context - ctx := context.WithValue(c.Request().Context(), "echo", c) - req := c.Request().WithContext(ctx) - srv.ServeHTTP(c.Response(), req) - return nil - }) + // Register REST API routes with auth middleware + apiGroup := e.Group("", auth.SessionAuthMiddleware(sessionConfig), echoContextMiddleware()) + api.RegisterHandlers(apiGroup, strictHandler) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -183,3 +153,15 @@ func RunServe(database *sql.DB, cfg *config.Config, publicFS embed.FS) { } log.Println("Server stopped") } + +// echoContextMiddleware injects echo.Context into request context +// so strict server handlers can access it (needed for session operations) +func echoContextMiddleware() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + ctx := api.WithEchoContext(c.Request().Context(), c) + c.SetRequest(c.Request().WithContext(ctx)) + return next(c) + } + } +} -- cgit v1.3-1-g0d28