nut-ioc
v1.3.4
Published
a simple, lightweight and fast IoC Container Framework
Downloads
46
Readme
nut-ioc
a simple, lightweight and fast IoC Container Framework
NPM link
https://www.npmjs.com/package/nut-ioc
nut-ioc injects dependencies run-time so that developers don't need to require modules.
Developers can implement in their codes following OOP basics, principles, patterns and concepts and probably more than that :)
- Separation of Concern(SoC)
- Single Responsibility Principle(SRP)
- Open Closed Principle
- Dipendency Inversion(Injection) Principle(DIP)
- Chain of Responsibility Pattern
- Aspect Oriented Programming
Installing nut-ioc with npm
npm i nut-ioc
Demo GitHub Repository for TypeScript
README file is inside the following repository.
https://github.com/nodejs-projects-kenanhancer/nut-ioc-typescript-simple-demo
Demo GitHub Repository for CommonJS
You can find different usages of nut-ioc framework in separate branchs.
https://github.com/nodejs-projects-kenanhancer/nut-ioc-basic-demo.git
Branch list | ------------------------------------------------------ | load-dependencies-with-dependencyPath | load-dependencies-with-dependencyPath-and_dynamically | load-dependencies-with-different-loaders | load-dependencies-with-interceptors | load-dependencies-with-new-loaders-and-filters | load-dependencies-with-programatic-notation | nut-swagger-usage |
Real life Example
This example code is very simple. But, developers never have this kind of simple scenario in real life project.
Classic code
Suppose that we have greeting service like below. This code example is very usual in Node.js world.
helper.js
const helper = {
getFullName: ({firstName, lastName})=>{
return `${firstName} ${lastName}`;
}
};
module.exports = helper;
greeting-service.js
const helper = require('./helper');
const greetingService = {
sayHello: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
};
module.exports = greetingService;
index.js
const greetingService = require('./greeting-service');
const helloMsg = greetingService.sayHello({firstName: "kenan", lastName: "hancer"});
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye({firstName: "kenan", lastName: "hancer"});
console.log(goodBydMsg);
nut-ioc Syntax
nut-ioc can use your node.js modules automatically. But, you need to export from your module and nut-ioc specific object.
Dependency Basic Syntax
No need to specify ServiceName and Namespace.
But if you need to call your dependency as a nested object, then use the following notation in Namespace
field.
helper.js
module.exports.ServiceName = ""; //fileName if empty,null or undefined
module.exports.Namespace = "business.logic.helpers"; //if empty, then consume helper dependency with name directly
module.exports.Service = ({
getFullName: ({ firstName, lastName }) => {
return `${firstName} ${lastName}`;
}
});
now in order to use helper
dependency in other dependency as below
greeting-service.js
module.exports.Service = ({ business: { logic: { helper } } }) =>
({
sayHello: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
});
you can consume helper.js node.js module with helper name. But, if you don't want to update fileName, then you can change serviceName in ServiceName field.
if you want to export any object or function, then use Service field.
helper.js
module.exports.ServiceName = ""; //fileName if empty,null or undefined
module.exports.Namespace = ""; //if empty, then consume helper dependency with name directly
module.exports.Service = ({
getFullName: ({ firstName, lastName }) => {
return `${firstName} ${lastName}`;
}
});
Dependency Basic Constructor Syntax
As you can see I didn't use ServiceName and Namespace fields, those fields will have default values.
nut-ioc is injecting dependencies from function always so if you have any dependency, use module.exports.Service = ({ helper }) =>
this syntax then you can use helper dependency in your code, then this constructor function should return an object or function.
one more time, if you have any dependency you should return one function(constructor function) and that constructor function should return an object or direct function.
greeting-service.js
module.exports.Service = ({ helper }) =>
({
sayHello: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
});
nut-ioc loading dependencies with directory path
helper.js
module.exports.ServiceName = ""; //fileName if empty,null or undefined
module.exports.Service = ({
getFullName: ({ firstName, lastName }) => {
return `${firstName} ${lastName}`;
}
});
greeting-service.js
module.exports.ServiceName = ""; //fileName if empty,null or undefined
module.exports.Service = ({ helper }) =>
({
sayHello: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = helper.getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
});
if you want to ignore some files or folder in your project, then use ignoredDependencies field in use function as below.
For example, node_modules folder has many folder and files, so you should ignore that folder.
index.js
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
const ignoredDependencies = ['node_modules',
'.env',
'*.json',
'.idea',
'.git',
'.gitignore',
'*.iml',
'.*',
'*.md',
'LICENSE'];
nutIocContainer.use({ dependencyPath: './', ignoredDependencies });
const { greetingService } = await nutIocContainer.build();
const helloMsg = greetingService.sayHello({ firstName: "kenan", lastName: "hancer" });
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye({ firstName: "kenan", lastName: "hancer" });
console.log(goodBydMsg);
};
mainAsync();
nut-ioc loading dependencies with programatic dependency definition
you don't have to write your code in JavaScript files, nut-ioc is definition specific framework, so you just provide your dependency definition programmaticaly then nut-ioc will do its job again :)
index.js
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
nutIocContainer.useDependency({
ServiceName: "authorBasicInfo",
Service: ({ firstName: "Kenan", lastName: "Hancer" })
});
nutIocContainer.useDependency({
ServiceName: "authorWithContacts",
Service: ({ authorBasicInfo }) => ({ ...authorBasicInfo, city: "London", mail: "[email protected]" })
});
nutIocContainer.useDependency({
ServiceName: "greetingHelper",
Service: ({ }) => ({
getFullName: ({ firstName, lastName }) => `${firstName} ${lastName}`
})
});
nutIocContainer.useDependency({
ServiceName: "greetingService",
Service: ({ greetingHelper: { getFullName } }) => ({
sayHello: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
})
});
const { authorWithContacts, greetingService } = await nutIocContainer.build();
const helloMsg = greetingService.sayHello(authorWithContacts);
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye(authorWithContacts);
console.log(goodBydMsg);
};
mainAsync();
nut-ioc loading dependencies with directory path and programatic dependency definition
index.js
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
const ignoredDependencies = ['node_modules',
'.env',
'*.json',
'.idea',
'.git',
'.gitignore',
'*.iml',
'.*',
'*.md',
'LICENSE'];
nutIocContainer.use({ dependencyPath: './', ignoredDependencies });
nutIocContainer.useDependency({
ServiceName: "authorBasicInfo",
Service: ({firstName: "Kenan", lastName: "Hancer"})
});
nutIocContainer.useDependency({
ServiceName: "authorWithContacts",
Service: ({authorBasicInfo}) => ({...authorBasicInfo, city: "London", mail: "[email protected]"})
});
const { greetingService } = await nutIocContainer.build();
const helloMsg = greetingService.sayHello(authorWithContacts);
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye(authorWithContacts);
console.log(goodBydMsg);
};
mainAsync();
nut-ioc loading dependencies with interceptors
I think that this is the most delicious part of code. The benefit of nut-ioc is not only Dependency Injection in run-time, nut-ioc can intercept your function calls. So that you can implement Aspect Oriented Programming, Separation of Concern etc :)
nut-ioc decreases your development time on any project and provide you many of best programming practices.
index.js
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
nutIocContainer.useDependency({
IsInterceptor: true,
ServiceName: "errorInterceptor",
Namespace: "interceptors",
Service: ({ }) =>
(environment, next) => {
let result;
try {
result = next(environment);
} catch (error) {
appLogger.error(`ERROR: ${`${environment.moduleName}.${environment.method.name}`} method`, error);
throw error;
}
return result;
}
});
nutIocContainer.useDependency({
IsInterceptor: true,
ServiceName: "logInterceptor",
Namespace: "interceptors",
Service: ({ }) =>
(environment, next) => {
const { method, args } = environment;
console.log(`ENTRY: ${method.name}(${JSON.stringify(args[0])}) function`)
const startDate = new Date();
const result = next(environment);
const elapsedMilliseconds = new Date() - startDate;
console.log(`SUCCESS: ${method.name} function returns //${result}: Elapsed milliseconds is ${elapsedMilliseconds}`);
return result;
}
});
nutIocContainer.useDependency({
ServiceName: "authorBasicInfo",
Service: ({ firstName: "Kenan", lastName: "Hancer" })
});
nutIocContainer.useDependency({
ServiceName: "authorWithContacts",
Service: ({ authorBasicInfo }) => ({ ...authorBasicInfo, city: "London", mail: "[email protected]" })
});
nutIocContainer.useDependency({
ServiceName: "greetingHelper",
Service: ({ }) => ({
getFullName: ({ firstName, lastName }) => `${firstName} ${lastName}`
}),
Interceptor: ({ interceptors: { errorInterceptor, logInterceptor } }) => {
return [errorInterceptor, logInterceptor];
}
});
nutIocContainer.useDependency({
ServiceName: "greetingService",
Service: ({ greetingHelper: { getFullName } }) => ({
sayHello: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
}),
Interceptor: ({ interceptors: { errorInterceptor, logInterceptor } }) => {
return [errorInterceptor, logInterceptor];
}
});
const { authorWithContacts, greetingService } = await nutIocContainer.build();
const helloMsg = greetingService.sayHello(authorWithContacts);
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye(authorWithContacts);
console.log(goodBydMsg);
};
mainAsync();
Output of above code
As you can see from output, it should function calls sequentialy with parameters and elapsed milliseconds. This is very simple implementation of nut-ioc, I am sure that you can extend this example better than me :)
$ node index
ENTRY: sayHello({"firstName":"Kenan","lastName":"Hancer","city":"London","mail":"[email protected]"}) function
ENTRY: getFullName({"firstName":"Kenan","lastName":"Hancer"}) function
SUCCESS: getFullName function returns //Kenan Hancer: Elapsed milliseconds is 0
SUCCESS: sayHello function returns //Hello Kenan Hancer: Elapsed milliseconds is 0
Hello Kenan Hancer
ENTRY: sayGoodbye({"firstName":"Kenan","lastName":"Hancer","city":"London","mail":"[email protected]"}) function
ENTRY: getFullName({"firstName":"Kenan","lastName":"Hancer"}) function
SUCCESS: getFullName function returns //Kenan Hancer: Elapsed milliseconds is 0
SUCCESS: sayGoodbye function returns //Goodbye, Kenan Hancer: Elapsed milliseconds is 0
Goodbye, Kenan Hancer
nut-ioc loading and grouping YAML and JSON dependencies
I thought that nut-ioc can do more that above features. So, I added dependency loader functionality, there are three default loaders in nut-ioc (node.js module, JSON, YAML dependency loaders)
In addition to this, if you want to group dependencies under one folder and later consume with folder name, then you need to add metadata.js file under folder. nut-ioc will collect all dependencies under swaggerDefinitions variable in run-time. Notice that metadata.js content standard nut-ioc dependency definition file, so if you don't want to use folder name as a group variable name then just use Namespace field :)
swagger-definitions/__metadata__.js
module.exports = {
Namespace: "",
ServiceName: "", //fileName if empty,null or undefine
Service: ({ }) => {
}
};
swagger-definitions/greeting-definition-yaml.yaml
swagger: '2.0'
info:
description: English Greeting API
version: 1.0.0
title: English Greeting API
basePath: /greeting-api/v1
schemes:
- http
paths:
/sayHello:
get:
summary: Say English Hello Message
operationId: greetingService.sayHello
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
/sayGoodbye:
get:
summary: Say English Goodbye Message
operationId: greetingService.sayGoodbye
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
swagger-definitions/greeting-definition-json.json
{
"swagger": "2.0",
"info": {
"description": "English Greeting API",
"version": "1.0.0",
"title": "English Greeting API"
},
"basePath": "/greeting-api/v1",
"schemes": [
"http"
],
"paths": {
"/sayHello": {
"get": {
"summary": "Say English Hello Message",
"operationId": "greetingService.sayHello",
"produces": [
"application/json"
],
"parameters": [
{
"name": "firstName",
"in": "header",
"type": "string",
"maxLength": 100,
"required": true,
"description": "Person First Name."
},
{
"name": "lastName",
"in": "header",
"type": "string",
"maxLength": 100,
"required": true,
"description": "Person Last Name."
}
],
"responses": {
"200": {
"description": "success"
}
}
}
},
"/sayGoodbye": {
"get": {
"summary": "Say English Goodbye Message",
"operationId": "greetingService.sayGoodbye",
"produces": [
"application/json"
],
"parameters": [
{
"name": "firstName",
"in": "header",
"type": "string",
"maxLength": 100,
"required": true,
"description": "Person First Name."
},
{
"name": "lastName",
"in": "header",
"type": "string",
"maxLength": 100,
"required": true,
"description": "Person Last Name."
}
],
"responses": {
"200": {
"description": "success"
}
}
}
}
}
}
index.js
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
nutIocContainer.useDependency({
IsInterceptor: true,
ServiceName: "errorInterceptor",
Namespace: "interceptors",
Service: ({ }) =>
(environment, next) => {
let result;
try {
result = next(environment);
} catch (error) {
appLogger.error(`ERROR: ${`${environment.moduleName}.${environment.method.name}`} method`, error);
throw error;
}
return result;
}
});
nutIocContainer.useDependency({
IsInterceptor: true,
ServiceName: "logInterceptor",
Namespace: "interceptors",
Service: ({ }) =>
(environment, next) => {
const { method, args } = environment;
console.log(`ENTRY: ${method.name}(${JSON.stringify(args[0])}) function`)
const startDate = new Date();
const result = next(environment);
const elapsedMilliseconds = new Date() - startDate;
console.log(`SUCCESS: ${method.name} function returns //${result}: Elapsed milliseconds is ${elapsedMilliseconds}`);
return result;
}
});
nutIocContainer.useDependency({
ServiceName: "authorBasicInfo",
Service: ({ firstName: "Kenan", lastName: "Hancer" })
});
nutIocContainer.useDependency({
ServiceName: "authorWithContacts",
Service: ({ authorBasicInfo }) => ({ ...authorBasicInfo, city: "London", mail: "[email protected]" })
});
nutIocContainer.useDependency({
ServiceName: "greetingHelper",
Service: ({ }) => ({
getFullName: ({ firstName, lastName }) => `${firstName} ${lastName}`
}),
Interceptor: ({ interceptors: { errorInterceptor, logInterceptor } }) => {
return [errorInterceptor, logInterceptor];
}
});
nutIocContainer.useDependency({
ServiceName: "greetingService",
Service: ({ greetingHelper: { getFullName } }) => ({
sayHello: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
}),
Interceptor: ({ interceptors: { errorInterceptor, logInterceptor } }) => {
return [errorInterceptor, logInterceptor];
}
});
nutIocContainer.use({ dependencyPath: './swagger-definitions' });
const { authorWithContacts, greetingService, swaggerDefinitions } = await nutIocContainer.build();
const helloMsg = greetingService.sayHello(authorWithContacts);
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye(authorWithContacts);
console.log(goodBydMsg);
console.log();
console.log('swaggerDefinitions:', swaggerDefinitions);
};
mainAsync();
Output of above code
Notice that swaggerDefinitions is written in output console, greeting-definition-json.json and greeting-definition-yaml.yaml files are converted to JavaScript object in run-time.
$ node index
ENTRY: sayHello({"firstName":"Kenan","lastName":"Hancer","city":"London","mail":"[email protected]"}) function
ENTRY: getFullName({"firstName":"Kenan","lastName":"Hancer"}) function
SUCCESS: getFullName function returns //Kenan Hancer: Elapsed milliseconds is 0
SUCCESS: sayHello function returns //Hello Kenan Hancer: Elapsed milliseconds is 0
Hello Kenan Hancer
ENTRY: sayGoodbye({"firstName":"Kenan","lastName":"Hancer","city":"London","mail":"[email protected]"}) function
ENTRY: getFullName({"firstName":"Kenan","lastName":"Hancer"}) function
SUCCESS: getFullName function returns //Kenan Hancer: Elapsed milliseconds is 0
SUCCESS: sayGoodbye function returns //Goodbye, Kenan Hancer: Elapsed milliseconds is 0
Goodbye, Kenan Hancer
swaggerDefinitions: {
greetingDefinitionJson: {
swagger: '2.0',
info: {
description: 'English Greeting API',
version: '1.0.0',
title: 'English Greeting API'
},
basePath: '/greeting-api/v1',
schemes: [ 'http' ],
paths: { '/sayHello': [Object], '/sayGoodbye': [Object] }
},
greetingDefinitionYaml: {
swagger: '2.0',
info: {
description: 'English Greeting API',
version: '1.0.0',
title: 'English Greeting API'
},
basePath: '/greeting-api/v1',
schemes: [ 'http' ],
paths: { '/sayHello': [Object], '/sayGoodbye': [Object] }
}
}
nut-ioc loading dependencies with new dependency loaders and filters
I thought that this features will never be enough, as I said before, nut-ioc has YAML, JSON, Node.js module loaders by default, but if you need to load CSV, CSS, JPEG, TXT, XML, HTML, BSON files as a JavaScript object or string, then you can inject new dependency loaders in nut-ioc with useConfiguration or useDependencyLoader functions.
There is also dependency filter functionality in nut-ioc. nut-ioc already has one default dependency filter which filters ignored files. But, if you need more custom filters then use useConfiguration or useDependencyLoader functions.
Shortly, nut-ioc can use your custom dependency loaders and filters in run-time.
index.js
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
nutIocContainer.useDependency({
IsInterceptor: true,
ServiceName: "errorInterceptor",
Namespace: "interceptors",
Service: ({ }) =>
(environment, next) => {
let result;
try {
result = next(environment);
} catch (error) {
appLogger.error(`ERROR: ${`${environment.moduleName}.${environment.method.name}`} method`, error);
throw error;
}
return result;
}
});
nutIocContainer.useDependency({
IsInterceptor: true,
ServiceName: "logInterceptor",
Namespace: "interceptors",
Service: ({ }) =>
(environment, next) => {
const { method, args } = environment;
console.log(`ENTRY: ${method.name}(${JSON.stringify(args[0])}) function`)
const startDate = new Date();
const result = next(environment);
const elapsedMilliseconds = new Date() - startDate;
console.log(`SUCCESS: ${method.name} function returns //${result}: Elapsed milliseconds is ${elapsedMilliseconds}`);
return result;
}
});
nutIocContainer.useDependency({
ServiceName: "authorBasicInfo",
Service: ({ firstName: "Kenan", lastName: "Hancer" })
});
nutIocContainer.useDependency({
ServiceName: "authorWithContacts",
Service: ({ authorBasicInfo }) => ({ ...authorBasicInfo, city: "London", mail: "[email protected]" })
});
nutIocContainer.useDependency({
ServiceName: "greetingHelper",
Service: ({ }) => ({
getFullName: ({ firstName, lastName }) => `${firstName} ${lastName}`
}),
Interceptor: ({ interceptors: { errorInterceptor, logInterceptor } }) => {
return [errorInterceptor, logInterceptor];
}
});
nutIocContainer.useDependency({
ServiceName: "greetingService",
Service: ({ greetingHelper: { getFullName } }) => ({
sayHello: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Hello ${fullName}`;
},
sayGoodbye: ({ firstName, lastName }) => {
const fullName = getFullName({ firstName, lastName });
return `Goodbye, ${fullName}`;
}
}),
Interceptor: ({ interceptors: { errorInterceptor, logInterceptor } }) => {
return [errorInterceptor, logInterceptor];
}
});
nutIocContainer.useConfiguration({
dependencyLoader: ({loaders}) => {
// console.log(loaders);
},
dependencyFilter: ({filters}) => {
// delete filters['defaultModuleFilter'];
// console.log(filters);
}
});
nutIocContainer.useDependencyLoader({
name: 'test-dependency-loader',
loader: ({filePath, nameProvider}) => {
// console.log();
}
});
nutIocContainer.useDependencyLoader({
name: 'test-dependency-loader-2',
loader: ({filePath, nameProvider}) => {
// console.log();
}
});
nutIocContainer.useDependencyFilter({
name: 'test-dependency-filter',
filter: ({filePath, ignoredDependencies}) => {
// console.log();
return true;
}
});
nutIocContainer.useDependencyFilter({
name: 'test-dependency-filter-2',
filter: ({filePath, ignoredDependencies}) => {
// console.log();
return true;
}
});
nutIocContainer.use({ dependencyPath: './swagger-definitions' });
const { authorWithContacts, greetingService, swaggerDefinitions } = await nutIocContainer.build();
const helloMsg = greetingService.sayHello(authorWithContacts);
console.log(helloMsg);
const goodBydMsg = greetingService.sayGoodbye(authorWithContacts);
console.log(goodBydMsg);
console.log();
console.log('swaggerDefinitions:', swaggerDefinitions);
};
mainAsync();
nut-ioc dependency hooks
Assume that there is downstream swagger documents, and you need to update host field for every environment like dev, test, prod, etc.
So, after all dependencies are constructed, you need to update host field of swagger definition, to do that you can define a hook service, and update any dependency.
You just need to use IsHook feature in nut-ioc services as below index.js code.
swagger-downstream-definitions/__metadata__.js
module.exports = {
Namespace: "",
ServiceName: "", //fileName if empty,null or undefine
Service: ({ }) => {
}
};
swagger-downstream-definitions/greeting-english-definition.yaml
swagger: '2.0'
info:
description: English Greeting API
version: 1.0.0
title: English Greeting API
host: localhost:9090
basePath: /greeting-english-api/v1
schemes:
- http
paths:
/sayHello:
get:
summary: Say English Hello Message
operationId: controllers.greetingEnglishService.sayHello
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
/sayGoodbye:
get:
summary: Say English Goodbye Message
operationId: controllers.greetingEnglishService.sayGoodbye
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
swagger-downstream-definitions/greeting-turkish-definition.yaml
swagger: '2.0'
info:
description: Turkish Greeting API
version: 1.0.0
title: Turkish Greeting API
host: localhost:9090
basePath: /greeting-turkish-api/v1
schemes:
- http
paths:
/sayHello:
get:
summary: Say Turkish Hello Message
operationId: controllers.greetingTurkishService.sayHello
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
/sayGoodbye:
get:
summary: Say Turkish Goodbye Message
operationId: controllers.greetingTurkishService.sayGoodbye
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
swagger-downstream-definitions/greeting-helper-definition.yaml
swagger: '2.0'
info:
description: Greeting Helper API
version: 1.0.0
title: Greeting Helper API
host: localhost:9090
basePath: /greeting-helper-api/v1
schemes:
- http
paths:
/getFullName:
get:
summary: Get Full Name
operationId: controllers.greetingHelperService.getFullName
produces:
- application/json
parameters:
- name: firstName
in: header
type: string
maxLength: 100
required: true
description: Person First Name.
- name: lastName
in: header
type: string
maxLength: 100
required: true
description: Person Last Name.
responses:
'200':
description: success
.env
# Downstream-service(ds) urls
ds.greetingEnglishDefinition.host="localhost:1080"
ds.greetingTurkishDefinition.host="localhost:1080"
ds.greetingHelperDefinition.host="localhost:1080"
# Current-service(cs) urls
cs.greetingDefinition.host="localhost:8080"
cs.greetingDefinitionV2.host="localhost:8080"
index.js
require('dotenv').config();
const nutIoc = require('nut-ioc');
const nutIocContainer = nutIoc();
const mainAsync = async () => {
nutIocContainer.useDependency({
ServiceName: "appEnv",
Namespace: undefined,
Service: { ...process.env }
});
nutIocContainer.use({ dependencyPath: './swagger-downstream-definitions' });
nutIocContainer.useDependency({
IsHook: true,
ServiceName: "swaggerDownstreamDefinitionsUpdateHook",
Namespace: undefined,
Service: ({swaggerDownstreamDefinitions, appEnv}) => {
Object.entries(appEnv).filter(([key, value]) => key.includes('ds.')).forEach(([key, value]) => {
const [group, serviceName, fieldName] = key.split('.');
swaggerDownstreamDefinitions[serviceName][fieldName] = value;
});
}
});
};
mainAsync();