Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,28 @@ jobs:
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm test
- name: Smoke test packed package (import, require and types)
run: |
pnpm pack --out package.tgz
mkdir -p ../smoke && cd ../smoke
npm init -y > /dev/null
npm install ../${{ github.event.repository.name }}/package.tgz typescript@7 @types/node@22
node --input-type=module -e "
import fs from 'node:fs';
import notifier, { NotificationCenter } from 'node-notifier';
import NC from 'node-notifier/notifiers/notificationcenter';
import { vendorPath } from './node_modules/node-notifier/dist/lib/vendor.js';
if (typeof notifier.notify !== 'function' || NC !== NotificationCenter) process.exit(1);
for (const f of ['notifu/notifu.exe', 'snoreToast/snoretoast-x64.exe', 'mac.noindex/terminal-notifier.app/Contents/MacOS/terminal-notifier'])
if (!fs.existsSync(vendorPath(f))) { console.error('missing vendor/' + f); process.exit(1); }
"
node -e "const n = require('node-notifier'); if (n.WindowsToaster !== require('node-notifier/notifiers/toaster')) process.exit(1)"
echo "import notifier, { NotifySend, type NotifySendNotification } from 'node-notifier'; const o: NotifySendNotification = { urgency: 'low' }; new NotifySend().notify(o); notifier.notify('hi');" > index.mts
echo '{"compilerOptions":{"module":"nodenext","strict":true,"noEmit":true,"types":["node"]}}' > tsconfig.json
npx tsc -p .

vendor:
name: Verify vendored binaries
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

### v12.1.0

Features:

- Rewritten in TypeScript, and types are now included in the package. `@types/node-notifier` is no longer needed. Each notifier has typed options (`NotificationCenterNotification`, `WindowsToasterNotification`, `WindowsBalloonNotification`, `NotifySendNotification`, `GrowlNotification`), and the notifier classes can be used as types, e.g. `const nc: NotificationCenter = new NotificationCenter()`.

Migrating from `@types/node-notifier`:

