Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve versioning documentation and add showcase example #163

Merged
merged 10 commits into from
May 24, 2024
297 changes: 152 additions & 145 deletions docs/api-versioning.md

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions packages/bautajs-fastify-versioning-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# bautajs-fastify-versioning-example

- This API example intends to show how you can manage versioning with bautajs-fastify.
- This project example purpose is to showcase main features using simple examples.
- This project example **does not** intend to show good practices using Node.js or security practices at all. Please be sure you follow security good practices on your Node.js API (i.e. adding [helmet](@fastify/helmet)).

## How to start

- It is recommented that you are using node v18.
- `npm install` from the root project of the monorepo
- enter into `packages/bautajs-fastify-versioning-example` folder

## Brief explanation of the different examples

We have a set of three services:

- `v1`
- `cats` --> endpoint marked as `deprecated`. This service returns name, communication and breed
- `dogs` --> This service returns name, communication and breed
- `v2`
- `cats` --> latest version of the endpoint. This service returns petName, communication and favouriteAction


## An example of each initialization method

You can run npm start for each one of the scripts:

- ``npm run start``: Uses default port 8080. Basic example without any versioning. Only v1 endpoints are exposed.
- ``start:external``: Configures the versioning inheritance outside the plugin.
- ``start:plugin``: Configures the versioning inheritance with the plugin option 'inheritOperationsFrom' and instantiates the two instances of bautaJs (the original and the new version).
- ``start:parent``: Configures the versioning inheritance instantiating only the parent bautaJs instance and uses the plugin option 'inheritOperationsFrom' to add the new version endpoints.


