cgapis
v0.6.0
Published
Generate API code for any client and any server from the API spec file
Downloads
8
Maintainers
Readme
cgapis: Code Generation from API Specification
cgapis
generates client-side SDKs and server-side APIs from specification files.
Installation and Usage
npm install -g cgapis # install globally to use from any directory
Start by copying the two directories /api-schemas
and /api-services
, then run:
cgapis
This will generate two output directories /generated-server
and /generated-client
.
Note: configuration files and CLI arguments are not yet implemented.
Why Code Generation?
1. Design-first Approach to API Development Life-cylce
- A contract between frontend and backend developers. A single source of truth for the API
- Language independent (see: Supported Languages)
2. Client Development Experience (DX)
- Discoverable API through the SDK
- Static typing
- Auto completion
- API documentation
3. Robust Error-Handling
- Full power of error handling in your language
- Application-specific errors (no generic status codes)
4. Data Validation (Optional)
- Before requests leave the client and when requests reach the server
- Using powerful JSON Schema validators (e.g., Ajv in case of JavaScript)
5. Cacheable By Default
Unlike GraphQL and JSON-RPC, cgapis is cacheable by default.
6. HTTP Methods Are Limiting
HTTP verbs aren't enough to express all functionalities of the web service, if your logic isn't just about GET, POST, PUT, PATCH, DELETE. For example, let's say I have a Course
Collection/Table, which contains a curriculum, which is an array of Sections
and within each section is an array of Nodes
which contain the content of the course, i.e., the learning material.
Now, how would you map the following to HTTP verbs?:
- Reorganize sections or nodes
- Increment views on a node
- Increment/Decrement likes/dislikes on a course
- Add a comment to a node
Developers' views would vary, simply because there are many ways to do it:
- What path to use?
- Should we make action paths?
- Pass parameters through URL path?
- Pass parameters through URL query?
- Pass parameters through request body?
I would like to just call SDK.Course.dislike(courseID, userID)
, or SDK.Node.addComment(nodeID, comment)
. What do you think?
Low-level primitives such as URL endpoints, HTTP methods, request body, query strings, URL encoding, content-type, ...etc are inferred by our smarter generators and abstracted away from the user (still available if needed).
Workflow
1. Initial Definition
Developers agree to define:
- Services in
/api-services
a namespace for operations - Schemas in
/api-schemas
defined using JSON Schema draft-07 - Service operations defines the structure of the request (
req
) and response (res
)
2. Code Generation
Then, you cd
into the directory where /api-services
and /api-schemas
exist, and run the command cgapis
. You'll see the output as two directories: /generated-client
and /generated-server
.
3. Later Modification of Specifications
We would like to provide a way to detect changes in specification changes. (not implemented yet)
Solution Details
We're using RPC over HTTP: basically, a remote procedure URL is as follows: http://<hostname>/api/<service>/<method>
. Using only two HTTP methods to do CRUD: GET
for "Read" operations and POST
for "Create", "Update", "Delete" operations. The generated code uses whatever network library there is to pass/recieve requests/responses between the client and the server, exposing a unified interface to application code both on the server (named: API) and the client (named: SDK). The interface contains methods on services and data types.
TBD (To Be Done)
- Handling Errors
- Access Control
- Deal with change in spec
- Over-fetching workaround
Supported Languages
| | Language/Frameworks | |--------------------|------------| | Client SDKs | Browser (Axios) | | Server APIs | Node (Express.js) |
Contribution
Generators for each language is at /generators/<lang>/[client|server]/<framework>.js
.
|File / Directory |Description |
|---------------------|--------------------------------------------------------------------------------------------------------------|
|index.js
|Main entry |
|config.js
|Configuration |
|cmd.js
|Command-Line Interface (overwrites config) |
|spec.js
|Exports {schemas, services}
after reading, parsing, and normalizing /api-schemas
and /api-services
| |
|/generators/semantics.js
|Helper functions for all languages |
|/generators/<lang>/common/
|Help functions for <lang>
shared across frameworks |
Some of the few things you can help with:
- Add languages/frameworks: Go, Python, Rust, ...etc.
- Suggest ways to improve
- Use, and raise issues Todos:
- [x] asdf
Remember
- The solution shall not make anything harder to do (e.g., access control, error-handling, logging, or validation). Only easier and simpler
- The solution shall adapt to changes in API specs
- The solution shall be easily customized to users' needs