Skip to content

Commit

Permalink
Merge 073b76d into fecd815
Browse files Browse the repository at this point in the history
  • Loading branch information
Nataniel López committed Apr 26, 2022
2 parents fecd815 + 073b76d commit d6b4ca9
Show file tree
Hide file tree
Showing 12 changed files with 877 additions and 117 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- `additionalFields` getter in **ModelClient** for customizing client fields
- **API Client Created** and **EventListener Client Created** `postSaveHook()` receives the created client object in second parameter.

## [5.2.5] - 2021-12-02
### Fixed
Expand Down
67 changes: 59 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ To skip the fetch of the credentials, it can be used the setting `skipFetchCrede
}
```

### ClientModel
### :sparkles::new::sparkles: ClientModel
At `./[MS_PATH]/models/client.js`

```js
Expand All @@ -157,6 +157,50 @@ const { ModelClient } = require('@janiscommerce/client-creator');
module.exports = ModelClient;
```

:new: **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.

> #### :information_source: This will affect Client Created API and EventListener and also Client Updated EventListener behavior
> 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.
#### Example:
```js
'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:
```json
{
"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:
```json
{
"name": "Some Client",
"code": "some-client",
"myAdditionalField": "some-additional-data",
"anotherAdditionalField": "another-additional-data"
}
```

### APICreate
At `./[MS_PATH]/api/client/post.js`

Expand Down Expand Up @@ -262,11 +306,12 @@ The `APICreate` and `listeners` have a hook for post processing the client or cl

#### APICreate

#### `postSaveHook(clientCodes)`
Receives the clientCodes from the API.
#### `postSaveHook(clientCodes, clients)`
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.

##### Example
```js
Expand All @@ -275,25 +320,30 @@ const { APICreate } = require('@janiscommerce/client-creator');

class ClientCreateAPI extends APICreate {

async postSaveHook(clientCodes) {
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}`)
})
}
}

module.exports = ClientCreateAPI;
```

#### Listener Created
#### `postSaveHook(clientCode)`
Receives the clientCode from the event.
#### `postSaveHook(clientCode, client)`
Receives the clientCode and client from the event.

Parameters:
- clientCode `string`: The client created code.gs of the created client.
- clientCode `string`: The client created code of the created client.
- client `object`: The client created object that was saved.

It can be implemented as the example bellow:
##### Example
Expand All @@ -304,8 +354,9 @@ const { ListenerCreated } = require('@janiscommerce/client-creator');

class ClientCreateListener extends ListenerCreated {

async postSaveHook(clientCode) {
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`)
}
}

Expand Down
21 changes: 16 additions & 5 deletions lib/api-create.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
'use strict';

const logger = require('lllog')();

const { API } = require('@janiscommerce/api');
const { struct } = require('@janiscommerce/superstruct');

const { Invoker } = require('@janiscommerce/lambda');

const ModelFetcher = require('./helpers/model-fetcher');
const ModelClient = require('./model-client');
const getClients = require('./helpers/get-clients');