- Uninstall `@types/node-notifier`. TypeScript uses the bundled types once they're installed and ignores it.
- The types are no longer in a namespace. Replace e.g. `NotificationCenter.Notification` with `NotificationCenterNotification`, `NotifySend.Notification` with `NotifySendNotification`, and `NodeNotifier` with `DefaultNotifier`. `NotificationCallback`, `NotificationMetadata` and `NotifierOptions` (DT's `Option`) are exported by name.
- Only the options documented in the README are typed. Raw notifier flags and old aliases (e.g. `time` for notify-send) still work at runtime, but need a cast.
- JavaScript users have nothing to change.

Fixes:

- Windows: `WindowsBalloon` with `wait` no longer throws when notifu exits without an error code.
- Linux: `NotifySend.notify` returns the notifier when `notify-send` isn't found, instead of `undefined`.

Internal:

- Built with [tsdown](https://tsdown.dev) into `dist/`, which is what's published together with `vendor/`. The public entry points (`node-notifier` and `node-notifier/notifiers/*`) are unchanged.
- Tests and examples are TypeScript, and CI typechecks and smoke tests the packed package with `import`, `require` and TypeScript.
- `pnpm test` no longer runs the linter first. Use `pnpm lint`.

### v12.0.0

Expand Down
17 changes: 9 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ node-notifier love getting pull requests and other help. Here's a quick guide.
If you want to see what command is run, execute the node program with the environmental variable `DEBUG="notifier"`, e.g.:

```
DEBUG="notifier" node index.js
DEBUG="notifier" node example/message.ts
```

```
Expand All @@ -31,17 +31,18 @@ corepack enable
pnpm install
```

Make sure the tests pass:
The source is TypeScript in `src/`. Node runs it directly through its built-in
type stripping, so the examples in `example/` and the tests need no build step.

```shell
pnpm test
pnpm test # vitest, including type tests in test/*.test-d.ts
pnpm lint # biome
pnpm typecheck # tsc
pnpm build # tsdown -> dist/, also run on pack/publish
node example/message.ts
```

Make your change. Add tests for your change. Make the tests pass:

```shell
pnpm test
```
Make your change. Add tests for your change. Make the checks above pass.

Push to your fork and [submit a pull request][pr].

Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ npm install node-notifier
Requires Node.js 22.22+, 24.15+ or 26+. The package is ES modules only, but
`require('node-notifier')` still works through Node's `require(esm)` support.

TypeScript types are included, so `@types/node-notifier` is no longer needed
(uninstall it if you have it). Each notifier has its own options type, e.g.
`NotificationCenterNotification` or `NotifySendNotification`.

### CLI

Need notifications from the terminal or a shell script? Use
Expand Down Expand Up @@ -120,7 +124,7 @@ notifier.notify(
(`make icon ICON=logo.png APP_NAME=my-tool`) and point `customPath` to it.
- macOS asks for notification permission the first time a notification is sent.

See [`example/macInput.js`](./example/macInput.js) for actions and reply.
See [`example/macInput.ts`](./example/macInput.ts) for actions and reply.

## `WindowsToaster` (Windows 8+)

Expand Down Expand Up @@ -157,7 +161,7 @@ notifier.notify(
- Toasts always wait for the user. `wait` and `timeout` don't change how long a
toast is shown, use `duration`. After that it stays in the Action Center.
- Choosing an action emits an event named after the lower-cased label. See
[`example/toaster-with-actions.js`](./example/toaster-with-actions.js).
[`example/toaster-with-actions.ts`](./example/toaster-with-actions.ts).
- On 32-bit Windows the bundled SnoreToast is 0.7.0: `duration` is ignored, and
clicks with a custom `appID` aren't reported. Use `customPath` with a newer
SnoreToast to get both.
Expand Down Expand Up @@ -208,7 +212,7 @@ new NotifySend().notify(

- Only notifications with `actions` wait for the user. Choosing an action emits
`click` with the label in `metadata.activationValue`, running out of time emits
`timeout`. See [`example/notify-send-actions.js`](./example/notify-send-actions.js).
`timeout`. See [`example/notify-send-actions.ts`](./example/notify-send-actions.ts).
- `actions` needs libnotify 0.7.10+ (e.g. Ubuntu 24.04, Debian 12) and a
notification daemon that supports actions.
- See [`notify-send(1)`](https://man.archlinux.org/man/notify-send.1) for all flags.
Expand Down
2 changes: 1 addition & 1 deletion example/advanced.js → example/advanced.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import { NotificationCenter } from '../index.js';
import { NotificationCenter } from '../src/index.ts';

const nc = new NotificationCenter();
const image = path.join(import.meta.dirname, 'coulson.jpg');
Expand Down
2 changes: 1 addition & 1 deletion example/forceBallon.js → example/forceBallon.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { WindowsBalloon } from '../index.js';
import { WindowsBalloon } from '../src/index.ts';

new WindowsBalloon()
.notify({ message: 'Hello' }, (err, data) => {
Expand Down
4 changes: 2 additions & 2 deletions example/macInput.js → example/macInput.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NotificationCenter } from '../index.js';
import { NotificationCenter } from '../src/index.ts';

const nc = new NotificationCenter();

Expand All @@ -17,7 +17,7 @@ nc.notify(
if (err) throw err;
console.log(metadata);

if (metadata.activationValue !== trueAnswer) {
if (metadata?.activationValue !== trueAnswer) {
return; // No need to continue
}

Expand Down
2 changes: 1 addition & 1 deletion example/message.js → example/message.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import notifier from '../index.js';
import notifier from '../src/index.ts';

notifier
.notify({ message: 'Hello', wait: true }, (err, data) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NotifySend } from '../index.js';
import { NotifySend } from '../src/index.ts';

// Requires notify-send (libnotify) 0.7.10 or newer and a notification daemon
// that supports actions.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import { WindowsToaster } from '../index.js';
import { WindowsToaster } from '../src/index.ts';

const customPath = path.join(
import.meta.dirname,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import notifier from '../index.js';
import notifier from '../src/index.ts';

notifier.notify(
{
Expand Down
2 changes: 1 addition & 1 deletion example/toaster.js → example/toaster.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import notifier from '../index.js';
import notifier from '../src/index.ts';

notifier.notify(
{
Expand Down
59 changes: 0 additions & 59 deletions index.js

This file was deleted.

7 changes: 0 additions & 7 deletions lib/callableClass.js

This file was deleted.

25 changes: 0 additions & 25 deletions lib/checkGrowl.js

This file was deleted.

44 changes: 25 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-notifier",
"version": "12.0.0",
"version": "12.1.0",
"description": "A Node.js module for sending notifications on native Mac, Windows (post and pre 8) and Linux (or Growl as fallback)",
"keywords": [
"notification center",
Expand All @@ -25,50 +25,56 @@
"author": "Mikael Brevik",
"type": "module",
"exports": {
".": "./index.js",
"./notifiers/*": "./notifiers/*.js",
"./notifiers/*.js": "./notifiers/*.js",
".": "./dist/index.js",
"./notifiers/*": "./dist/notifiers/*.js",
"./notifiers/*.js": "./dist/notifiers/*.js",
"./package.json": "./package.json"
},
"types": "./dist/index.d.ts",
"files": [
"index.js",
"lib/",
"notifiers/",
"vendor/"
"dist",
"vendor"
],
"sideEffects": false,
"engines": {
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"packageManager": "pnpm@12.10.1+sha512.ba40a37eb1a370d60fea8c4cf1d364c13bcccef518e98ad2bcee954f539d38da37458e58261a3fa55e06523450ea0ffff9f497b135be41f2c15c1642bacace6c",
"scripts": {
"pretest": "pnpm run lint",
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest run",
"test:integration": "vitest run --config vitest.integration.config.js",
"example": "node ./example/message.js",
"example:mac": "node ./example/advanced.js",
"example:mac:input": "node ./example/macInput.js",
"example:linux:actions": "node ./example/notify-send-actions.js",
"example:windows": "node ./example/toaster.js",
"example:windows:actions": "node ./example/toaster-with-actions.js",
"example:windows:custom-path": "cross-env DEBUG=notifier node ./example/toaster-custom-path.js",
"test:watch": "vitest",
"test:integration": "vitest run --config vitest.integration.config.ts",
"typecheck": "tsc",
"lint": "biome check",
"format": "biome check --write",
"prepack": "pnpm run build",
"prepare": "husky",
"format": "biome check --write"
"example": "node ./example/message.ts",
"example:mac": "node ./example/advanced.ts",
"example:mac:input": "node ./example/macInput.ts",
"example:linux:actions": "node ./example/notify-send-actions.ts",
"example:windows": "node ./example/toaster.ts",
"example:windows:actions": "node ./example/toaster-with-actions.ts",
"example:windows:custom-path": "cross-env DEBUG=notifier node ./example/toaster-custom-path.ts"
},
"dependencies": {
"growly": "^1.3.0",
"is-wsl": "^3.1.1"
},
"devDependencies": {
"@biomejs/biome": "2.6.3",
"@types/node": "^22.20.5",
"cross-env": "^10.1.0",
"husky": "^9.1.7",
"lint-staged": "^17.6.0",
"tsdown": "^0.23.4",
"typescript": "^7.0.2",
"vitest": "^5.0.5"
},
"lint-staged": {
"*.{js,json,css}": [
"*.{js,ts,json,css}": [
"biome check --write --no-errors-on-unmatched"
]
}
Expand Down
Loading
Loading