From abf18de9b46848dec4880f98a0bf72f979082735 Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sun, 15 Sep 2024 19:46:09 -0400 Subject: [PATCH 1/7] add JSDoc --- lib/pushover.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/lib/pushover.js b/lib/pushover.js index 69b0403..366984d 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,14 @@ Pushover.prototype.updateSounds = function () { req.end() } +/** + * Sends a message using Pushover. + * @param {object} obj - The message object to send. + * @param {string} obj.token - The API token. + * @param {string} obj.user - The user key. + * @param {string} [obj.file] - Optional file attachment. + * @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 +254,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 +307,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 +320,11 @@ 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. + */ + exports = module.exports = Pushover From 1cc4583c87b22fbe69dd5a8b41776f0faa63011c Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sun, 15 Sep 2024 19:53:02 -0400 Subject: [PATCH 2/7] generate type declarations --- .gitignore | 2 + package-lock.json | 31 ++++++++++++++ package.json | 9 ++-- types/pushover.d.ts | 102 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 package-lock.json create mode 100644 types/pushover.d.ts diff --git a/.gitignore b/.gitignore index 0dec3a6..aa5bf08 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ npm-debug.log tinyproxy.log +node_modules + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b0397e7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,31 @@ +{ + "name": "pushover-notifications", + "version": "1.2.3", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pushover-notifications", + "version": "1.2.3", + "dependencies": { + "typescript": "^5.6.2" + }, + "devDependencies": {}, + "engines": { + "node": "*" + } + }, + "node_modules/typescript": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/package.json b/package.json index 0768ecc..2bc8dd2 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,14 @@ "type": "git", "url": "https://github.com/qbit/node-pushover.git" }, - "dependencies": {}, - "devDependencies": {}, - "optionalDependencies": {}, + "dependencies": { + "typescript": "^5.6.2" + }, "engines": { "node": "*" }, "scripts": { - "test": "standard && pkill tinyproxy ; tinyproxy -c test/tinyproxy.conf && set -e; for t in test/*.js; do node $t; done" + "test": "standard && pkill tinyproxy ; tinyproxy -c test/tinyproxy.conf && set -e; for t in test/*.js; do node $t; done", + "build": "npx -p typescript tsc lib/**.js --declaration --allowJs --emitDeclarationOnly --outDir types" } } diff --git a/types/pushover.d.ts b/types/pushover.d.ts new file mode 100644 index 0000000..33125a0 --- /dev/null +++ b/types/pushover.d.ts @@ -0,0 +1,102 @@ +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 {object} obj - The message object to send. + * @param {string} obj.token - The API token. + * @param {string} obj.user - The user key. + * @param {string} [obj.file] - Optional file attachment. + * @param {PushoverCallback} fn - The callback function that handles the response. + */ + send(obj: { + token: string; + user: string; + file?: string; + }, fn: PushoverCallback): void; +} +declare namespace Pushover { + export { PushoverCallback }; +} +/** + * A callback function that handles the result of the Pushover send operation. + */ +type PushoverCallback = (error: Error | null, result: any) => any; From 93b91df2b0afa01ef07d5427e0dfac1bb496782d Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sun, 15 Sep 2024 20:10:10 -0400 Subject: [PATCH 3/7] add Message type --- lib/pushover.js | 22 ++++++++++++--- tsconfig.json | 22 +++++++++++++++ types/pushover.d.ts | 67 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 tsconfig.json diff --git a/lib/pushover.js b/lib/pushover.js index 366984d..b8a78ba 100644 --- a/lib/pushover.js +++ b/lib/pushover.js @@ -215,10 +215,7 @@ Pushover.prototype.updateSounds = function () { /** * Sends a message using Pushover. - * @param {object} obj - The message object to send. - * @param {string} obj.token - The API token. - * @param {string} obj.user - The user key. - * @param {string} [obj.file] - Optional file attachment. + * @param {Message} obj - The message to send. * @param {PushoverCallback} fn - The callback function that handles the response. */ Pushover.prototype.send = function (obj, fn) { @@ -327,4 +324,21 @@ Pushover.prototype.send = function (obj, fn) { * @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 index 33125a0..c698d3f 100644 --- a/types/pushover.d.ts +++ b/types/pushover.d.ts @@ -81,22 +81,69 @@ declare class Pushover { updateSounds(): void; /** * Sends a message using Pushover. - * @param {object} obj - The message object to send. - * @param {string} obj.token - The API token. - * @param {string} obj.user - The user key. - * @param {string} [obj.file] - Optional file attachment. + * @param {Message} obj - The message to send. * @param {PushoverCallback} fn - The callback function that handles the response. */ - send(obj: { - token: string; - user: string; - file?: string; - }, fn: PushoverCallback): void; + send(obj: Message, fn: PushoverCallback): void; } declare namespace Pushover { - export { PushoverCallback }; + 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; +}; From 45a2d6eda2c47afdf5c239d32975277f3fd18097 Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sat, 21 Sep 2024 17:52:11 -0400 Subject: [PATCH 4/7] rm typescript --- package-lock.json | 31 ------------------------------- package.json | 3 --- 2 files changed, 34 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index b0397e7..0000000 --- a/package-lock.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "pushover-notifications", - "version": "1.2.3", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "pushover-notifications", - "version": "1.2.3", - "dependencies": { - "typescript": "^5.6.2" - }, - "devDependencies": {}, - "engines": { - "node": "*" - } - }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - } - } -} diff --git a/package.json b/package.json index 2bc8dd2..99f838c 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,6 @@ "type": "git", "url": "https://github.com/qbit/node-pushover.git" }, - "dependencies": { - "typescript": "^5.6.2" - }, "engines": { "node": "*" }, From 1d2a40b91894aef22fae6873d77337eeedddd9eb Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sat, 21 Sep 2024 17:54:08 -0400 Subject: [PATCH 5/7] rm node_modules from gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index aa5bf08..29379b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ npm-debug.log tinyproxy.log -node_modules From 85f69db45e0c7aeedb85babb2dee4c0b455aa9b5 Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sat, 21 Sep 2024 17:54:15 -0400 Subject: [PATCH 6/7] add instructions on how to regenerate types to readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) 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 +``` + From cae8a861a1ef27de0a51c8eddd6123f06cad7bd2 Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sat, 21 Sep 2024 17:58:33 -0400 Subject: [PATCH 7/7] cleanup --- .gitignore | 1 - package.json | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 29379b8..0dec3a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ npm-debug.log tinyproxy.log - diff --git a/package.json b/package.json index 99f838c..0768ecc 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,13 @@ "type": "git", "url": "https://github.com/qbit/node-pushover.git" }, + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, "engines": { "node": "*" }, "scripts": { - "test": "standard && pkill tinyproxy ; tinyproxy -c test/tinyproxy.conf && set -e; for t in test/*.js; do node $t; done", - "build": "npx -p typescript tsc lib/**.js --declaration --allowJs --emitDeclarationOnly --outDir types" + "test": "standard && pkill tinyproxy ; tinyproxy -c test/tinyproxy.conf && set -e; for t in test/*.js; do node $t; done" } }