1.1.7 • Published 5 months ago

@quasidea/oas-client-react v1.1.7

Weekly downloads
62
License
MIT
Repository
github
Last release
5 months ago

About the OAS Client for JavaScript/React

This library provides the ability to code-generate a fully featured Swagger (a.k.a. Open API Specification) client codebase for JavaScript/React.

In a standard Swagger file, you have the following:

  • paths: defines all of the API webservice methods
  • definitions: defines all of the schemas that are used as input parameters and/or output responses for the API API webservice methods

This library is able to code-generate all of the paths and definitions into Clients and Models for use in your JavaScript/React-based application.

  • Clients: standard JavaScript methods that match 1-to-1 with each path, using standard JavaScript primitives and objects as your input parameters and response data passed to your callbacks
  • Models: standard JavaScript classes that match 1-to-1 with each definition, allowing for strongly typed request and response objects

Quick Installation

Begin by installing the package through NPM:

npm install @quasidea/oas-client-react

Run the command line tool for the OAS Client to setup/initialize the settings:

npx oas-client init URL

(where URL is the URL of the swagger file that your application will be the client of)

This command will create a oas-client.json settings file that contains the following three properties:

  • swaggerUrl: the URL of the swagger file that you specified above
  • clientsDestination: the relative folder path that you want to save your code-generated Clients
  • modelsDestination: the relative folder path that you want to save your code-generated Models

While you can feel free to edit this file, it's recommended that you only make edits prior to your first run of your code generator.

And then to actually run the code generator itself:

npx oas-client codegen

The Code Generator

The OAS Client code generator will generate files into the folders defined as clientsDestination and modelsDestination in your oas-client.json settings file.

The Clients folder contains:

  • ClientMiddleware.js: this is where you can define specific behaviors for all of your Client API calls. This file is designed to be edited.
  • base/Client.js: this is a simple proxy/accessor class that allows easy access to all of your Client APIs. This file is NOT meant to be edited (any subsequent runs of the code generator will ovewrite any manual changes).
  • base/*.js: the other files are the individual Client APIs as defined in the Swagger file. These files are NOT meant to be edited (any subsequent runs of the code generator will ovewrite any manual changes).

The Models folder contains:

  • *.js: the top level folder contains the individual superclasses for each of the Models as defined in the Swagger file. These files all inherit from their respective base classes. While these superclasses are initially empty, it is designed to hold any customization you wish to make on the Model classes. These file are designed to be edited.
  • base/*.js: this contains the individual code-generated subclass for each of the Models as defined in the Swagger file. These files are NOT meant to be edited (any subsequent runs of the code generator will ovewrite any manual changes).
  • enum/*.js: if any ENUMs are defined in the Swagger, each ENUM will be defined here. It is recommended that these enum object properties be used instead of text strings, so that any linting tools can be used to detect errors/issues. These files are NOT meant to be edited (any subsequent runs of the code generator will ovewrite any manual changes).

Client API Call Workflow

Each code-generated client method uses the JavaScript-standard Fetch API to make the HTTP requests to the server. The method names and the Client API that it belongs to is defined by the operationId property defined in each method in the Swagger.

Assuming you have a path defined your swagger that has an operationId of SomeApi::doSomething, then the workflow to call this API is as follows:

  • You can make the call to Client.SomeApi.doSomething()
  • You would pass in any parameters that is defined in the swagger note that if the method is expecting any schemas, you would pass in the strongly typed Model that was code generated for it. note that it doesn't matter if the parameter is a body, query or path parameter... the Client API treats all of them the same way. All you need to do is to pass it in and the code generated method will generate the fetch() call appropriately. note that you don't need to worry about what URL to call. Again, the Client API does this for you. note that it doesn't matter if this is a POST, GET, PUT, DELETE, etc. Again, the Client API takes care of figuring this out for you.
  • You would also pass in a ResponseHandler to define your response callbacks this is similar in concept to a Promise, except that it is more robust/featured to handle promises based on the actual HTTP Status Code. You can also define pre-configured/default promise handlers you would have a status### response handler defined for each HTTP Status Code you are expecting you should also define an else response handler to handle any HTTP Status Code that you received which weren't defined/specified You should also define an error response handler to handle any HTTP transport errors
  • The code generated doSomething() method will then make the following calls to the ClientMiddleware (and remember, all of these methods are designed to be modified for your application): getEndpointUrl to get the root endpoint URL for all webservice method calls generateRequestOptionsForMethod to get the options to pass into the fetch() call * generateDefaultResponseHandler to get the "default" set of ResponseHandlers, of which any would be overridden by the specific Call

So to illustrate the above example more fully, suppose the swagger is defined as follows:

{
	...
	"paths": {
		"/some_api/do_something/{id}": {
			"post": {
				"operationId": "SomeApi::doSomething",
				"parameters": [
					{
						"in": "path",
						"name": "id",
						"type": "string"
					},
					{
						"in": "body",
						"name": "person",
						"schema": {
							"$ref": "#/definitions/Person"
						}
					}
				],
				"responses": {
					"200": {
						"schema": {
							"$ref": "#/definitions/DoSomethingResponse"
						}
					},
					"404": {
						"description": "id was not found"
					},
					"409": {
						"description": "there was a conflict trying to do this action"
					}
				}
			}
		},
		...
		"definitions": {
			"Person": {
				"type": "object",
				"properties": {
					"email": {"type": "string"},
					"password": {"type": "string"}
				}
			},
			"DoSomethingResponse": {
				"type": "object",
				"properties": {
					"message": {"type": "string"},
					"configuration": {"type": "string"}
				}
			}
		}
	}
}

Your call to DoSomething would then look as follows:

const id = 1234;

const person = new Person();
person.email = 'johndoe@example.com';
person.password = 'mypassword';

Client.SomeApi.doSomething(id, person, {
	status200: responseObject => {
		alert("The call was successful... the configuration is " + responseObject.configuration);
	},
	status404: responseText => {
		alert('The ID was not found.  Here is the response from the server: ' + responseText);
	},
	status409: responseText => {
		alert('There was a conflict trying to do this.  Here is the response from the server: ' + responseText);
	},
	else: (statusCode, responseText) => {
		alert('Oops, we were not expecting a HTTP status code of ' + statusCode);
		console.error('unhandled response to status code ' + statusCode + ': ' + responseText);
	},
	error: error => {
		alert('An error occurred.  Please view the console for more information.');
		console.error(error);
	}
});

As you can see, the input and outputs use standard JavaScript primitives or code generated strongly typed models. And note that the ResponseHandler specifies what to do for each different HTTP Status Code that you are expecting, or an else as a catch all for anything else you may have missed.

Also, for most applications, you will want to define a default else and error handler that would account for most of your use cases. You can define this in ClientMiddleware.js, and this would make most of your Client API calls cleaner since you will not need to define these handlers all the time.

1.1.7

5 months ago

1.1.6

8 months ago

1.1.1

1 year ago

1.1.5

1 year ago

1.1.4

1 year ago

1.1.3

1 year ago

1.1.2

1 year ago

1.1.0

1 year ago

1.0.27

2 years ago

1.0.26

2 years ago

1.0.25

2 years ago

1.0.24

3 years ago

1.0.23

3 years ago

1.0.22

3 years ago

1.0.21

3 years ago

1.0.20

3 years ago

1.0.19

3 years ago

1.0.18

3 years ago

1.0.17

3 years ago

1.0.16

3 years ago

1.0.15

4 years ago

1.0.14

4 years ago

1.0.11

4 years ago

1.0.13

4 years ago

1.0.12

4 years ago

1.0.10

4 years ago

1.0.9

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago