Wrapping NPM Packages as a Service Provider in AdonisJs

Search for a command to run...

No comments yet. Be the first to comment.
Several times, I have been involved in starting a project/feature and realising that there exist issues that are yet to be discussed, either with external teams, other departments, or the relations team of a third-party provider. This has made me spe...

The SOLID principles are a set of five principles, amongst others, guiding how software is designed to be less fragile, less rigid, more testable, maintainable, and readable. It influences how we write code in such a way that future changes do not th...

GraphQL is a query language and a runtime. As a query language, unlike SQL(Structured Query Language), it never interacts with a database. It speaks with the API directly about what it needs and a server-side program that runs your queries using the ...
I recently installed Bun on my windows system. This article is a step-by-step guide on the process involved in doing so. It also includes the challenges I went through to ensure a successful installation. I will assume you have wsl on your local mach...
Disclaimer: This write-up is not written to tell you which is better or which will come out victorious. Instead, the writer seeks to help you understand what they are and the inherent differences between the two of them. The internet today is at an a...
AdonisJs makes creating APIs fun, it makes dependency importing into a file easy with the use global method. It gives the developer a central point to configure their dependencies and bind it to the IOC container. To read about the IOC container click here.
This article will show you how to use AdonisJs service providers to achieve all the benefits mentioned earlier, including configuring different dependencies serving a similar purpose to have a single interface and a central point to switch from one dependency to the other without altering the code.
I will be demonstrating using the Twilio Node.js helper library, I will assume you are already working with AdonisJs but if you need to learn about adonisJs you can follow this link and have a basic understanding of object-oriented programming.
First, we install the Twilio helper library using npm, if you prefer you can use yarn. npm install twilio into the project.
So we open up the config folder and create a file in it called sms.js. The configuration object will be created in such a way that it can contain various SMS service providers configuration details. The details will be fed from the environment file.
const Env = use('Env')
module.exports = {
/*
|--------------------------------------------------------------------------
| Connection
|--------------------------------------------------------------------------
|
| Connection to be used for sending SMS.
| A connection needs to have a corresponding object below.
|
*/
connection: Env.get('SMS_CONNECTION'),
sms_sender: Env.get('SMS_SENDER'),
/*
|--------------------------------------------------------------------------
| TWILIO
|--------------------------------------------------------------------------
|
| Here we define the configuration for sending SMS via TWILIO.
|
*/
twilio: {
driver: 'twilio',
accountSid: Env.get('TWILIO_SMS_ACCOUNTS_ID'),
auth_token: Env.get('TWILIO_SMS_AUTH_TOKEN')
},
}
The connection determines which SMS service provider the system is using, sms_sender defines the number sending the SMS, twilio is the object containing the configuration details for the Twilio SMS service provider, any other service provider needed can be configured by adding the configuration object like the twilio object.
The providers folder will contain all providers and will live in the root of your app. In the providers folder we create a folder called Sms, here is where all the magic will happen.
|-- app
| |--config
| |-- providers
| |-- sms
| |-- start
In the newly created providers/sms folder, we need to have a folder where the code interacts with the npm package. the folder will be named src, which will contain an index.js file and other files for the different SMS service providers. In this demo, we will call it a Twilio.js file which will contain the class that interacts with the Twilio node.js helper function.
const Twilio = require('twilio')
class TwilioDriver {
constructor (config, sender) {
this.config = config
this.messageBody = null
this.sendTo = null
this.sender = sender
}
to (to) {
this.sendTo = to
return this
}
body (body) {
this.messageBody = body
return this
}
async sendSms () {
const client = Twilio (this.config.accountSid, this.config.auth_token)
return await client.messages.create ({
body: this.messageBody,
from: this.sender,
to: this.sendTo
})
}
}
module.exports = TwilioDriver
Next, we create an index.js file in the src folder, the file will require other files in the src folder, pass it into an object and export the object. The index.js file will look like this:
module.exports = {
twilio: require('./Twilio')
}
This file takes in the config file and the index.js file from the src folder, it will reside in the Sms folder. It takes in the connection property of the config file and decides which SMS service provider to instantiate.
const Driver = require('./src')
class Sms {
constructor (Config) {
this.Config = Config
}
prepare () {
/**
* Read connection name using Config
* provider
*/
const SmsConfig = this.Config.get('sms')
const name = SmsConfig.connection
const sender = SmsConfig.sms_sender
const config = SmsConfig[name]
const SmsDriver = Driver[name]
/**
* Return the instance back
*/
return new SmsDriver (config, sender)
}
}
module.exports = Sms
Here we use service provider to bind all our previous work to the IOC container. The service provider is a class we extend, it comes with a register and a boot method but we only need to use the register method. In the register method, the configuration from the config file is passed into the Sms class located in the sms/index.js file. The first parameter of this.app.bind defines the name used to address the provider when importing it later for use.
const { ServiceProvider } = require('@adonisjs/fold')
class SmsProvider extends ServiceProvider {
register () {
this.app.bind('Sms', () => {
const Config = this.app.use('Adonis/Src/Config')
return new (require('.'))(Config).prepare()
})
}
}
module.exports = SmsProvider
this.app references the ioc object, so we can use this.app.bind or this.app.singleton and it will be the same with ioc.bind or ioc.singleton
To register the newly created provider, open the app.js file in the start folder in the root of the app.
const path = require('path')
providers array const providers = [
path.join(__dirname, '..', 'providers', 'sms/Provider'),
]
const Sms = use('Sms')
config/Sms.js file, we add the class to interact with the helper library in the providers/sms/src folder to handle it. The class will contain the to method, the body method and the sendSms method. So as not to break existing code. Finally, remember to define the new name of the service provider in the .env file and let it be the name of one of the properties in the config/Sms.js file holding a configuration object.In conclusion, we have seen have to configure an NPM package as a service provider for AdonisJs, the principles remain the same and a Provider.js file is always necessary, the rest are defined based on the needs of the developer.