This is only a showcase of how the versioning works. For details you should check [versioning](https://github.com/axa-group/bauta.js/blob/main/docs/api-versioning.md).


## Third party dependencies licenses

### Production
- [@axa/[email protected]](https://github.com/axa-group/bauta.js) - MIT*
- [@axa/[email protected]](https://github.com/axa-group/bauta.js) - MIT*
- [@axa/[email protected]](https://github.com/axa-group/bauta.js) - MIT*
- [[email protected]](https://github.com/fastify/fastify) - MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"openapi": "3.0.0",
"info": {
"description": "A new API",
"version": "v1",
"title": "Cats API"
},
"servers": [
{
"url": "/v1/api/"
}
],
"paths": {
"/cats": {
"get": {
"operationId": "findCat",
"deprecated": true,
"responses": {
"200": {
"description": "Miau!",
"content": {
"application/json": {
"schema": {
"properties": {
"name": {
"type": "string"
},
"communication": {
"type": "string"
},
"breed": {
"type": "string"
}
}
}
}
}
}
}
}
},
"/dogs": {
"get": {
"operationId": "findDog",
"responses": {
"200": {
"description": "Woof!",
"content": {
"application/json": {
"schema": {
"properties": {
"name": {
"type": "string"
},
"communication": {
"type": "string"
},
"breed": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"openapi": "3.0.0",
"info": {
"description": "A new API",
"version": "v2",
"title": "Cats API"
},
"servers": [
{
"url": "/v2/api/"
}
],
"paths": {
"/cats": {
"get": {
"operationId": "findCatV2",
"responses": {
"200": {
"description": "Miaw!",
"content": {
"application/json": {
"schema": {
"properties": {
"petName": {
"type": "string"
},
"communication": {
"type": "string"
},
"favouriteAction": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
29 changes: 29 additions & 0 deletions packages/bautajs-fastify-versioning-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "@axa/bautajs-fastify-versioning-example",
"version": "1.0.0",
"description": "A bautaJS example of versioning in fastify",
"main": "./server-without-versioning.js",
"scripts": {
"start": "LOG_LEVEL=info DEBUG=bautajs* node ./server-without-versioning.js",
"start:parent": "LOG_LEVEL=info DEBUG=bautajs* node ./versioning-only-parent.js",
"start:plugin": "LOG_LEVEL=info DEBUG=bautajs* node ./versioning-plugin-inherits.js",
"start:external": "LOG_LEVEL=info DEBUG=bautajs* node ./versioning-external-inherits.js"
},
"repository": {
"type": "git",
"url": "https://github.com/axa-group/bauta.js"
},
"private": true,
"keywords": [
"bautajs",
"fastify",
"middleware"
],
"license": "SEE LICENSE IN LICENSE.txt",
"dependencies": {
"@axa/bautajs-core": "^3.1.0",
"@axa/bautajs-datasource-rest": "^3.1.0",
"@axa/bautajs-fastify": "^3.1.0",
"fastify": "^4.15.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const fastify = require('fastify')({ logger: true });

const { bautajsFastify } = require('@axa/bautajs-fastify');
const { BautaJS } = require('@axa/bautajs-core');

const apiDefinitionsV1 = require('./api-definitions-v1.json');

const bautaJsV1 = new BautaJS({
apiDefinition: apiDefinitionsV1,
resolversPath: './server/**/resolvers*.js',
staticConfig: {
someVar: 2
},
strictResponseSerialization: false,
validatorOptions: {
coerceTypes: 'array'
}
});

(async () => {
fastify.register(bautajsFastify, {
bautajsInstance: bautaJsV1,
prefix: '/v1/',
apiBasePath: '/api/'
});

fastify.listen(
{
host: '0.0.0.0',
port: 8080
},
err => {
if (err) throw err;
fastify.log.info('Server listening on localhost:', fastify.server.address().port);
}
);
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { pipe, resolver, step } = require('@axa/bautajs-core');

const getCatStep = step(() => {
return {
name: 'Grey',
communication: 'Meow',
breed: 'all cats are the same'
};
});

const getDogStep = step(() => {
return {
name: 'Milu',
communication: 'Woof',
breed: 'fox-terrier'
};
});

module.exports = resolver(operations => {
operations.findCat.validateRequest(true).validateResponse(true).setup(pipe(getCatStep));
operations.findDog.validateRequest(true).validateResponse(true).setup(pipe(getDogStep));
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const { pipe, resolver, step } = require('@axa/bautajs-core');

const getCatStep = step(() => {
return {
petName: 'Blondie',
communication: 'Meow',
favouriteAction: 'Purr'
};
});

module.exports = resolver(operations => {
operations.findCatV2
.validateRequest(true)
.validateResponse(true)
.setup(
pipe(getCatStep, prev => {
console.log('mierda mia', prev);
return prev;
})
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const fastify = require('fastify')({ logger: true });

const { bautajsFastify } = require('@axa/bautajs-fastify');
const { BautaJS } = require('@axa/bautajs-core');

const apiDefinitionsV1 = require('./api-definitions-v1.json');

const apiDefinitionsV2 = require('./api-definitions-v2.json');

const bautaJsV1 = new BautaJS({
apiDefinition: apiDefinitionsV1,
resolversPath: './server/v1/resolvers*.js',
staticConfig: {
someVar: 2
},
strictResponseSerialization: false,
validatorOptions: {
coerceTypes: 'array'
}
});

const bautaJsV2 = new BautaJS({
apiDefinition: apiDefinitionsV2,
resolversPath: './server/v2/resolvers*.js',
staticConfig: {
someVar: 2
},
strictResponseSerialization: false,
validatorOptions: {
coerceTypes: 'array'
}
});

(async () => {
fastify
.register(bautajsFastify, {
bautajsInstance: bautaJsV1,
prefix: '/v1/',
apiBasePath: '/api/'
})
.after(() => {
bautaJsV2.inheritOperationsFrom(bautaJsV1);
fastify.register(bautajsFastify, {
bautajsInstance: bautaJsV2,
prefix: '/v2/',
apiBasePath: '/api/'
});
});

fastify.listen(
{
host: '0.0.0.0',
port: 8181
},
err => {
if (err) throw err;
fastify.log.info('Server listening on localhost:', fastify.server.address().port);
}
);
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const fastify = require('fastify')({ logger: true });

const { bautajsFastify } = require('@axa/bautajs-fastify');
const { BautaJS } = require('@axa/bautajs-core');

const apiDefinitionsV1 = require('./api-definitions-v1.json');

const apiDefinitionsV2 = require('./api-definitions-v2.json');

const bautaJsV1 = new BautaJS({
apiDefinition: apiDefinitionsV1,
resolversPath: './server/v1/resolvers.js',
staticConfig: {
someVar: 2
},
strictResponseSerialization: false,
validatorOptions: {
coerceTypes: 'array'
}
});

(async () => {
fastify
.register(bautajsFastify, {
bautajsInstance: bautaJsV1,
prefix: '/v1/',
apiBasePath: '/api/'
})
.after(() => {
fastify.register(bautajsFastify, {
resolversPath: './server/v2/resolvers.js',
apiDefinition: apiDefinitionsV2,
prefix: '/v2/',
apiBasePath: '/api/',
inheritOperationsFrom: bautaJsV1
});
});

fastify.listen(
{
host: '0.0.0.0',
port: 8383
},
err => {
if (err) throw err;
fastify.log.info('Server listening on localhost:', fastify.server.address().port);
}
);
})();
Loading
Loading