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
278 changes: 189 additions & 89 deletions DefaultApi.md

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ const response = await client.createNotification(notification);
console.log('Notification ID:', response.id);
```

## Send with idempotent retries

`createNotificationWithRetry` generates a UUIDv4 `idempotency_key` when absent (a caller-provided key is respected), retries 429 / 503 / transport errors with the **same** key (honoring `Retry-After`, exponential backoff otherwise; `maxRetries` / `baseDelayMs` configurable via the options object), fails fast on other errors, and reports via `wasReplayed` whether the server answered from a previously completed request (`Idempotent-Replayed` response header). It is a `DefaultApi` method, so the call mirrors `createNotification`:

```javascript
const result = await client.createNotificationWithRetry(notification);
console.log('Notification ID:', result.response.id, 'replayed:', result.wasReplayed);
```

## Send a push notification by External ID

Target specific users with the alias label `external_id` (snake_case). This is different from the notification-level `external_id` field, which is only for [idempotent requests](https://documentation.onesignal.com/docs/idempotent-notification-requests).
Expand Down
54 changes: 54 additions & 0 deletions apis/exception.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,58 @@ export class ApiException<T> extends Error {
// Reference: https://github.com/microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
Object.setPrototypeOf(this, ApiException.prototype);
}

/**
* The error messages carried by the response body, normalized to a flat
* string array regardless of which envelope shape the API returned
* (`{ errors: "..." }`, `{ errors: ["..."] }`, `{ errors: [{ code, title }] }`,
* or an object map such as `{ errors: { invalid_aliases: {...} } }`, which is
* surfaced as `"<key>: <value>"` entries). Returns an empty array when the
* body is not a recognizable error envelope. The raw body remains on `body`.
*/
public get errorMessages(): string[] {
let parsed: any = this.body;
if (typeof parsed === "string") {
try {
parsed = JSON.parse(parsed);
} catch {
return [];
}
}
if (parsed === null || typeof parsed !== "object") {
return [];
}
const errors: any = parsed.errors;
if (typeof errors === "string") {
return [errors];
}
if (Array.isArray(errors)) {
return errors
.map((e: any) => {
if (typeof e === "string") {
return e;
}
if (e !== null && typeof e === "object") {
const title = typeof e.title === "string" ? e.title : undefined;
const code = typeof e.code === "string" ? e.code : (e.code != null ? String(e.code) : undefined);
return title || code;
}
return undefined;
})
.filter((m: any): m is string => typeof m === "string");
}
if (errors !== null && typeof errors === "object") {
// Object-shaped envelopes (e.g. { invalid_aliases: {...} }) carry data
// under arbitrary keys; surface each so it isn't silently dropped. Key
// order is unspecified, so sort for deterministic output.
return Object.keys(errors)
.map((key: string) => {
const value: any = errors[key];
const rendered = typeof value === "string" ? value : JSON.stringify(value);
return key + ": " + rendered;
})
.sort();
}
return [];
}
}
1 change: 1 addition & 0 deletions dist/apis/exception.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export declare class ApiException<T> extends Error {
constructor(code: number, message: string, body: T, headers: {
[key: string]: string;
});
get errorMessages(): string[];
}
43 changes: 43 additions & 0 deletions dist/apis/exception.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/apis/exception.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export * from "./models/all";
export { createConfiguration } from "./configuration";
export { Configuration, ConfigurationParameters } from "./configuration";
export * from "./apis/exception";
export * from "./helpers";
export * from "./servers";
export { RequiredError } from "./apis/baseapi";
export { PromiseMiddleware as Middleware } from './middleware';
export { PromiseDefaultApi as DefaultApi } from './types/PromiseAPI';
export * from "./errors";
2 changes: 2 additions & 0 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions dist/types/PromiseAPI.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as models from '../models/all';
import { Configuration } from '../configuration';
import { CreateNotificationWithRetryOptions, CreateNotificationWithRetryResult } from '../helpers';
import { ApiKeyTokensListResponse } from '../models/ApiKeyTokensListResponse';
import { App } from '../models/App';
import { CopyTemplateRequest } from '../models/CopyTemplateRequest';
Expand Down Expand Up @@ -37,7 +39,9 @@ import { UserIdentityBody } from '../models/UserIdentityBody';
import { DefaultApiRequestFactory, DefaultApiResponseProcessor } from "../apis/DefaultApi";
export declare class PromiseDefaultApi {
private api;
private configuration;
constructor(configuration: Configuration, requestFactory?: DefaultApiRequestFactory, responseProcessor?: DefaultApiResponseProcessor);
createNotificationWithRetry(notification: models.Notification, options?: CreateNotificationWithRetryOptions): Promise<CreateNotificationWithRetryResult>;
cancelNotification(appId: string, notificationId: string, _options?: Configuration): Promise<GenericSuccessBoolResponse>;
copyTemplateToApp(templateId: string, appId: string, copyTemplateRequest: CopyTemplateRequest, _options?: Configuration): Promise<TemplateResource>;
createAlias(appId: string, aliasLabel: string, aliasId: string, userIdentityBody: UserIdentityBody, _options?: Configuration): Promise<UserIdentityBody>;
Expand Down
5 changes: 5 additions & 0 deletions dist/types/PromiseAPI.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading