8 ms·
Show HN: REST Alternative to GraphQL and tRPC
- moltar 3y agoIt’s a really good solution. Wish it would use undicci/fetch instead of axios though.
- jimiljojo 3y agoWhen I see API tools, I am bummed to see the diminished focused on API clients. Particularly client experience (not the libs). Its all about REST vs GraphQL vs gRPC vs Async API vs native SDKs. It's all about how to make it easier or faster for developers to build these APIs. Never about, how to make this API best for the API client. That is what matters the most. Focus on clients and can they get the job done. If it does, no need to over engineer!
- mikercampbell 3y agoDid you ever play with Realm.io? It had a ton of promise, and I loved the idea of “OOP API”, where objects write themselves to the database from your app. My opinion is more nuanced now, but still it’s super cool.
- notpushkin 3y agoCongrats on the launch! How does this compare to other solutions, like https://openapi-ts.pages.dev/ https://openapi-ts.pages.dev/?
- anttiviljami 3y agoGood idea to add to the comparisons page! The openapi-typescript package is a library for generating types from openapi spec, similar to the openapicmd typegen command provided by openapi-stack. The new openapi-typescript-fetch seems similar to openapi-client-axios, but using fetch instead of axios for a more lightweight approach. Both libraries are great and well aligned with goals of openapi-stack! In addition to type generation and consuming APIs, https://openapistack.co https://openapistack.co provides tools for building and mocking API backends with the openapi-backend library, as well as a general cli tool to work with openapi files and invoke APIs via the command line. The core mission of https://openapistack.co https://openapistack.co is to bring together tools for an end to end full stack toolkit for building and consuming typesafe REST APIs.
- mortallywounded 3y agoIs it just me, or do these "API contracts and type safety guarantees" all call back to SOAP?
- brightball 3y agoWSDL
- nine_k 3y agoThe core idea of SOAP was good. The ability to generate client and server code stubs from a single declarative file was great. I worked with SOAP extensively in early 2000s. The problem that killed SOAP, to my mind, was growing complexity that eventually started to outweigh the benefits of the protocol. Not every implementation supported every new complication that, say, MS kept inventing, it hurt interoperability. I think a modern sort-of-replacement for the SOAP's use case is GRPC. It eschews the heavyweight XML and tries to keep things simple, while staying reasonably typesafe, declarative, discoverable, and extendable.
- chrisweekly 3y agoSpeaking from painful experience, gRPC is an absolutely terrible choice for client-server interactions. Google (its creator) discourages its use except for server-to-server, and Improbable labs' grpc-web library is handcuffed to brittle and rapidly-aging web tooling.
- nine_k 3y agoGRPC is compact; in some cases it's important. What would you suggest, beyond the standard "ReST" and GraphQL, with OpenAPI as a declarative description?
- rattray 3y agoFor a compact message format being sent to browsers, you might look at messagepack, eg with https://github.com/msgpack/msgpack-javascript https://github.com/msgpack/msgpack-javascript – it's essentially binary JSON, so it'd be compatible with OpenAPI specs. I think the ser/des is slower than JSON in most browsers, but the message format is smaller. Oftentimes, using a query parameter like `?exclude[]=…` or `?include[]=…` or similar to say "only get me these response fields, not the whole object" can be useful for this too (and then you still get JSON back).
- Sytten 3y agoWhat I really like with graphql that IMO all the other spec lack is a nice human readable format. When as a team you design a new API no way I am going to write openapi spec, but I can reason in GraphQL schema. Then each side takes the contract and go implement the frontend and the backend and it just works.
- nlarew 3y ago> no way I am going to write openapi spec I don't get the stubbornness here. OpenAPI is not hard??? It's just JSON schema + some routes and effectively conveys the same information as a GraphQL schema, possibly more if you're not using custom directives and such. > Then each side takes the contract and go implement the frontend and the backend and it just works This is not unique to GraphQL. There's almost zero difference between programming to an OpenAPI spec vs a GraphQL schema - they're both API interface definitions.
- CharlieDigital 3y agoIf you want to do that, try gRPC and Proto. But I feel like REST and OpenAPI are fine especially if you start from the backend. I think with .NET Web APIs, the story is particularly good since it has out-of-the-box tooling for OpenAPI spec generation based on your exposed endpoints and models and then the option to customize that as needed. I've recently been working with it trying to get hot reload working on the frontend client generation and it's a fantastic DX with minimal wiring: https://chrlschn.dev/blog/2023/10/end-to-end-type-safety-with-dotnet7-webapis-typescript-openapi/ https://chrlschn.dev/blog/2023/10/end-to-end-type-safety-wit...
- dontlaugh 3y agoThere’s also Twirp, if gRPC doesn’t fit your requirements.
- Sytten 3y agoGrpc browser support is pretty bad, I still can't wrap my head around the whole grpc-web thing that looks like giant hacks. Openapi is not human readable IMO and the point is you design the API waaaay before you write any line of code. The api should express the business needs and be a two way discussion with the frontend people.
- okal 3y agoGraphQL is well over a decade old. I'm not sure "tried and tested" is a meaningful contrast between the two approaches at this point, especially as it relates to API requests from the frontend. It's okay for people to choose REST just because they like it better, and/or aren't interested in learning something different.
- anttiviljami 3y agoAgree. GraphQL is well mature by this point.
- paulddraper 3y agoGraphQL's first draft release was 8 years ago. [1] It's first non-draft release was 5 years ago. [2] It's first release under community governance was 2 years ago. [3] [1] https://github.com/graphql/graphql-spec/releases/tag/July2015 https://github.com/graphql/graphql-spec/releases/tag/July201... [2] https://github.com/graphql/graphql-spec/releases/tag/June2018 https://github.com/graphql/graphql-spec/releases/tag/June201... [3] https://github.com/graphql/graphql-spec/releases/tag/October2021 https://github.com/graphql/graphql-spec/releases/tag/October...
- andrewingram 3y agoI think I shipped my first production GraphQL server around this time 8 years ago, but by all accounts it was in use at Facebook a couple of years before it was opened up. So overall ~10 years old sounds right, though the released spec is a little different to the internal version that predates it.
- paulddraper 3y agoBy that standard MyCorpInnerPlatform is very mature.
- zabil 3y agoWe're pretty pleased with using trpc. With trpc-openapi, you can set up REST-like APIs. I like this method because it uses TypeScript and not YAML.
- anttiviljami 3y agoLove tRPC! For full stack typescript teams it’s the obvious way to go. Super simple and straightforward. OpenAPI or GraphQL are great though if you’re investing into APIs as a product
- jayy-lmao 3y agoAfter looking at tRPC, and having done a lot in a few jobs with GraphQL codegen & gRPC codegen, I always wondered why there were so few recent OpenAPI based codegen/client-server-contract tools. I think I was searching for this exact tool. Love that it makes the client somewhat backend agnostic, but the tools for the OpenAPI backend also look great. Thank you for this, I hope it is successful in achieving some adoption!
- anttiviljami 3y agoThanks for the encouraging words! So far it’s already nice to see these libraries being adopted slowly by more and more companies. Not nearly as big as graphql and trpc of course.
- brodouevencode 3y agoI want this, but language agnostic. Let me explain: standards are great, type safety is great, API contracts are great. Locked into a particular language is not great. In fact it's bad for the author. tRPC and now this assume my team has the desire and time to move to another language. The best frameworks assume none of that. I'm not asking for implementations for every possible language given a framework. I'm asking for a framework for which any possible language can be built upon because the constructs are simple and easy to follow: graphql does this pretty well despite some of the nuances. Bonus points if the author provides examples out of the box in a variety of languages.
- stetrain 3y agoThere are libraries out there for a lot of languages that can generate OpenAPI specs for your APIs and generate clients from OpenAPI specs. This seems like a nice set of tools for doing so in Node/Typescript but the general pattern of using OpenAPI contracts is language agnostic.
- brodouevencode 3y agoThe difference being that each language-specific framework has their own way of implementing the specs with the problem that some are done well and some are done half-assed. But then again, this problem exists with many specifications (OpenAPI is not alone). I look at it like this: the spec should inform the framework which should inform the (language specific) implementation. If the language specific implementation is it's own framework then so be it, but counter to the intentions of the layer above it. So why do all this? Enterprises have many teams that have many capabilities. How one (Python) team implements OpenAPI is drastically different than how another (Typescript) team implements OpenAPI, which causes a lot of friction when moving engineers around to different teams. If a spec desires to have mass adoption then providing at least heuristics for implementation will only increase that adoption.
- arcbyte 3y agoThere's no winning at this layer and every attempt is as doomed as medieval alchemists trying to transmute lead to gold. The key here is overall speed, but you can't trade the time spent learning/understanding the API contract for these crazy complicated tools. The developer still has to look at the operations and data models exposed by the API, understand them, amd plan for how to integrate them into the larger application. The big bonus of the human documentation approaches today is that time is somewhat combined with building the client. The downside of course is that it's a human doing it. My point here is that you can't take the time a human is going to spend understanding the API concepts and then tack on a bunch of time learning, configuring, and running the client gen code and associated infrastructure as well and expext that your solution is going to win. The more complicated these codegen setups get, the less comicated just reading some docs and spinning up a few lines of client code is. And guess which I'm going to choose as a dev? Whatever is overall fastest and gets me on to the problems I'm really trying to solve.
- progx 3y agoThat is why we now step back to SSR-apps. No api necessary, no extra layers, no extra bloat and it is fast and scalable enough for the most apps.
- throwaway11004 3y agoWho's we? Most apps nowadays have a mobile app, so you need the API anyways...
- anttiviljami 3y agoThis project is precisely for devs who dislike codegen and want to just ship products fast. 1. Design your API in yaml 2. Run a mock API 3. Develop the App, iterate mock API 4. Implement backend and ship No code generation needed. Generate types if you want.
- tnolet 3y agoHow is designing an API in YAML “fast”? Isn’t using code much, much faster for the average dev?
- djha-skin 3y ago> While REST APIs don't generally provide the same level of control to clients as GraphQL, many times this could be seen as a benefit especially in scenarios where strict control over data access and operations is crucial. REST is more secure, cacheable, and more performant on the server side as field resolution doesn't need to happen like it does with GraphQL. I'm told it is easier to develop against on the client side, and this is a trade-off, but I favor REST applications over GraphQL ones as a DevOps engineer. They are much easier to administer infrastructure-wise. I can cache the requests, I don't need to stand up an Apollo router, and WAF support for GraphQL is still pretty nacent. My coworker found a GraphQL query only about five layers deep that could tip over a service. Please don't put cycles in your graphs. Data at our company suggests that several small requests actually do better performance-wise than one large one. We switched to GraphQL a year and a half ago or so, but this piece of data seems to suggest that we might have been better off (performance wise on the client side) just sticking with REST. My suggestion to that effect was not met with optimism either on the client or server side. Apparently there are server-side benefits as well, allowing for more modular development or something like that. I have used OpenAPI using connexion[1]. It was hard to understand at first, but I really liked that the single source of truth was one schema. It also made it really easy to develop against the API because it came with a UI that showed the documentation for all the REST end points and even had test buttons. 1: https://connexion.readthedocs.io/en/latest/ https://connexion.readthedocs.io/en/latest/
- datadeft 3y agoI concur. I usually implement a specific rest resource for use cases which is usually easier to do than implement a GraphQL backend.
- SkyPuncher 3y ago> My coworker found a GraphQL query only about five layers deep that could tip over a service. I find arguments like this a bit odd. That's a pretty deep query in REST as well. I don't have extensive experience with GraphQL, but the complaints I see about it often seem like things you just shouldn't be doing anyways - or, if you do, they're going to be rough in REST as well.
- coding123 3y agoGraphQL is more future proof than rest. Rest is tied to HTTP forever - GraphQL can be separated, easily. Rest communicates inputs and outputs in too many ways for my liking any more: headers, paths, bodies, query params, and dare I say method. One complaint for GQL is that potentially they had a chance to standardize paging, filtering, etc... instead every schema is customized. I guess we'll have to create a new standard at some point. We'll never get this shit right.
- anttiviljami 3y agoI don’t really agree GraphQL is somehow more ”future proof” because it doesn’t use as many HTTP features. It’s not like HTTP is going to go away in a while. I find that AsyncAPI is a nice extension of OpenAPI/REST ideas if you need to go beyond request / response.
- mdaniel 3y agoIf I'm understanding coding123's comment correctly, I think AsyncAPI would need to be extended to allow specifying a GraphQL schema and not just a JSON schema as the message payload and (I guess implied?) response types
- isuckatcoding 3y agoMore a comment on the main page. Show some code or small example on that main page. I have no idea or sense to compare it to graphql without some small toy example.
- anttiviljami 3y agoThanks for the feedback! There is a full interactive sandbox example on the front/landing page https://openapistack.co https://openapistack.co But point taken, will make sure code examples are visible on the overview page
- ericls 3y agoGraphQL is RESTful. Just treat GraphQL Result as the resource..
- t1mmen 3y agoCool to see more of these kinds of projects, nice work OP! I'm a huge fan of this general concept, so you're definitely on the right path imo. That said, two things are jumping out at me: - Users would still be writing OpenAPI specs/JSON Schema by hand, an incredibly annoying and tedious process (unless using a nicer DSL) - Generation/build steps are annoying (but likely unavoidable here) As pointed out by many other comments, an unfortunate amount of teams aren't writing OAPI specs. I personally feel this is a major mistake for anyone building an API, but that's a discussion for another day. I've been using https://www.ts-rest.com https://www.ts-rest.com, a similar project, for a few months now. Instead of relying on OpenAPI specs as the source, you define the "contracts" using Zod. These contracts are essentially OpenAPI specs, but Zod makes for a MUCH better DSL. I really like that... - Real-time type checking without generator steps, both server & client-side. XHR clients like `fetch`, `react-query`, etc clients are inferred from the contract. - The Zod contracts _can_ generate/output OpenAPI specs and Mock Service Worker mocks for testing (as needed, not required) - (Optional) Automatic request & response validation based on Zod contract definitions, no additional code needed. - (Node) Backend agnostic (partially, anyway: NextJS, Express, Nest and Fastify supported atm) - Works very well with `react-hook-form` & `ZodResolver`, so e.g an invalid value on client-side shows the same error as the API would have if request were fired. - Zod types can be used as typescript (z.infer), a wonderful way to re-use e.g model types in client-side components. This ts-rest experience has fundamentally solidified a belief in me: One single source of truth, propagating through the system, is _the_ best way to build safely and efficiently. I am almost ashamed to look back on the many, many projects I've worked on where APIs and client-side did not share truth. Duplication of (hand-rolled) types, error messages, etc is horrific in retrospect. I don't want to think about the amount of bugs I've come across due to this dual (at best) truth approach.
- 8note 3y ago> Users would still be writing OpenAPI specs/JSON Schema by hand, an incredibly annoying and tedious process (unless using a nicer DSL) My big foot gun for this is that you can manually write jsonschema that doesn't have a nicely serializable java representation, making it hard to use cross-language, and you don't find out that that's the case until you try
- 3y ago
- i_like_robots 3y agoCongrats, this looks really nice! I recently finished a side project using Fastify and the Fastify Swagger plugin (which extends the built-in request and response validation and can dynamically generate an Open API definition) which was a good experience overall but the addition of request mocking and the solid documentation site shown here could tempt me to revisit it.
- anttiviljami 3y agoCheers! Going from code first to schema first is definitely worth it in my experience! Especially when working in a team. The nice thing is you already have an openapi spec, so it’s pretty trivial to eject from fastify swagger and switch to openapi-backend if you want! Here’s an example of openapi-backend running on Fastify https://github.com/openapistack/openapi-backend/tree/main/examples/fastify https://github.com/openapistack/openapi-backend/tree/main/ex...
- jensneuse 3y ago> Many organizations choose REST over GraphQL due to more established conventions, simplicity, and the ability to leverage standard HTTP features directly. I strongly disagree with this. REST APIs are usually a complete mess and follow no conventions at all. Even if OpenAPI is being used, the majority of OAS documents have errors or are entirely broken. I'm Working on tooling to automatically parse OAS and transform it to GraphQL schemas. There's not a single day where we don't find another broken OAS. Compare that to GraphQL where we now have powerful linters for schemas etc... But even without, the average GraphQL API is definitely in better shape than the average REST API, and that's simply because the tooling enforces better boundaries. You might have a correct OAS vs every GraphQL server actually follows the GraphQL spec.
- anttiviljami 3y ago> The average GraphQL API is definitely in better shape than the average REST API Totally agree. GraphQL tooling is generally just better. It enforces a Schema first workflow and thus more emphasis on conventions and design. OpenAPI tends to be an after thought with teams building REST APIs. Swagger started out as a way to add docs and generate SDKs. That was exactly my motivation for building openapi-stack. GraphQL-like tooling, but for teams using REST.
- jensneuse 3y agoThat's fantastic and I hope to see more of this.
- deleted 3y ago[deleted]
- barefeg 3y agoHow do you make sure that the spec is in sync with the implementation?
- anttiviljami 3y agoThe spec is used in runtime for routing and validation. https://openapistack.co/docs/examples/building-apis/ https://openapistack.co/docs/examples/building-apis/
- barefeg 3y agoThanks. I missed this part https://openapistack.co/docs/openapi-backend/typescript/ https://openapistack.co/docs/openapi-backend/typescript/ so the types are generated for the backend to use. We’ve used API first approach before, but it was very painful to keep the types in sync. Now we’re transitioning to FastAPI which allows to more or less create the OpenAPI types in code (via pydantic which can export the python types into OpenAPI schema). We now follow a kind of hybrid approach in which the routes and types are created in code first, without actual implementation (just return 404). This auto generates the spec.yaml as well as any vendor code we might need (via client generator). I think this is quite a productive workflow as well because the type generation in code is more convenient than typing yaml by hand and everything is always in sync
- anttiviljami 3y agoThe code first approach is surely enticing and miles better than manually keeping the openapi spec up to date. But I’d always advocate for going schema first. This has huge benefits for collaboration between frontend and backend engineers and results in better designed APIs and generally better software in my experience. Wrote a full blog post some time ago explaining why the API First approach works: https://dev.to/epilot/why-we-design-apis-first-e85 https://dev.to/epilot/why-we-design-apis-first-e85
- barefeg 3y agoMaybe I didn’t explain the process correctly, we do generate the spec first, it’s just that the tool we use for creating the spec is the code that will later contain the implementation.
- theogravity 3y agoAwesome job! I really liked that you built it in a way that it's framework-agnostic and you also have parameter validation built in! This might be the best OpenAPI Typescript-based project I've seen so far. The ones I've used often tie you into a specific framework and do not perform any validation on the parameters at all.
- anttiviljami 3y agoThank you for the kind words!