From cb4354903e07e8378fa58a9024c8a9171362db6a Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 10 Mar 2020 11:11:15 -0700 Subject: [PATCH] feat(apiconnect): initial implemention of ApiConnectComponent --- extensions/apiconnect/.npmrc | 1 + extensions/apiconnect/LICENSE | 25 +++++++ extensions/apiconnect/README.md | 66 +++++++++++++++++++ extensions/apiconnect/index.d.ts | 6 ++ extensions/apiconnect/index.js | 6 ++ extensions/apiconnect/index.ts | 8 +++ extensions/apiconnect/package-lock.json | 19 ++++++ extensions/apiconnect/package.json | 54 +++++++++++++++ .../acceptance/apiconnect.acceptance.ts | 53 +++++++++++++++ .../apiconnect/src/apiconnect.component.ts | 11 ++++ .../src/apiconnect.spec-enhancer.ts | 51 ++++++++++++++ extensions/apiconnect/src/index.ts | 8 +++ extensions/apiconnect/src/keys.ts | 16 +++++ extensions/apiconnect/tsconfig.build.json | 11 ++++ 14 files changed, 335 insertions(+) create mode 100644 extensions/apiconnect/.npmrc create mode 100644 extensions/apiconnect/LICENSE create mode 100644 extensions/apiconnect/README.md create mode 100644 extensions/apiconnect/index.d.ts create mode 100644 extensions/apiconnect/index.js create mode 100644 extensions/apiconnect/index.ts create mode 100644 extensions/apiconnect/package-lock.json create mode 100644 extensions/apiconnect/package.json create mode 100644 extensions/apiconnect/src/__tests__/acceptance/apiconnect.acceptance.ts create mode 100644 extensions/apiconnect/src/apiconnect.component.ts create mode 100644 extensions/apiconnect/src/apiconnect.spec-enhancer.ts create mode 100644 extensions/apiconnect/src/index.ts create mode 100644 extensions/apiconnect/src/keys.ts create mode 100644 extensions/apiconnect/tsconfig.build.json diff --git a/extensions/apiconnect/.npmrc b/extensions/apiconnect/.npmrc new file mode 100644 index 000000000000..cafe685a112d --- /dev/null +++ b/extensions/apiconnect/.npmrc @@ -0,0 +1 @@ +package-lock=true diff --git a/extensions/apiconnect/LICENSE b/extensions/apiconnect/LICENSE new file mode 100644 index 000000000000..be7863ca6c60 --- /dev/null +++ b/extensions/apiconnect/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) IBM Corp. 2020. All Rights Reserved. +Node module: @loopback/apiconnect +This project is licensed under the MIT License, full text below. + +-------- + +MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/extensions/apiconnect/README.md b/extensions/apiconnect/README.md new file mode 100644 index 000000000000..bf9c370221af --- /dev/null +++ b/extensions/apiconnect/README.md @@ -0,0 +1,66 @@ +# @loopback/apiconnect + +This module extends LoopBack with the ability to integrate with +[IBM API Connect](https://www.ibm.com/cloud/api-connect). It comes with an +`ApiConnectComponent` that adds an `OASEnhencer` extension to contribute +`x-ibm-configuration` to the OpenAPI spec generated by LoopBack applications. + +## Stability: ⚠️Experimental⚠️ + +> Experimental packages provide early access to advanced or experimental +> functionality to get community feedback. Such modules are published to npm +> using `0.x.y` versions. Their APIs and functionality may be subject to +> breaking changes in future releases. + +## Installation + +```sh +npm i @loopback/apiconnect --save +``` + +## Usage + +The component should be loaded in the constructor of your custom Application +class. + +Start by importing the component class: + +```ts +import {ApiConnectComponent} from '@loopback/apiconnect'; +``` + +In the constructor, add the component to your application: + +```ts +this.component(ApiConnectComponent); +``` + +The component requires a configuration for API Connect extension for OpenAPI +spec. The `targetUrl` tells API Connect gateway where the REST APIs are served. + +```ts +const apiConnectOptions: ApiConnectSpecOptions = { + targetUrl: 'http://localhost:3000/test-service', +}; +app + .configure(ApiConnectBindings.API_CONNECT_SPEC_ENHANCER) + .to(apiConnectOptions); +``` + +## Contributions + +- [Guidelines](https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md) +- [Join the team](https://github.com/strongloop/loopback-next/issues/110) + +## Tests + +Run `npm test` from the root folder. + +## Contributors + +See +[all contributors](https://github.com/strongloop/loopback-next/graphs/contributors). + +## License + +MIT diff --git a/extensions/apiconnect/index.d.ts b/extensions/apiconnect/index.d.ts new file mode 100644 index 000000000000..6d1e5f25950f --- /dev/null +++ b/extensions/apiconnect/index.d.ts @@ -0,0 +1,6 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +export * from './dist'; diff --git a/extensions/apiconnect/index.js b/extensions/apiconnect/index.js new file mode 100644 index 000000000000..7a68a0b4da28 --- /dev/null +++ b/extensions/apiconnect/index.js @@ -0,0 +1,6 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +module.exports = require('./dist'); diff --git a/extensions/apiconnect/index.ts b/extensions/apiconnect/index.ts new file mode 100644 index 000000000000..7b10624b4b5b --- /dev/null +++ b/extensions/apiconnect/index.ts @@ -0,0 +1,8 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +// DO NOT EDIT THIS FILE +// Add any additional (re)exports to src/index.ts instead. +export * from './src'; diff --git a/extensions/apiconnect/package-lock.json b/extensions/apiconnect/package-lock.json new file mode 100644 index 000000000000..994a36582cb4 --- /dev/null +++ b/extensions/apiconnect/package-lock.json @@ -0,0 +1,19 @@ +{ + "name": "@loopback/apiconnect", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "10.17.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", + "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==", + "dev": true + }, + "tslib": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" + } + } +} diff --git a/extensions/apiconnect/package.json b/extensions/apiconnect/package.json new file mode 100644 index 000000000000..592a964f41e6 --- /dev/null +++ b/extensions/apiconnect/package.json @@ -0,0 +1,54 @@ +{ + "name": "@loopback/apiconnect", + "version": "0.0.1", + "description": "An extension for IBM API Connect", + "engines": { + "node": ">=10" + }, + "scripts": { + "acceptance": "lb-mocha \"dist/__tests__/acceptance/**/*.js\"", + "build:apidocs": "lb-apidocs", + "build": "lb-tsc", + "clean": "lb-clean loopback-apiconnect*.tgz dist tsconfig.build.tsbuildinfo package", + "pretest": "npm run build", + "test": "lb-mocha \"dist/__tests__/**/*.js\"", + "unit": "lb-mocha \"dist/__tests__/unit/**/*.js\"", + "verify": "npm pack && tar xf loopback-apiconnect*.tgz && tree package && npm run clean" + }, + "author": "IBM Corp.", + "copyright.owner": "IBM Corp.", + "license": "MIT", + "keywords": [ + "LoopBack", + "IBM API Connect" + ], + "files": [ + "README.md", + "index.js", + "index.d.ts", + "dist", + "src", + "!*/__tests__" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/strongloop/loopback-next.git", + "directory": "extensions/apiconnect" + }, + "dependencies": { + "@loopback/context": "^3.0.0", + "@loopback/core": "^2.0.0", + "@loopback/openapi-v3": "^3.0.0", + "tslib": "^1.11.1" + }, + "devDependencies": { + "@loopback/rest": "^3.0.0", + "@loopback/build": "^4.0.0", + "@loopback/eslint-config": "^6.0.0", + "@loopback/testlab": "^2.0.0", + "@types/node": "^10.17.17" + } +} diff --git a/extensions/apiconnect/src/__tests__/acceptance/apiconnect.acceptance.ts b/extensions/apiconnect/src/__tests__/acceptance/apiconnect.acceptance.ts new file mode 100644 index 000000000000..269a68330ba7 --- /dev/null +++ b/extensions/apiconnect/src/__tests__/acceptance/apiconnect.acceptance.ts @@ -0,0 +1,53 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {Application} from '@loopback/core'; +import {RestApplication, RestServer} from '@loopback/rest'; +import {expect} from '@loopback/testlab'; +import {ApiConnectBindings, ApiConnectComponent} from '../..'; +import {ApiConnectSpecOptions} from '../../apiconnect.spec-enhancer'; + +describe('Extension for IBM API Connect - OASEnhancer', () => { + let app: Application; + let server: RestServer; + beforeEach(givenAServer); + + it('adds x-ibm-configuration to apiSpec', async () => { + const EXPECTED_SPEC = { + 'x-ibm-configuration': { + assembly: { + execute: [ + { + invoke: { + title: 'invoke', + version: '2.0.0', + 'target-url': 'http://localhost:3000/test-service', + }, + }, + ], + }, + cors: {enabled: true}, + enforced: true, + phase: 'realized', + testable: true, + gateway: 'datapower-api-gateway', + }, + }; + const spec = await server.getApiSpec(); + expect(spec).to.containDeep(EXPECTED_SPEC); + }); + + async function givenAServer() { + app = new RestApplication(); + app.component(ApiConnectComponent); + const apiConnectOptions: ApiConnectSpecOptions = { + targetUrl: 'http://localhost:3000/test-service', + }; + app + .configure(ApiConnectBindings.API_CONNECT_SPEC_ENHANCER) + .to(apiConnectOptions); + server = await app.getServer(RestServer); + } +}); diff --git a/extensions/apiconnect/src/apiconnect.component.ts b/extensions/apiconnect/src/apiconnect.component.ts new file mode 100644 index 000000000000..250b34db77b3 --- /dev/null +++ b/extensions/apiconnect/src/apiconnect.component.ts @@ -0,0 +1,11 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {Component, createBindingFromClass} from '@loopback/core'; +import {ApiConnectSpecEnhancer} from './apiconnect.spec-enhancer'; + +export class ApiConnectComponent implements Component { + bindings = [createBindingFromClass(ApiConnectSpecEnhancer)]; +} diff --git a/extensions/apiconnect/src/apiconnect.spec-enhancer.ts b/extensions/apiconnect/src/apiconnect.spec-enhancer.ts new file mode 100644 index 000000000000..762a55172956 --- /dev/null +++ b/extensions/apiconnect/src/apiconnect.spec-enhancer.ts @@ -0,0 +1,51 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {bind, config} from '@loopback/core'; +import {asSpecEnhancer, OASEnhancer, OpenAPIObject} from '@loopback/openapi-v3'; + +/** + * Configuration for IBM API Connect extensions to the OpenAPI spec + */ +export type ApiConnectSpecOptions = { + targetUrl: string; +}; + +/** + * An OpenAPI spec enhancer to add `x-ibm-configuration` extension required + * by API Connect + */ +@bind(asSpecEnhancer) +export class ApiConnectSpecEnhancer implements OASEnhancer { + name = 'IBM API Connect'; + + constructor( + @config({optional: false}) private options: ApiConnectSpecOptions, + ) {} + + modifySpec(spec: OpenAPIObject): OpenAPIObject { + spec['x-ibm-configuration'] = { + assembly: { + execute: [ + { + invoke: { + title: 'invoke', + version: '2.0.0', + 'target-url': this.options.targetUrl, + }, + }, + ], + }, + cors: { + enabled: true, + }, + enforced: true, + phase: 'realized', + testable: true, + gateway: 'datapower-api-gateway', + }; + return spec; + } +} diff --git a/extensions/apiconnect/src/index.ts b/extensions/apiconnect/src/index.ts new file mode 100644 index 000000000000..b868cc6592c4 --- /dev/null +++ b/extensions/apiconnect/src/index.ts @@ -0,0 +1,8 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +export * from './apiconnect.component'; +export * from './apiconnect.spec-enhancer'; +export * from './keys'; diff --git a/extensions/apiconnect/src/keys.ts b/extensions/apiconnect/src/keys.ts new file mode 100644 index 000000000000..035d76d1da4c --- /dev/null +++ b/extensions/apiconnect/src/keys.ts @@ -0,0 +1,16 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: @loopback/apiconnect +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {BindingKey} from '@loopback/core'; +import {ApiConnectSpecEnhancer} from './apiconnect.spec-enhancer'; + +export namespace ApiConnectBindings { + /** + * Strongly-typed binding key for ApiConnectSpecEnhancer + */ + export const API_CONNECT_SPEC_ENHANCER = BindingKey.create< + ApiConnectSpecEnhancer + >('oas-enhancer.ApiConnectSpecEnhancer'); +} diff --git a/extensions/apiconnect/tsconfig.build.json b/extensions/apiconnect/tsconfig.build.json new file mode 100644 index 000000000000..4435a00cd154 --- /dev/null +++ b/extensions/apiconnect/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "@loopback/build/config/tsconfig.common.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": [ + "src" + ] +}