@sonatel-os/juf
Version:
The community SDK for Orange Money, SMS, Email & Sonatel APIs on the Orange Developer Platform.
180 lines (177 loc) • 6.26 kB
JavaScript
import {
authenticationService_default
} from "./chunk-QDNKDHVC.js";
import {
EMAIL_URI,
SMS_URI,
buildAuthHeader,
validate
} from "./chunk-BXTDSY5Z.js";
import {
SMS_CHANNEL,
fromAxiosError,
getApiUrl,
logger,
requester_default
} from "./chunk-4T5F3RH2.js";
// src/communication/communication.structure.js
import { object, string, boolean, optional, define } from "superstruct";
var EmailStructure = object({
subject: string(),
to: string(),
from: string(),
body: string(),
html: optional(boolean())
});
var DateTimeString = define("DateTimeString", (value) => {
return typeof value === "string" && !isNaN(Date.parse(value));
});
var SmsStructure = object({
body: string(),
to: string(),
confidential: optional(boolean()),
scheduledFor: optional(DateTimeString),
senderName: string()
});
// src/communication/communicationService.js
var Communication = class _Communication {
/** @private @type {Authentication} */
#authService;
/** @private @type {import('axios').AxiosInstance} */
#client;
/** @private */
#logger;
/**
* Creates a Communication instance with injectable dependencies.
*
* @param {object} deps - Dependencies for the communication service.
* @param {Authentication} deps.authService - Authentication service instance.
* @param {import('axios').AxiosInstance} deps.client - HTTP client instance.
* @param {object} deps.logger - Logger instance with error/warn/info/debug methods.
*/
constructor({ authService, client, logger: logger2 }) {
this.#authService = authService;
this.#client = client;
this.#logger = logger2;
}
/**
* Factory method to initialize Communication with default dependencies.
* @method init
* @memberof Service\Communication
* @param {object} [deps] - Optional shared dependencies.
* @param {Authentication} [deps.authService] - Shared auth instance (avoids duplicate token fetches).
* @returns {Communication} An initialized instance of Communication.
*/
static init({ authService } = {}) {
return new _Communication({
authService: authService || authenticationService_default.init(),
client: requester_default.bootstrap({ baseURL: getApiUrl() }),
logger: logger.child("communication")
});
}
/**
* Sends an email through the Apigee API.
*
* @async
* @method sendEmail
* @memberof Service\Communication
* @param {object} emailParams - Parameters for the email to be sent.
* @param {string} emailParams.subject - The subject of the email.
* @param {string} emailParams.to - The email address of the recipient.
* @param {string} emailParams.from - The email address of the sender.
* @param {string} emailParams.body - The plaintext body of the email.
* @param {boolean} [emailParams.html] - Whether the body is HTML (optional).
* @returns {Promise<{ id: string, status: string }>} The response from the Apigee API.
* @throws {import('../core/errors.js').ValidationError} When input validation fails.
* @throws {import('../core/errors.js').ExternalServiceError} When the API request fails.
*
* @example
* communication.sendEmail({
* subject: 'Hello!',
* to: 'recipient@example.com',
* from: 'sender@example.com',
* body: '<p>This is a test email.</p>',
* html: true
* });
*/
async sendEmail({ subject, to, from, body, html }) {
validate({ subject, to, from, body, html }, EmailStructure, "sendEmail");
const headers = await this.#getAuthHeaders();
const payload = {
subject,
from,
to,
body,
...html && { html }
};
return this.#sendRequest(EMAIL_URI, payload, headers);
}
/**
* Sends an SMS through the Apigee API.
*
* @async
* @method sendSMS
* @memberof Service\Communication
* @param {object} smsParams - Parameters for the SMS to be sent.
* @param {string} smsParams.body - The message body of the SMS.
* @param {boolean} [smsParams.confidential=true] - Whether the message is confidential.
* @param {string} [smsParams.scheduledFor] - Scheduled time (ISO 8601 format).
* @param {string} smsParams.senderName - The name of the sender.
* @param {string} smsParams.to - The phone number of the recipient.
* @returns {Promise<{ id: string, status: string }>} The response from the Apigee API.
* @throws {import('../core/errors.js').ValidationError} When input validation fails.
* @throws {import('../core/errors.js').ExternalServiceError} When the API request fails.
*
* @example
* communication.sendSMS({
* body: 'This is a test SMS.',
* to: '+1234567890',
* senderName: 'MyApp'
* });
*/
async sendSMS({ body, confidential = true, scheduledFor, senderName, to }) {
validate({ body, confidential, scheduledFor, senderName, to }, SmsStructure, "sendSMS");
const headers = await this.#getAuthHeaders();
const payload = {
body,
channel: SMS_CHANNEL,
confidential,
...scheduledFor && { scheduledFor },
...senderName && { senderName },
to
};
return this.#sendRequest(SMS_URI, payload, headers);
}
/**
* @private
* @returns {Promise<{ Authorization: string }>} Authorization headers.
*/
async #getAuthHeaders() {
const { access_token, token_type } = await this.#authService.debug();
return buildAuthHeader(access_token, token_type);
}
/**
* @private
* @param {string} uri - The API endpoint path.
* @param {object} payload - The request payload.
* @param {object} headers - The request headers.
* @returns {Promise<object>} The response data.
* @throws {import('../core/errors.js').ExternalServiceError} On request failure.
*/
async #sendRequest(uri, payload, headers) {
try {
const { data } = await this.#client.post(uri, payload, { headers });
return data;
} catch (error) {
this.#logger.error("Communication request failed", { uri, status: error.response?.status });
throw fromAxiosError(error, "Request failed. Please check your input and try again.");
}
}
};
var communicationService_default = Communication;
export {
EmailStructure,
SmsStructure,
communicationService_default
};
//# sourceMappingURL=chunk-ZWM2VYBB.js.map