module.exports = class ClientCreateAPI extends API {

Expand All @@ -18,17 +20,26 @@ module.exports = class ClientCreateAPI extends API {

async process({ clients: clientCodes } = this.data) {

const clientsToCreate = await ModelClient.formatForCreate(clientCodes);

const ClientModel = ModelFetcher.get(); // se tiene que usar el modelo del servicio

const model = new ClientModel();

const clients = ClientModel.validateAdditionalFields() ? await getClients(clientCodes) : clientCodes.map(code => ({ code }));

if(!clients) {
logger.error('Unable to get Janis ID clients, they won\'t be created.');
return;
}

if(clients.length !== clientCodes.length)
logger.warn('Some clients couldn\'t be obtained from Janis ID service, they won\'t be created.');

const clientsToCreate = await ClientModel.formatForCreate(clients);

await model.multiSave(clientsToCreate);

await Invoker.call('MongoDBIndexCreator');

return this.postSaveHook(clientCodes);
return this.postSaveHook(clientCodes, clientsToCreate);
}

/**
Expand Down
16 changes: 14 additions & 2 deletions lib/helpers/client-formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,24 @@ module.exports = class ClientFormatter {
return this._statusActive;
}

static format(code) {
return {
static format({ code, ...client }, additionalFields) {

const formattedClient = {
code,
databases: this.prepareDatabases(code),
status: this.statusActive
};

if(additionalFields) {

additionalFields.forEach(field => {

if(typeof client[field] !== 'undefined')
formattedClient[field] = client[field];
});
}

return formattedClient;
}

static prepareDatabases(code) {
Expand Down
17 changes: 17 additions & 0 deletions lib/helpers/get-clients.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const MicroserviceCall = require('@janiscommerce/microservice-call');

module.exports = async clientCodes => {

const msCall = new MicroserviceCall();

const { statusCode, body } = await msCall.safeList('id', 'client', { filters: { clientCode: clientCodes }, limit: clientCodes.length });

if(statusCode >= 500) {
const errorMessage = body && body.message ? `${body.message}` : 'Service failed';
throw new Error(`Failed to get Janis ID clients: ${errorMessage}`);
}

return statusCode < 400 && body.length && body;
};
23 changes: 18 additions & 5 deletions lib/listener-created.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use strict';

const logger = require('lllog')();

const { EventListener } = require('@janiscommerce/event-listener');

const MongoDBIndexCreator = require('@janiscommerce/mongodb-index-creator');

const ModelFetcher = require('./helpers/model-fetcher');
const ModelClient = require('./model-client');
const getClients = require('./helpers/get-clients');

const mongoDBIndexCreator = new MongoDBIndexCreator();

Expand All @@ -19,17 +21,28 @@ module.exports = class ClientCreatedListener extends EventListener {

const clientCode = this.eventId;

const formattedClient = await ModelClient.formatForCreate(clientCode);

const ClientModel = ModelFetcher.get(); // se tiene que usar el modelo del servicio

const model = new ClientModel();

const client = ClientModel.validateAdditionalFields() ? await this.getClient(clientCode) : { code: clientCode };

if(!client) {
logger.error('Unable to get Janis ID client, it won\'t be created.');
return;
}

const [formattedClient] = await ClientModel.formatForCreate([client]);

await model.save(formattedClient);

await mongoDBIndexCreator.executeForClientCode(clientCode);

return this.postSaveHook(clientCode);
return this.postSaveHook(clientCode, formattedClient);
}

async getClient(clientCode) {
const client = await getClients([clientCode]);
return client && client[0];
}

/**
Expand Down
38 changes: 26 additions & 12 deletions lib/listener-updated.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const logger = require('lllog')();

const { EventListener } = require('@janiscommerce/event-listener');
const MicroserviceCall = require('@janiscommerce/microservice-call');

Expand All @@ -17,8 +19,10 @@ module.exports = class ClientUpdatedListener extends EventListener {

const updatedClient = await this.getUpdatedClient(clientId);

if(!updatedClient)
if(!updatedClient) {
logger.error('Unable to get Janis ID client, it won\'t be updated.');
return;
}

await this.updateServiceClient(updatedClient);

Expand All @@ -29,26 +33,36 @@ module.exports = class ClientUpdatedListener extends EventListener {

const msCall = new MicroserviceCall();

const response = await msCall.safeCall('id', 'client', 'get', null, null, { id: clientId });
const { statusCode, body } = await msCall.safeCall('id', 'client', 'get', null, null, { id: clientId });

if(msCall.shouldRetry(response)) {
const msCallError = (response.body && response.body.message) ? `${response.body.message}` : 'Unable to get Janis ID client';
throw new Error(msCallError);
if(statusCode >= 500) {
const errorMessage = body && body.message ? `${body.message}` : 'Service failed';
throw new Error(`Failed to get Janis ID client: ${errorMessage}`);
}

return response.statusCode < 400 && response.body;
return statusCode < 400 && body;
}

updateServiceClient(updatedClient) {
updateServiceClient({ code, status, ...updatedClient }) {

const ClientModel = ModelFetcher.get();
const model = new ClientModel();

return model.update({
status: updatedClient.status
}, {
code: updatedClient.code
});
const fieldsToUpdate = { status };
const fieldsToRemove = {};

if(ClientModel.validateAdditionalFields()) {

ClientModel.additionalFields.forEach(fieldName => {

if(typeof updatedClient[fieldName] !== 'undefined')
fieldsToUpdate[fieldName] = updatedClient[fieldName];
else
fieldsToRemove[fieldName] = '';
});
}

return model.update({ ...fieldsToUpdate, ...Object.keys(fieldsToRemove).length && { $unset: fieldsToRemove } }, { code });
}

/**
Expand Down
24 changes: 17 additions & 7 deletions lib/model-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,27 @@ module.exports = class Client extends Model {
return ['databases'];
}

static async formatForCreate(clientCodes) {
/**
* Get additional fields
* @returns {string[]|undefined} returns undefined by default
*/
static get additionalFields() {
return undefined;
}

await ClientFormatter.prepareSettings();
static validateAdditionalFields() {

const isMultiple = Array.isArray(clientCodes);
if(!this.additionalFields)
return;

if(!isMultiple)
clientCodes = [clientCodes];
if(!Array.isArray(this.additionalFields))
throw new Error('Invalid getter \'additionalFields\': Should be an array.');

const formattedClients = clientCodes.map(clientCode => ClientFormatter.format(clientCode));
return !!this.additionalFields.length;
}

return isMultiple ? formattedClients : formattedClients[0];
static async formatForCreate(clients) {
await ClientFormatter.prepareSettings();
return clients.map(client => ClientFormatter.format(client, this.additionalFields));
}
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@janiscommerce/model": "^5.5.0",
"@janiscommerce/mongodb-index-creator": "^2.3.0",
"@janiscommerce/settings": "^1.0.1",
"@janiscommerce/superstruct": "^1.2.0"
"@janiscommerce/superstruct": "^1.2.0",
"lllog": "^1.1.2"
}
}
Loading

0 comments on commit d6b4ca9

Please sign in to comment.