Skip to content
Open
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
7 changes: 6 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ interface Aps {
badge?: number
sound?: string | ApsSound
"content-available"?: undefined | 1
"content-changed"?: undefined | true
"mutable-content"?: undefined | 1
"url-args"?: string[]
category?: string
Expand Down Expand Up @@ -267,7 +268,7 @@ export class MultiProvider extends EventEmitter {
shutdown(callback?: () => void): Promise<void>;
}

export type NotificationPushType = 'background' | 'alert' | 'voip' | 'pushtotalk' | 'liveactivity' | 'location' | 'complication' | 'fileprovider' | 'mdm';
export type NotificationPushType = 'background' | 'alert' | 'voip' | 'pushtotalk' | 'liveactivity' | 'location' | 'complication' | 'fileprovider' | 'mdm' | 'widgets';

export type ChannelAction = 'create' | 'read' | 'readAll' | 'delete';

Expand Down Expand Up @@ -366,6 +367,10 @@ export class Notification {
*
*/
public mutableContent: boolean;
/**
* Setting this to true will specify "content-changed" in the payload when it is compiled
*/
public contentChanged: boolean;
Comment on lines +370 to +373
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify declaration/runtime/test contract for contentChanged
rg -n "contentChanged|content-changed" index.d.ts lib/notification/apsProperties.js test/notification/apsProperties.js -C3

Repository: parse-community/node-apn

Length of output: 3811


Widen contentChanged type to match runtime setter behavior.

Line 373 declares contentChanged as boolean, but the runtime setter (lib/notification/apsProperties.js:148–154) accepts true | 1 and clears on undefined and other falsy values. TS users cannot currently express the full contract.

Proposed typing fix
-  public contentChanged: boolean;
+  public contentChanged: boolean | 1 | undefined;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Setting this to true will specify "content-changed" in the payload when it is compiled
*/
public contentChanged: boolean;
/**
* Setting this to true will specify "content-changed" in the payload when it is compiled
*/
public contentChanged: boolean | 1 | undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.d.ts` around lines 370 - 373, The declaration for contentChanged
currently uses boolean but the runtime setter (see
lib/notification/apsProperties.js) treats allowed set values as true | 1 and
clears the field on undefined/other falsy values; update the index.d.ts
declaration for the public property contentChanged to reflect the runtime
contract (allow true and numeric 1 as valid set values and undefined to clear)
so TypeScript callers can express setting and clearing correctly (locate the
contentChanged property in the type/class declaration and change its type
accordingly).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wouldn't be an unreasonable type declaration, but it doesn't match how other properties (such as mutableContent are declared

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dwrss, that's a fair point. Keeping contentChanged: boolean is consistent with how mutableContent (and similar properties) are declared, even though the runtime setter accepts 1 as well. The simplified boolean type is a reasonable abstraction for TypeScript callers. I'll withdraw this suggestion.

(^_^) 🐇


✏️ Learnings added
Learnt from: dwrss
Repo: parse-community/node-apn PR: 194
File: index.d.ts:370-373
Timestamp: 2026-04-04T01:53:22.032Z
Learning: In parse-community/node-apn (`index.d.ts`), APS convenience properties like `mutableContent`, `contentAvailable`, and `contentChanged` are intentionally typed as `boolean` even though their runtime setters in `lib/notification/apsProperties.js` also accept `1` (numeric). The simplified `boolean` type is the established pattern and should not be widened to `boolean | 1 | undefined` for consistency.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

/**
* The value to specify for the `mdm` field where applicable.
*/
Expand Down
8 changes: 8 additions & 0 deletions lib/notification/apsProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ module.exports = {
}
},

set contentChanged(value) {
if (value === true || value === 1) {
this.aps['content-changed'] = true;
} else {
this.aps['content-changed'] = undefined;
}
},

set mdm(value) {
this._mdm = value;
},
Expand Down
1 change: 1 addition & 0 deletions lib/notification/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Notification.prototype = require('./apsProperties');
'sound',
'contentAvailable',
'mutableContent',
'contentChanged',
'mdm',
'urlArgs',
'category',
Expand Down
32 changes: 32 additions & 0 deletions test/notification/apsProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,38 @@ describe('Notification', function () {
});
});

describe('content-changed', function () {
it('defaults to undefined', function () {
expect(compiledOutput()).to.not.have.nested.deep.property('aps.content-changed');
});

it('can be set to a boolean value', function () {
note.contentChanged = true;

expect(compiledOutput()).to.have.nested.deep.property('aps.content-changed', true);
});

it('can be set to `1`', function () {
note.contentChanged = 1;

expect(compiledOutput()).to.have.nested.deep.property('aps.content-changed', true);
});

it('can be set to undefined', function () {
note.contentChanged = true;
note.contentChanged = undefined;

expect(compiledOutput()).to.not.have.nested.deep.property('aps.content-changed');
});

describe('setContentChanged', function () {
it('is chainable', function () {
expect(note.setContentChanged(true)).to.equal(note);
expect(compiledOutput()).to.have.nested.deep.property('aps.content-changed', true);
});
});
});

describe('mdm', function () {
it('defaults to undefined', function () {
expect(compiledOutput()).to.not.have.nested.deep.property('mdm');
Expand Down