This package includes all the generic functionality to create, update and remove a client from the services. Its main purpose is to avoid code repetition.
npm install @janiscommerce/client-creator
Since 7.1.0
Retrieves database configurations for clients directly from AWS Parameter Store {process.env.JANIS_SERVICE_NAME}-databases
and store configuration in db
new field
Parameter Store expected parsed content
{
"newClientsDatabases": {
"default": "6728b0de39a492eee4fcdaa8"
}
}
Client created
{
"code": "client-code",
"db": {
"default": {
"id": "6728b0de39a492eee4fcdaa8",
"database": "service-name-client-code"
}
},
"status": "active"
}
⚠️ The client models will be dispatched using @janiscommerce/model@^8.8.0
You should configure the database config in your service for the new clients using the package Settings and the newClientsDatabases
field
{
"newClientsDatabases": {
"default": { // DB config that the new clients will use
"type": "mongodb",
"database": "janis-{{code}}" // necessary to add dynamic database name. Since 3.0.0
},
"other-database": {
"write": {
"type": "solr",
"database": "core-{{code}}"
},
"read": {
"type": "solr",
"host": "host-read-solr",
"database": "core-{{code}}"
}
}
}
}
If we create a brand-new-client
client with the previous settings, we will get the following client
{
"code": "brand-new-client",
"databases": {
"default": {
"write": {
"type": "mongodb",
"database": "janis-brand-new-client"
}
},
"other-database": {
"write": {
"type": "solr",
"database": "core-brand-new-client"
},
"read": {
"type": "solr",
"database": "core-brand-new-client"
}
}
},
"status": "active"
}
The package will get the secret using the JANIS_SERVICE_NAME environment variable.
If the secret was found, the result will be merged with the settings found in the janiscommercerc.json
in the newClientsDatabases
field.
The Secrets are stored in AWS Secrets Manager and obtained with the package @janiscommerce/aws-secrets-manager
Complete example in which the settings are obtained in the settings file and merged with the fetched credentials in AWS Secrets Manager.
In the example will be used a new client brand-new-client.
- Settings in file.
{
"newClientsDatabases": {
"default": {
"type": "mongodb",
"database": "janis-{{code}}"
}
}
}
- Secret fetched.
{
"databases": {
"default": {
"write": {
"host": "mongodb+srv://some-host.mongodb.net",
"user": "secure-user",
"password": "secure-password",
}
}
}
}
- Settings merged after fetching the Secret
{
"default": {
"write": {
"type": "mongodb",
"database": "janis-brand-new-client",
"host": "mongodb+srv://some-host.mongodb.net",
"user": "secure-user",
"password": "secure-password",
}
}
}
To skip the fetch of the credentials, it can be used the setting skipFetchCredentials
set as true.
{
"newClientsDatabases": {
"default": {
"write": {
"type": "mongodb",
"skipFetchCredentials": true,
"protocol": "mongodb+srv://",
"host": "mongodb+srv://some-host.mongodb.net",
"user": "some-user",
"password": "insecure-password"
}
}
}
}
At ./[MS_PATH]/models/client.js
'use strict';
const { ModelClient } = require('@janiscommerce/client-creator');
module.exports = ModelClient;
✨🆕✨ Additional Fields Additional fields is a getter that allows the service to customize the clients fields, this is useful when a service needs their own custom data in clients.
When a client is created or modified, the current client will be obtained from ID service and only the additional fields that exist in the getter will be saved in the service along with the basic client fields.
Examples using additionalFields()
Model configuration
'use strict';
const { ModelClient } = require('@janiscommerce/client-creator');
module.exports = class MyModelClient extends ModelClient {
static get additionalFields() {
return [
'myAdditionalField',
'anotherAdditionalField'
]
}
};
If a new client is created with these additional fields:
{
"name": "Some Client",
"code": "some-client",
"myAdditionalField": "some-additional-data",
"anotherAdditionalField": "another-additional-data",
"unusedAdditionalField": "unused-data"
}
The client will be saved in the service with only the specified additional fields:
{
"name": "Some Client",
"code": "some-client",
"myAdditionalField": "some-additional-data",
"anotherAdditionalField": "another-additional-data"
}
This Api will create new clients received in clients
parameter.
Parameters:
- clients
string Array
: The clients codes to be created. optional - processClients
boolean
: If received as true will compare Service clients with Janis ID clients and create, update or remove clients when needed. optional
File location ./[MS_PATH]/api/client/post.js
'use strict';
const { APICreate } = require('@janiscommerce/client-creator');
module.exports = APICreate;
Receives the clientCodes and clients from the API.
Parameters:
- clientCodes
string Array
: The client created codes. - clients
object Array
: The clients created objects that were saved.
ℹ️ This hook is used when received clients
or processClients
(when need to create)
Example using ApiCreate postSaveHook()
'use strict';
const { APICreate } = require('@janiscommerce/client-creator');
module.exports = class ClientCreateAPI extends APICreate {
async postSaveHook(clientCodes, clients) {
await myPostSaveMethod(clientCodes);
clientCodes.forEach(clientCode => {
console.log(`Saved client ${clientCode}, now i'm gonna do something great`);
})
clients.forEach(({ databases, status }) => {
console.log(`This epic client has ${databases.length} databases and its status is ${status}`)
})
}
};
Hook called after update clients.
ℹ️ This hook is used when received processClients
(when no need to create)
Parameters:
- clients
object
: The recently updated client.
Hook called after remove clients.
ℹ️ This hook is used when received processClients
(when found clients to remove in service)
Parameters:
- clientsCodes
string Array
: The recently removed client codes.
This listener handles a created event emitted by Janis ID service. It allows to create a new client in the core database and set a new database for him.
File location ./[MS_PATH]/event-listeners/id/client/created.js
'use strict';
const { ServerlessHandler } = require('@janiscommerce/event-listener');
const { ListenerCreated } = require('@janiscommerce/client-creator');
module.exports.handler = (...args) => ServerlessHandler.handle(ListenerCreated, ...args);
Receives the clientCode and client from the event.
Parameters:
- clientCode
string
: The client created code of the created client. - client
object
: The client created object that was saved.
Example using ListenerCreated postSaveHook()
'use strict';
const { ServerlessHandler } = require('@janiscommerce/event-listener');
const { ListenerCreated } = require('@janiscommerce/client-creator');
class ClientCreatedListener extends ListenerCreated {
async postSaveHook(clientCode, client) {
console.log(`Saved client ${clientCode}, now i'm gonna do something great`);
console.log(`Saved client has ${client.databases.length} databases! Whoaaa`)
}
}
module.exports.handler = (...args) => ServerlessHandler.handle(ClientCreatedListener, ...args);
This listener handles an updated event emitted by Janis ID service. It allows to activate or deactivate a client by changing his status.
File location ./[MS_PATH]/event-listeners/id/client/updated.js
'use strict';
const { ServerlessHandler } = require('@janiscommerce/event-listener');
const { ListenerUpdated } = require('@janiscommerce/client-creator');
module.exports.handler = (...args) => ServerlessHandler.handle(ListenerUpdated, ...args);
Receives the currentClient from the event.
Parameters:
- currentClient
object
: The recently updated client.
Example using ListenerUpdated postSaveHook()
'use strict';
const { ServerlessHandler } = require('@janiscommerce/event-listener');
const { ListenerUpdated } = require('@janiscommerce/client-creator');
class ClientUpdatedListener extends ListenerUpdated {
async postSaveHook(currentClient) {
console.log(`Saved client ${currentClient.name}, now i'm gonna do something great`);
}
}
module.exports.handler = (...args) => ServerlessHandler.handle(ClientUpdatedListener, ...args);
This listener handles a removed event emitted by Janis ID service. It allows to remove a client from the core clients database and drop his database.
File location ./[MS_PATH]/event-listeners/id/client/removed.js
'use strict';
const { ServerlessHandler } = require('@janiscommerce/event-listener');
const { ListenerRemoved } = require('@janiscommerce/client-creator');
module.exports.handler = (...args) => ServerlessHandler.handle(ListenerRemoved, ...args);
Receives the removed clientCode from the API.
Parameters:
- clientCode
string
: The client removed code.
Example using ListenerRemoved postRemovedHook()
'use strict';
const { ServerlessHandler } = require('@janiscommerce/event-listener');
const { ListenerRemoved } = require('@janiscommerce/client-creator');
class ClientRemovedListener extends ListenerRemoved {
async postRemovedHook(clientCode) {
console.log(`Saved client ${clientCode}, now i'm gonna do something great`);
}
}
module.exports.handler = (...args) => ServerlessHandler.handle(ClientRemovedListener, ...args);
The package exports clientFunctions
, an array with serverless functions to simplify the usage. It has the hooks for the Create Api and Listeners.
At ./serverless.js
'use strict';
const { helper } = require('sls-helper'); // eslint-disable-line
const { clientFunctions } = require('@janiscommerce/client-creator');
module.exports = helper({
hooks: [
// other hooks
...clientFunctions
]
});
Add schemas for the Client Created, Updated and Removed event listeners and the Create Client API post. Subscribe to events.
At ./schemas/client/
add these two files:
At ./schemas/event-listeners/id/client
add this file:
At ./events/src/id/
add this file:
The default Api and Listeners (:warning: without customization) not need to be tested.
To avoid coverage leaks, in ./.nycrc
{
"exclude": [
//... other excluded files
"src/event-listeners/id/client/",
"src/models/client.js",
"src/api/client/post.js"
]
}
⚠️ If exists any customization of the files, do not add the file to the .nycrc and add the corresponding tests.