diff --git a/README.md b/README.md index d6521cf..3ef792f 100644 --- a/README.md +++ b/README.md @@ -172,3 +172,10 @@ for ( var i = 0, l = users.length; i < l; i++ ) { }) } ``` + +## Development +### Generate new TypeScript definitions +```sh +$ npx -p typescript tsc lib/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types +``` + diff --git a/lib/pushover.js b/lib/pushover.js index 69b0403..b8a78ba 100644 --- a/lib/pushover.js +++ b/lib/pushover.js @@ -6,6 +6,11 @@ var qs = require('querystring') var pUrl = 'https://api.pushover.net/1/messages.json' var path = require('path') +/** + * Sets default values for missing properties in the object. + * @param {object} o - The object containing optional properties. + * @returns {object} The object with default properties set. + */ function setDefaults (o) { var def = [ 'device', @@ -28,6 +33,11 @@ function setDefaults (o) { return o } +/** + * Loads an image from the specified file path. + * @param {string} imgPath - The file path of the image to load. + * @returns {object} An object containing the image name and data. + */ function loadImage(imgPath) { var o = {} o.name = path.basename(imgPath) @@ -36,6 +46,13 @@ function loadImage(imgPath) { } +/** + * Converts a request string into a multipart form-data payload. + * @param {string} rs - The request string to convert. + * @param {string} b - The boundary string used for multipart form-data. + * @param {object} [imgObj] - The optional image object containing the image data and metadata. + * @returns {Buffer} The multipart payload as a Buffer object. + */ function reqString2MP(rs, b, imgObj) { var a = [] var parts = [] @@ -81,6 +98,17 @@ function reqString2MP(rs, b, imgObj) { return payload } +/** + * Creates a new Pushover instance. + * @class + * @param {object} opts - The options for Pushover. + * @param {string} opts.token - The Pushover API token. + * @param {string} opts.user - The user key for sending messages. + * @param {object} [opts.httpOptions] - Optional HTTP options. + * @param {boolean} [opts.debug] - Enable debug logging. + * @param {function} [opts.onerror] - Custom error handler. + * @param {boolean} [opts.update_sounds] - Automatically update sounds. + */ function Pushover (opts) { var self = this this.boundary = "--" + Math.random().toString(36).substring(2) @@ -129,6 +157,12 @@ function Pushover (opts) { } +/** + * Handles errors from Pushover API responses. + * @param {string|object} d - The response data from the API. + * @param {object} res - The HTTP response object. + * @throws {Error} Throws an error if there are API errors and no error handler is provided. + */ Pushover.prototype.errors = function (d, res) { if (typeof d === 'string') { try { @@ -148,6 +182,9 @@ Pushover.prototype.errors = function (d, res) { } } +/** + * Updates the list of available Pushover sounds. + */ Pushover.prototype.updateSounds = function () { var self = this var data = '' @@ -176,6 +213,11 @@ Pushover.prototype.updateSounds = function () { req.end() } +/** + * Sends a message using Pushover. + * @param {Message} obj - The message to send. + * @param {PushoverCallback} fn - The callback function that handles the response. + */ Pushover.prototype.send = function (obj, fn) { var self = this var o = url.parse(pUrl) @@ -209,7 +251,7 @@ Pushover.prototype.send = function (obj, fn) { mp = reqString2MP(reqString, self.boundary, obj.file) } } else { - mp = reqString2MP(reqString, self.boundary) + mp = reqString2MP(reqString, self.boundary) } o.headers = { @@ -262,8 +304,8 @@ Pushover.prototype.send = function (obj, fn) { if (fn) { fn(err) } - // In the tests the "end" event did not get emitted if "error" was emitted, - // but to be sure that the callback is not get called twice, null the callback function + // In the tests the "end" event did not get emitted if "error" was emitted, + // but to be sure that the callback is not called twice, null the callback function fn = null }) @@ -275,4 +317,28 @@ Pushover.prototype.send = function (obj, fn) { req.end() } +/** + * A callback function that handles the result of the Pushover send operation. + * @callback PushoverCallback + * @param {Error|null} error - The error object if the operation failed, or null if successful. + * @param {any} result - The result of the operation, can be any type. + */ + +/** + * @typedef {Object} Message + * @property {string} message - The message to send + * @property {string} [token] - The API token. + * @property {string} [user] - The user key. + * @property {string|object} [file] - A file path or binary image attachment to send with the message + * @property {string} [device] - The name of one of your devices to send just to that device instead of all devices + * @property {string} [html] - Set to 1 to enable HTML parsing + * @property {string} [priority] - A value of -2, -1, 0 (default), 1, or 2 + * @property {string} [sound] - The name of a supported sound to override your default sound choice + * @property {string} [timestamp] - A Unix timestamp of a time to display instead of when our API received it + * @property {string} [title] - Your message's title, otherwise your app's name is used + * @property {string} [ttl] - A number of seconds that the message will live, before being deleted automatically + * @property {string} [url] - A supplementary URL to show with your message + * @property {string} [url_title] - A title for the URL specified as the url parameter, otherwise just the URL is shown + */ + exports = module.exports = Pushover diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..896b9e7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + // Change this to match your project + "include": ["lib/**/*"], + "compilerOptions": { + // Tells TypeScript to read JS files, as + // normally they are ignored as source files + "allowJs": true, + // Generate d.ts files + "declaration": true, + // This compiler run should + // only output d.ts files + "emitDeclarationOnly": true, + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "dist", + // go to js file when using IDE functions like + // "Go to Definition" in VSCode + "declarationMap": true + } +} + diff --git a/types/pushover.d.ts b/types/pushover.d.ts new file mode 100644 index 0000000..c698d3f --- /dev/null +++ b/types/pushover.d.ts @@ -0,0 +1,149 @@ +export = Pushover; +/** + * Creates a new Pushover instance. + * @class + * @param {object} opts - The options for Pushover. + * @param {string} opts.token - The Pushover API token. + * @param {string} opts.user - The user key for sending messages. + * @param {object} [opts.httpOptions] - Optional HTTP options. + * @param {boolean} [opts.debug] - Enable debug logging. + * @param {function} [opts.onerror] - Custom error handler. + * @param {boolean} [opts.update_sounds] - Automatically update sounds. + */ +declare function Pushover(opts: { + token: string; + user: string; + httpOptions?: object; + debug?: boolean; + onerror?: Function; + update_sounds?: boolean; +}): void; +declare class Pushover { + /** + * Creates a new Pushover instance. + * @class + * @param {object} opts - The options for Pushover. + * @param {string} opts.token - The Pushover API token. + * @param {string} opts.user - The user key for sending messages. + * @param {object} [opts.httpOptions] - Optional HTTP options. + * @param {boolean} [opts.debug] - Enable debug logging. + * @param {function} [opts.onerror] - Custom error handler. + * @param {boolean} [opts.update_sounds] - Automatically update sounds. + */ + constructor(opts: { + token: string; + user: string; + httpOptions?: object; + debug?: boolean; + onerror?: Function; + update_sounds?: boolean; + }); + boundary: string; + token: string; + user: string; + httpOptions: any; + sounds: { + pushover: string; + bike: string; + bugle: string; + cashregister: string; + classical: string; + cosmic: string; + falling: string; + gamelan: string; + incoming: string; + intermission: string; + magic: string; + mechanical: string; + pianobar: string; + siren: string; + spacealarm: string; + tugboat: string; + alien: string; + climb: string; + persistent: string; + echo: string; + updown: string; + none: string; + }; + debug: true; + onerror: Function; + /** + * Handles errors from Pushover API responses. + * @param {string|object} d - The response data from the API. + * @param {object} res - The HTTP response object. + * @throws {Error} Throws an error if there are API errors and no error handler is provided. + */ + errors(d: string | object, res: object): void; + /** + * Updates the list of available Pushover sounds. + */ + updateSounds(): void; + /** + * Sends a message using Pushover. + * @param {Message} obj - The message to send. + * @param {PushoverCallback} fn - The callback function that handles the response. + */ + send(obj: Message, fn: PushoverCallback): void; +} +declare namespace Pushover { + export { PushoverCallback, Message }; +} +/** + * A callback function that handles the result of the Pushover send operation. + */ +type PushoverCallback = (error: Error | null, result: any) => any; +type Message = { + /** + * - The message to send + */ + message: string; + /** + * - The API token. + */ + token?: string; + /** + * - The user key. + */ + user?: string; + /** + * - A file path or binary image attachment to send with the message + */ + file?: string | object; + /** + * - The name of one of your devices to send just to that device instead of all devices + */ + device?: string; + /** + * - Set to 1 to enable HTML parsing + */ + html?: string; + /** + * - A value of -2, -1, 0 (default), 1, or 2 + */ + priority?: string; + /** + * - The name of a supported sound to override your default sound choice + */ + sound?: string; + /** + * - A Unix timestamp of a time to display instead of when our API received it + */ + timestamp?: string; + /** + * - Your message's title, otherwise your app's name is used + */ + title?: string; + /** + * - A number of seconds that the message will live, before being deleted automatically + */ + ttl?: string; + /** + * - A supplementary URL to show with your message + */ + url?: string; + /** + * - A title for the URL specified as the url parameter, otherwise just the URL is shown + */ + url_title?: string; +};