ab-ecosystem-cpass 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -1
- package/dist/client.d.ts +23 -0
- package/dist/client.js +32 -5
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +22 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/bytes.d.ts +38 -0
- package/dist/internal/bytes.js +84 -0
- package/dist/internal/bytes.js.map +1 -0
- package/dist/internal/device.d.ts +24 -0
- package/dist/internal/device.js +91 -0
- package/dist/internal/device.js.map +1 -0
- package/dist/internal/md5.d.ts +4 -0
- package/dist/internal/md5.js +109 -0
- package/dist/internal/md5.js.map +1 -0
- package/dist/internal/receiver-file.d.ts +106 -0
- package/dist/internal/receiver-file.js +128 -0
- package/dist/internal/receiver-file.js.map +1 -0
- package/dist/resources/audience/notifications.d.ts +171 -0
- package/dist/resources/audience/notifications.js +215 -0
- package/dist/resources/audience/notifications.js.map +1 -0
- package/dist/resources/campaign-audience.d.ts +132 -0
- package/dist/resources/campaign-audience.js +224 -0
- package/dist/resources/campaign-audience.js.map +1 -0
- package/dist/resources/campaign-report-exports.d.ts +14 -0
- package/dist/resources/campaign-report-exports.js +28 -0
- package/dist/resources/campaign-report-exports.js.map +1 -0
- package/dist/resources/campaign-reports.d.ts +15 -0
- package/dist/resources/campaign-reports.js +25 -0
- package/dist/resources/campaign-reports.js.map +1 -0
- package/dist/resources/campaigns.d.ts +239 -0
- package/dist/resources/campaigns.js +300 -0
- package/dist/resources/campaigns.js.map +1 -0
- package/dist/types/audience.d.ts +82 -0
- package/dist/types/campaign.d.ts +229 -0
- package/dist/types/campaign.js +3 -0
- package/dist/types/campaign.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/docs/audience/notifications.md +263 -0
- package/docs/campaign/campaigns.md +489 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -179,6 +179,7 @@ same pages ship inside the package, so they are readable offline at
|
|
|
179
179
|
| `crm.exports` | [export history](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/audience/exports.md) | `list` `get` `create` `delete` |
|
|
180
180
|
| `crm.webhooks` | [audience webhooks](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/audience/webhooks.md) | `list` `get` `create` `update` `delete` |
|
|
181
181
|
| `crm.scheduledMessages` | [scheduled messages](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/audience/scheduled-messages.md) | `list` `get` `create` `createSeries` `createRepeating` `reschedule` `cancel` `cancelSeries` `sendNow` |
|
|
182
|
+
| `crm.notifications` | [push notifications](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/audience/notifications.md) | `subscribe` `unsubscribe` `devices` — the devices a user wants notified |
|
|
182
183
|
|
|
183
184
|
### Channels — `/v1/channels`
|
|
184
185
|
|
|
@@ -225,4 +226,65 @@ Requests are promises; pushes are what other agents and contacts did. The same
|
|
|
225
226
|
event name can be both — an archive you performed and one another agent performed
|
|
226
227
|
arrive identically, so one handler per kind of change is enough.
|
|
227
228
|
|
|
228
|
-
|
|
229
|
+
## Campaigns
|
|
230
|
+
|
|
231
|
+
One message sent to many people. The audience is a single `filters` field with
|
|
232
|
+
five modes, chosen by the **shape** of the array: `[]` for every contact, a list
|
|
233
|
+
of filter conditions for a segment, `[{numbers, hash}]` for a bulk list,
|
|
234
|
+
`[{type: 'channel'|'template', ...}]` for a group campaign split into buckets, or
|
|
235
|
+
`[{type: 'status'|'selection', ...}]` to re-target an earlier campaign.
|
|
236
|
+
|
|
237
|
+
`createBulk` is the one worth knowing about. Hand it numbers or a CSV and it does
|
|
238
|
+
the whole bulk path — the recipient list does not travel inside the campaign,
|
|
239
|
+
because a million numbers is not a request body:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const { campaign, receivers, skipped, duplicates } = await crm.campaigns.createBulk({
|
|
243
|
+
name: 'Diwali offer',
|
|
244
|
+
audience: { csv: await file.text(), recipientColumn: 'phone' },
|
|
245
|
+
messages: [{ channel: { id: channelId }, message: template }],
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
It parses the input, encrypts the list under a per-file secret, uploads it
|
|
250
|
+
through a presigned URL, and creates the campaign pointing at the file. Every
|
|
251
|
+
CSV column becomes a per-recipient template variable. Rows with no usable number
|
|
252
|
+
and repeated numbers are dropped and **counted** — `skipped` and `duplicates` —
|
|
253
|
+
rather than passed over silently.
|
|
254
|
+
|
|
255
|
+
`createGroup` is the bucketed form: it splits recipients across channels or
|
|
256
|
+
templates, uploading one file per bucket.
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
await crm.campaigns.createGroup({
|
|
260
|
+
name: 'Diwali offer',
|
|
261
|
+
distributeBy: 'channel',
|
|
262
|
+
buckets: [
|
|
263
|
+
{ channel: channelA, audience: { rows: north, recipientColumn: 'phone' } },
|
|
264
|
+
{ channel: channelB, audience: { rows: south, recipientColumn: 'phone' } },
|
|
265
|
+
],
|
|
266
|
+
messages: [{ channel: { id: channelA }, message: template }],
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Note that `campaign.receivers` is `0` on a campaign you just created: the
|
|
271
|
+
audience is resolved when the campaign sends, not when it is built. The
|
|
272
|
+
`receivers` on the result is the count written into the file, and it is the one
|
|
273
|
+
to show a user.
|
|
274
|
+
|
|
275
|
+
| Resource | Page | Actions |
|
|
276
|
+
| --- | --- | --- |
|
|
277
|
+
| `crm.campaigns` | [campaigns](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/campaign/campaigns.md) | `list` `get` `create` `createBulk` `createGroup` `uploadReceivers` `update` `schedule` `cancel` `delete` |
|
|
278
|
+
| `crm.campaignReports` | [campaigns](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/campaign/campaigns.md#campaign-reports) | `list` `getByCampaign` |
|
|
279
|
+
| `crm.campaignReportExports` | [campaigns](https://github.com/udghatan-dev/crm-sdk/blob/main/packages/sdk-js/docs/campaign/campaigns.md#campaign-reports) | `list` `get` `create` |
|
|
280
|
+
|
|
281
|
+
The audience helpers are exported too, so a UI can show "12,480 recipients, 3
|
|
282
|
+
duplicates dropped" before anything is uploaded:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
import { parseDelimited, resolveAudience } from 'ab-ecosystem-cpass';
|
|
286
|
+
|
|
287
|
+
const { headers } = parseDelimited(text);
|
|
288
|
+
const { receivers, skipped, duplicates } = resolveAudience({ csv: text, recipientColumn });
|
|
289
|
+
```
|
|
290
|
+
|
package/dist/client.d.ts
CHANGED
|
@@ -10,12 +10,16 @@ import { Exports } from './resources/audience/export-history';
|
|
|
10
10
|
import { Webhooks } from './resources/audience/webhooks';
|
|
11
11
|
import { ScheduledMessages } from './resources/audience/scheduled-messages';
|
|
12
12
|
import { InboxMedia } from './resources/audience/inbox-media';
|
|
13
|
+
import { Notifications } from './resources/audience/notifications';
|
|
13
14
|
import { Channels } from './resources/channels/channels';
|
|
14
15
|
import { Templates } from './resources/channels/templates';
|
|
15
16
|
import { ChannelWebhooks } from './resources/channels/webhooks';
|
|
16
17
|
import { Billing } from './resources/channels/billing';
|
|
17
18
|
import { Wallet } from './resources/channels/wallet';
|
|
18
19
|
import { Activity } from './resources/channels/activity';
|
|
20
|
+
import { Campaigns } from './resources/campaigns';
|
|
21
|
+
import { CampaignReports } from './resources/campaign-reports';
|
|
22
|
+
import { CampaignReportExports } from './resources/campaign-report-exports';
|
|
19
23
|
/**
|
|
20
24
|
* One client for the whole gateway. Construct it once and share it: it holds no
|
|
21
25
|
* per-request state, and every resource below runs over the same HTTP client,
|
|
@@ -60,6 +64,12 @@ export declare class CrmClient {
|
|
|
60
64
|
* pass to `inbox.messages.sendMedia()`.
|
|
61
65
|
*/
|
|
62
66
|
readonly inboxMedia: InboxMedia;
|
|
67
|
+
/**
|
|
68
|
+
* Push notification subscriptions: the browsers and apps a user wants
|
|
69
|
+
* notified. `subscribe()` after the browser hands you a Firebase registration
|
|
70
|
+
* token, `unsubscribe()` on logout.
|
|
71
|
+
*/
|
|
72
|
+
readonly notifications: Notifications;
|
|
63
73
|
/** Channels, and the provider properties that hang off them. */
|
|
64
74
|
readonly channels: Channels;
|
|
65
75
|
/** WhatsApp message templates, per channel. */
|
|
@@ -72,5 +82,18 @@ export declare class CrmClient {
|
|
|
72
82
|
readonly wallet: Wallet;
|
|
73
83
|
/** Channel activity feed. */
|
|
74
84
|
readonly activity: Activity;
|
|
85
|
+
/**
|
|
86
|
+
* Campaigns: a message sent to many people at once.
|
|
87
|
+
*
|
|
88
|
+
* `createBulk()` is the one to reach for when you hold the recipients
|
|
89
|
+
* yourself -- numbers or a CSV. It encrypts the list, uploads it, and creates
|
|
90
|
+
* the campaign pointing at the file, which is otherwise several steps a caller
|
|
91
|
+
* has to get exactly right.
|
|
92
|
+
*/
|
|
93
|
+
readonly campaigns: Campaigns;
|
|
94
|
+
/** Per-campaign delivery metrics. */
|
|
95
|
+
readonly campaignReports: CampaignReports;
|
|
96
|
+
/** Report extracts as CSV or XLSX, generated asynchronously. */
|
|
97
|
+
readonly campaignReportExports: CampaignReportExports;
|
|
75
98
|
constructor(options: ClientOptions);
|
|
76
99
|
}
|
package/dist/client.js
CHANGED
|
@@ -14,6 +14,7 @@ const export_history_1 = require("./resources/audience/export-history");
|
|
|
14
14
|
const webhooks_1 = require("./resources/audience/webhooks");
|
|
15
15
|
const scheduled_messages_1 = require("./resources/audience/scheduled-messages");
|
|
16
16
|
const inbox_media_1 = require("./resources/audience/inbox-media");
|
|
17
|
+
const notifications_1 = require("./resources/audience/notifications");
|
|
17
18
|
// Channels
|
|
18
19
|
const channels_1 = require("./resources/channels/channels");
|
|
19
20
|
const templates_1 = require("./resources/channels/templates");
|
|
@@ -21,11 +22,10 @@ const webhooks_2 = require("./resources/channels/webhooks");
|
|
|
21
22
|
const billing_1 = require("./resources/channels/billing");
|
|
22
23
|
const wallet_1 = require("./resources/channels/wallet");
|
|
23
24
|
const activity_1 = require("./resources/channels/activity");
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// import { CampaignReportExports } from './resources/campaign-report-exports';
|
|
25
|
+
// Campaign
|
|
26
|
+
const campaigns_1 = require("./resources/campaigns");
|
|
27
|
+
const campaign_reports_1 = require("./resources/campaign-reports");
|
|
28
|
+
const campaign_report_exports_1 = require("./resources/campaign-report-exports");
|
|
29
29
|
/**
|
|
30
30
|
* One client for the whole gateway. Construct it once and share it: it holds no
|
|
31
31
|
* per-request state, and every resource below runs over the same HTTP client,
|
|
@@ -71,6 +71,12 @@ class CrmClient {
|
|
|
71
71
|
* pass to `inbox.messages.sendMedia()`.
|
|
72
72
|
*/
|
|
73
73
|
inboxMedia;
|
|
74
|
+
/**
|
|
75
|
+
* Push notification subscriptions: the browsers and apps a user wants
|
|
76
|
+
* notified. `subscribe()` after the browser hands you a Firebase registration
|
|
77
|
+
* token, `unsubscribe()` on logout.
|
|
78
|
+
*/
|
|
79
|
+
notifications;
|
|
74
80
|
// -- Channels -------------------------------------------------------------
|
|
75
81
|
/** Channels, and the provider properties that hang off them. */
|
|
76
82
|
channels;
|
|
@@ -84,6 +90,20 @@ class CrmClient {
|
|
|
84
90
|
wallet;
|
|
85
91
|
/** Channel activity feed. */
|
|
86
92
|
activity;
|
|
93
|
+
// -- Campaign -------------------------------------------------------------
|
|
94
|
+
/**
|
|
95
|
+
* Campaigns: a message sent to many people at once.
|
|
96
|
+
*
|
|
97
|
+
* `createBulk()` is the one to reach for when you hold the recipients
|
|
98
|
+
* yourself -- numbers or a CSV. It encrypts the list, uploads it, and creates
|
|
99
|
+
* the campaign pointing at the file, which is otherwise several steps a caller
|
|
100
|
+
* has to get exactly right.
|
|
101
|
+
*/
|
|
102
|
+
campaigns;
|
|
103
|
+
/** Per-campaign delivery metrics. */
|
|
104
|
+
campaignReports;
|
|
105
|
+
/** Report extracts as CSV or XLSX, generated asynchronously. */
|
|
106
|
+
campaignReportExports;
|
|
87
107
|
constructor(options) {
|
|
88
108
|
const http = new http_1.HttpClient(options);
|
|
89
109
|
this.contacts = new contacts_1.Contacts(http);
|
|
@@ -97,12 +117,19 @@ class CrmClient {
|
|
|
97
117
|
this.webhooks = new webhooks_1.Webhooks(http);
|
|
98
118
|
this.scheduledMessages = new scheduled_messages_1.ScheduledMessages(http);
|
|
99
119
|
this.inboxMedia = new inbox_media_1.InboxMedia(http);
|
|
120
|
+
this.notifications = new notifications_1.Notifications(http);
|
|
100
121
|
this.channels = new channels_1.Channels(http);
|
|
101
122
|
this.templates = new templates_1.Templates(http);
|
|
102
123
|
this.channelWebhooks = new webhooks_2.ChannelWebhooks(http);
|
|
103
124
|
this.billing = new billing_1.Billing(http);
|
|
104
125
|
this.wallet = new wallet_1.Wallet(http);
|
|
105
126
|
this.activity = new activity_1.Activity(http);
|
|
127
|
+
// Campaigns build their own uploader over the same HTTP client: a bulk
|
|
128
|
+
// audience is uploaded through the media endpoint before the campaign is
|
|
129
|
+
// created.
|
|
130
|
+
this.campaigns = new campaigns_1.Campaigns(http);
|
|
131
|
+
this.campaignReports = new campaign_reports_1.CampaignReports(http);
|
|
132
|
+
this.campaignReportExports = new campaign_report_exports_1.CampaignReportExports(http);
|
|
106
133
|
}
|
|
107
134
|
}
|
|
108
135
|
exports.CrmClient = CrmClient;
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,iCAAwD;AAExD,WAAW;AACX,4DAAyD;AACzD,oEAAgE;AAChE,sEAAkE;AAClE,sEAAkE;AAClE,4DAAyD;AACzD,oEAAgE;AAChE,wEAA8D;AAC9D,wEAA8D;AAC9D,4DAAyD;AACzD,gFAA4E;AAC5E,kEAA8D;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,iCAAwD;AAExD,WAAW;AACX,4DAAyD;AACzD,oEAAgE;AAChE,sEAAkE;AAClE,sEAAkE;AAClE,4DAAyD;AACzD,oEAAgE;AAChE,wEAA8D;AAC9D,wEAA8D;AAC9D,4DAAyD;AACzD,gFAA4E;AAC5E,kEAA8D;AAC9D,sEAAmE;AAEnE,WAAW;AACX,4DAAyD;AACzD,8DAA2D;AAC3D,4DAAgE;AAChE,0DAAuD;AACvD,wDAAqD;AACrD,4DAAyD;AAEzD,WAAW;AACX,qDAAkD;AAClD,mEAA+D;AAC/D,iFAA4E;AAE5E;;;;;;;;;;;GAWG;AACH,MAAa,SAAS;IACpB,4EAA4E;IAE5E,gDAAgD;IACvC,QAAQ,CAAW;IAC5B,oDAAoD;IAC3C,WAAW,CAAc;IAClC,kEAAkE;IACzD,YAAY,CAAe;IACpC,qDAAqD;IAC5C,YAAY,CAAe;IACpC,uCAAuC;IAC9B,QAAQ,CAAW;IAC5B,qFAAqF;IAC5E,WAAW,CAAc;IAClC,kEAAkE;IACzD,OAAO,CAAU;IAC1B,yDAAyD;IAChD,OAAO,CAAU;IAC1B,0DAA0D;IACjD,QAAQ,CAAW;IAC5B;;;OAGG;IACM,iBAAiB,CAAoB;IAE9C;;;;;;OAMG;IACM,UAAU,CAAa;IAEhC;;;;OAIG;IACM,aAAa,CAAgB;IAEtC,4EAA4E;IAE5E,gEAAgE;IACvD,QAAQ,CAAW;IAC5B,+CAA+C;IACtC,SAAS,CAAY;IAC9B,wEAAwE;IAC/D,eAAe,CAAkB;IAC1C,yDAAyD;IAChD,OAAO,CAAU;IAC1B,6BAA6B;IACpB,MAAM,CAAS;IACxB,6BAA6B;IACpB,QAAQ,CAAW;IAE5B,4EAA4E;IAE5E;;;;;;;OAOG;IACM,SAAS,CAAY;IAC9B,qCAAqC;IAC5B,eAAe,CAAkB;IAC1C,gEAAgE;IACvD,qBAAqB,CAAwB;IAEtD,YAAY,OAAsB;QAChC,MAAM,IAAI,GAAG,IAAI,iBAAU,CAAC,OAAO,CAAC,CAAC;QAErC,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,IAAI,0BAAW,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,IAAI,4BAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,YAAY,GAAG,IAAI,4BAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,IAAI,0BAAW,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,IAAI,wBAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,IAAI,wBAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,iBAAiB,GAAG,IAAI,sCAAiB,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,UAAU,GAAG,IAAI,wBAAU,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,aAAa,GAAG,IAAI,6BAAa,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,IAAI,qBAAS,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,eAAe,GAAG,IAAI,0BAAe,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAO,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,IAAI,eAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC,IAAI,CAAC,CAAC;QAEnC,uEAAuE;QACvE,yEAAyE;QACzE,WAAW;QACX,IAAI,CAAC,SAAS,GAAG,IAAI,qBAAS,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,eAAe,GAAG,IAAI,kCAAe,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,qBAAqB,GAAG,IAAI,+CAAqB,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;CACF;AAxGD,8BAwGC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,17 @@ export { CrmTriggers } from './resources/audience/crm-triggers';
|
|
|
12
12
|
export { Imports } from './resources/audience/import-history';
|
|
13
13
|
export { Exports } from './resources/audience/export-history';
|
|
14
14
|
export { Webhooks } from './resources/audience/webhooks';
|
|
15
|
+
export { Notifications } from './resources/audience/notifications';
|
|
15
16
|
export { InboxMedia, type UploadMediaOptions, type UploadMediaSource, } from './resources/audience/inbox-media';
|
|
17
|
+
export { Campaigns, type CreateBulkCampaignInput, type BulkCampaignResult, type CreateGroupCampaignInput, type GroupBucket, type GroupBucketResult, type GroupCampaignResult, type ReceiverUploader, } from './resources/campaigns';
|
|
18
|
+
export { CampaignReports } from './resources/campaign-reports';
|
|
19
|
+
export { CampaignReportExports } from './resources/campaign-report-exports';
|
|
20
|
+
/**
|
|
21
|
+
* The audience helpers, exported because they are useful before a campaign
|
|
22
|
+
* exists: a UI can parse a CSV, show "12,480 recipients, 3 duplicates dropped",
|
|
23
|
+
* and let someone confirm before anything is uploaded.
|
|
24
|
+
*/
|
|
25
|
+
export { MAX_BULK_RECEIVERS, buildReceivers, normaliseColumn, normaliseNumbers, parseDelimited, resolveAudience, type BulkAudienceInput, type CampaignReceiver, type ResolvedAudience, } from './resources/campaign-audience';
|
|
16
26
|
export { Channels, type SetPropOptions } from './resources/channels/channels';
|
|
17
27
|
export { Templates } from './resources/channels/templates';
|
|
18
28
|
export { ChannelWebhooks } from './resources/channels/webhooks';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.Activity = exports.Wallet = exports.Billing = exports.ChannelWebhooks = exports.Templates = exports.Channels = exports.InboxMedia = exports.Webhooks = exports.Exports = exports.Imports = exports.CrmTriggers = exports.Segments = exports.CustomFields = exports.ContactNotes = exports.ContactTags = exports.Contacts = exports.CHANNELS = exports.AUDIENCE = void 0;
|
|
17
|
+
exports.Activity = exports.Wallet = exports.Billing = exports.ChannelWebhooks = exports.Templates = exports.Channels = exports.resolveAudience = exports.parseDelimited = exports.normaliseNumbers = exports.normaliseColumn = exports.buildReceivers = exports.MAX_BULK_RECEIVERS = exports.CampaignReportExports = exports.CampaignReports = exports.Campaigns = exports.InboxMedia = exports.Notifications = exports.Webhooks = exports.Exports = exports.Imports = exports.CrmTriggers = exports.Segments = exports.CustomFields = exports.ContactNotes = exports.ContactTags = exports.Contacts = exports.CHANNELS = exports.AUDIENCE = void 0;
|
|
18
18
|
__exportStar(require("./client"), exports);
|
|
19
19
|
__exportStar(require("./http"), exports);
|
|
20
20
|
__exportStar(require("./errors"), exports);
|
|
@@ -41,8 +41,29 @@ var export_history_1 = require("./resources/audience/export-history");
|
|
|
41
41
|
Object.defineProperty(exports, "Exports", { enumerable: true, get: function () { return export_history_1.Exports; } });
|
|
42
42
|
var webhooks_1 = require("./resources/audience/webhooks");
|
|
43
43
|
Object.defineProperty(exports, "Webhooks", { enumerable: true, get: function () { return webhooks_1.Webhooks; } });
|
|
44
|
+
var notifications_1 = require("./resources/audience/notifications");
|
|
45
|
+
Object.defineProperty(exports, "Notifications", { enumerable: true, get: function () { return notifications_1.Notifications; } });
|
|
44
46
|
var inbox_media_1 = require("./resources/audience/inbox-media");
|
|
45
47
|
Object.defineProperty(exports, "InboxMedia", { enumerable: true, get: function () { return inbox_media_1.InboxMedia; } });
|
|
48
|
+
// Campaign
|
|
49
|
+
var campaigns_1 = require("./resources/campaigns");
|
|
50
|
+
Object.defineProperty(exports, "Campaigns", { enumerable: true, get: function () { return campaigns_1.Campaigns; } });
|
|
51
|
+
var campaign_reports_1 = require("./resources/campaign-reports");
|
|
52
|
+
Object.defineProperty(exports, "CampaignReports", { enumerable: true, get: function () { return campaign_reports_1.CampaignReports; } });
|
|
53
|
+
var campaign_report_exports_1 = require("./resources/campaign-report-exports");
|
|
54
|
+
Object.defineProperty(exports, "CampaignReportExports", { enumerable: true, get: function () { return campaign_report_exports_1.CampaignReportExports; } });
|
|
55
|
+
/**
|
|
56
|
+
* The audience helpers, exported because they are useful before a campaign
|
|
57
|
+
* exists: a UI can parse a CSV, show "12,480 recipients, 3 duplicates dropped",
|
|
58
|
+
* and let someone confirm before anything is uploaded.
|
|
59
|
+
*/
|
|
60
|
+
var campaign_audience_1 = require("./resources/campaign-audience");
|
|
61
|
+
Object.defineProperty(exports, "MAX_BULK_RECEIVERS", { enumerable: true, get: function () { return campaign_audience_1.MAX_BULK_RECEIVERS; } });
|
|
62
|
+
Object.defineProperty(exports, "buildReceivers", { enumerable: true, get: function () { return campaign_audience_1.buildReceivers; } });
|
|
63
|
+
Object.defineProperty(exports, "normaliseColumn", { enumerable: true, get: function () { return campaign_audience_1.normaliseColumn; } });
|
|
64
|
+
Object.defineProperty(exports, "normaliseNumbers", { enumerable: true, get: function () { return campaign_audience_1.normaliseNumbers; } });
|
|
65
|
+
Object.defineProperty(exports, "parseDelimited", { enumerable: true, get: function () { return campaign_audience_1.parseDelimited; } });
|
|
66
|
+
Object.defineProperty(exports, "resolveAudience", { enumerable: true, get: function () { return campaign_audience_1.resolveAudience; } });
|
|
46
67
|
// Channels
|
|
47
68
|
var channels_1 = require("./resources/channels/channels");
|
|
48
69
|
Object.defineProperty(exports, "Channels", { enumerable: true, get: function () { return channels_1.Channels; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,yCAAuB;AACvB,2CAAyB;AACzB,0CAAwB;AAExB,2CAAuD;AAA9C,iGAAA,QAAQ,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAE3B,WAAW;AACX,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,kEAAgE;AAAvD,2GAAA,WAAW,OAAA;AACpB,oEAAkE;AAAzD,6GAAA,YAAY,OAAA;AACrB,oEAAkE;AAAzD,6GAAA,YAAY,OAAA;AACrB,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,kEAAgE;AAAvD,2GAAA,WAAW,OAAA;AACpB,sEAA8D;AAArD,yGAAA,OAAO,OAAA;AAChB,sEAA8D;AAArD,yGAAA,OAAO,OAAA;AAChB,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,gEAI0C;AAHxC,yGAAA,UAAU,OAAA;AAKZ,WAAW;AACX,0DAA8E;AAArE,oGAAA,QAAQ,OAAA;AACjB,4DAA2D;AAAlD,sGAAA,SAAS,OAAA;AAClB,0DAAgE;AAAvD,2GAAA,eAAe,OAAA;AACxB,wDAAuD;AAA9C,kGAAA,OAAO,OAAA;AAChB,sDAAqD;AAA5C,gGAAA,MAAM,OAAA;AACf,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,yCAAuB;AACvB,2CAAyB;AACzB,0CAAwB;AAExB,2CAAuD;AAA9C,iGAAA,QAAQ,OAAA;AAAE,iGAAA,QAAQ,OAAA;AAE3B,WAAW;AACX,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,kEAAgE;AAAvD,2GAAA,WAAW,OAAA;AACpB,oEAAkE;AAAzD,6GAAA,YAAY,OAAA;AACrB,oEAAkE;AAAzD,6GAAA,YAAY,OAAA;AACrB,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,kEAAgE;AAAvD,2GAAA,WAAW,OAAA;AACpB,sEAA8D;AAArD,yGAAA,OAAO,OAAA;AAChB,sEAA8D;AAArD,yGAAA,OAAO,OAAA;AAChB,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,oEAAmE;AAA1D,8GAAA,aAAa,OAAA;AACtB,gEAI0C;AAHxC,yGAAA,UAAU,OAAA;AAKZ,WAAW;AACX,mDAS+B;AAR7B,sGAAA,SAAS,OAAA;AASX,iEAA+D;AAAtD,mHAAA,eAAe,OAAA;AACxB,+EAA4E;AAAnE,gIAAA,qBAAqB,OAAA;AAC9B;;;;GAIG;AACH,mEAUuC;AATrC,uHAAA,kBAAkB,OAAA;AAClB,mHAAA,cAAc,OAAA;AACd,oHAAA,eAAe,OAAA;AACf,qHAAA,gBAAgB,OAAA;AAChB,mHAAA,cAAc,OAAA;AACd,oHAAA,eAAe,OAAA;AAMjB,WAAW;AACX,0DAA8E;AAArE,oGAAA,QAAQ,OAAA;AACjB,4DAA2D;AAAlD,sGAAA,SAAS,OAAA;AAClB,0DAAgE;AAAvD,2GAAA,eAAe,OAAA;AACxB,wDAAuD;AAA9C,kGAAA,OAAO,OAAA;AAChB,sDAAqD;AAA5C,gGAAA,MAAM,OAAA;AACf,0DAAyD;AAAhD,oGAAA,QAAQ,OAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byte and text conversions, written out rather than taken from a platform.
|
|
3
|
+
*
|
|
4
|
+
* This SDK runs in a browser and in Node, and the obvious helpers differ between
|
|
5
|
+
* them: `btoa` is browser-first and deprecated in Node, `Buffer` does not exist
|
|
6
|
+
* in a browser, and feature-detecting between the two puts an environment branch
|
|
7
|
+
* in the middle of something that has to produce identical bytes everywhere.
|
|
8
|
+
* These are a few lines each and have no such branch.
|
|
9
|
+
*/
|
|
10
|
+
/** UTF-8 bytes of a string. `TextEncoder` is global in Node 18+ and every browser. */
|
|
11
|
+
export declare const utf8: (value: string) => Uint8Array;
|
|
12
|
+
/**
|
|
13
|
+
* A standalone `ArrayBuffer` holding a copy of these bytes.
|
|
14
|
+
*
|
|
15
|
+
* Web Crypto takes `BufferSource`, and a `Uint8Array` is not always one as far as
|
|
16
|
+
* the type system is concerned: since TypeScript 5.7 the array is generic in its
|
|
17
|
+
* backing buffer, and the `ArrayBufferLike` that `TextEncoder` hands back could
|
|
18
|
+
* in principle be a `SharedArrayBuffer`, which `BufferSource` excludes. Copying
|
|
19
|
+
* into a buffer of known provenance settles it without an assertion, and without
|
|
20
|
+
* putting a generic type parameter into the emitted declarations -- which would
|
|
21
|
+
* make this package fail to typecheck for anyone on an older compiler.
|
|
22
|
+
*/
|
|
23
|
+
export declare const toArrayBuffer: (bytes: Uint8Array) => ArrayBuffer;
|
|
24
|
+
/** Standard base64, with padding -- the form `CryptoJS`'s default formatter emits. */
|
|
25
|
+
export declare const toBase64: (bytes: Uint8Array) => string;
|
|
26
|
+
/** Lower-case hex, two characters per byte. */
|
|
27
|
+
export declare const toHex: (bytes: Uint8Array) => string;
|
|
28
|
+
/**
|
|
29
|
+
* Cryptographically random bytes.
|
|
30
|
+
*
|
|
31
|
+
* `crypto.getRandomValues` is the one API that is present and seeded properly in
|
|
32
|
+
* both environments -- global in Node 18+ and in browsers. `Math.random` is not
|
|
33
|
+
* an acceptable substitute here: the value it would produce is the key under
|
|
34
|
+
* which a customer's phone numbers are encrypted.
|
|
35
|
+
*/
|
|
36
|
+
export declare const randomBytes: (length: number) => Uint8Array;
|
|
37
|
+
/** Web Crypto, or a clear error naming what is missing rather than a `TypeError`. */
|
|
38
|
+
export declare const subtle: () => SubtleCrypto;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Byte and text conversions, written out rather than taken from a platform.
|
|
4
|
+
*
|
|
5
|
+
* This SDK runs in a browser and in Node, and the obvious helpers differ between
|
|
6
|
+
* them: `btoa` is browser-first and deprecated in Node, `Buffer` does not exist
|
|
7
|
+
* in a browser, and feature-detecting between the two puts an environment branch
|
|
8
|
+
* in the middle of something that has to produce identical bytes everywhere.
|
|
9
|
+
* These are a few lines each and have no such branch.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.subtle = exports.randomBytes = exports.toHex = exports.toBase64 = exports.toArrayBuffer = exports.utf8 = void 0;
|
|
13
|
+
/** UTF-8 bytes of a string. `TextEncoder` is global in Node 18+ and every browser. */
|
|
14
|
+
const utf8 = (value) => new TextEncoder().encode(value);
|
|
15
|
+
exports.utf8 = utf8;
|
|
16
|
+
/**
|
|
17
|
+
* A standalone `ArrayBuffer` holding a copy of these bytes.
|
|
18
|
+
*
|
|
19
|
+
* Web Crypto takes `BufferSource`, and a `Uint8Array` is not always one as far as
|
|
20
|
+
* the type system is concerned: since TypeScript 5.7 the array is generic in its
|
|
21
|
+
* backing buffer, and the `ArrayBufferLike` that `TextEncoder` hands back could
|
|
22
|
+
* in principle be a `SharedArrayBuffer`, which `BufferSource` excludes. Copying
|
|
23
|
+
* into a buffer of known provenance settles it without an assertion, and without
|
|
24
|
+
* putting a generic type parameter into the emitted declarations -- which would
|
|
25
|
+
* make this package fail to typecheck for anyone on an older compiler.
|
|
26
|
+
*/
|
|
27
|
+
const toArrayBuffer = (bytes) => {
|
|
28
|
+
const buffer = new ArrayBuffer(bytes.length);
|
|
29
|
+
new Uint8Array(buffer).set(bytes);
|
|
30
|
+
return buffer;
|
|
31
|
+
};
|
|
32
|
+
exports.toArrayBuffer = toArrayBuffer;
|
|
33
|
+
const BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
34
|
+
/** Standard base64, with padding -- the form `CryptoJS`'s default formatter emits. */
|
|
35
|
+
const toBase64 = (bytes) => {
|
|
36
|
+
let out = '';
|
|
37
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
38
|
+
const a = bytes[i];
|
|
39
|
+
const b = bytes[i + 1];
|
|
40
|
+
const c = bytes[i + 2];
|
|
41
|
+
out += BASE64_ALPHABET[a >> 2];
|
|
42
|
+
out += BASE64_ALPHABET[((a & 0x03) << 4) | ((b ?? 0) >> 4)];
|
|
43
|
+
out += b === undefined ? '=' : BASE64_ALPHABET[((b & 0x0f) << 2) | ((c ?? 0) >> 6)];
|
|
44
|
+
out += c === undefined ? '=' : BASE64_ALPHABET[c & 0x3f];
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
};
|
|
48
|
+
exports.toBase64 = toBase64;
|
|
49
|
+
/** Lower-case hex, two characters per byte. */
|
|
50
|
+
const toHex = (bytes) => {
|
|
51
|
+
let out = '';
|
|
52
|
+
for (const byte of bytes)
|
|
53
|
+
out += byte.toString(16).padStart(2, '0');
|
|
54
|
+
return out;
|
|
55
|
+
};
|
|
56
|
+
exports.toHex = toHex;
|
|
57
|
+
/**
|
|
58
|
+
* Cryptographically random bytes.
|
|
59
|
+
*
|
|
60
|
+
* `crypto.getRandomValues` is the one API that is present and seeded properly in
|
|
61
|
+
* both environments -- global in Node 18+ and in browsers. `Math.random` is not
|
|
62
|
+
* an acceptable substitute here: the value it would produce is the key under
|
|
63
|
+
* which a customer's phone numbers are encrypted.
|
|
64
|
+
*/
|
|
65
|
+
const randomBytes = (length) => {
|
|
66
|
+
const source = globalThis.crypto;
|
|
67
|
+
if (!source?.getRandomValues) {
|
|
68
|
+
throw new Error('No cryptographic random source: globalThis.crypto.getRandomValues is unavailable. ' +
|
|
69
|
+
'This SDK needs Node 18+ or a browser with Web Crypto.');
|
|
70
|
+
}
|
|
71
|
+
return source.getRandomValues(new Uint8Array(length));
|
|
72
|
+
};
|
|
73
|
+
exports.randomBytes = randomBytes;
|
|
74
|
+
/** Web Crypto, or a clear error naming what is missing rather than a `TypeError`. */
|
|
75
|
+
const subtle = () => {
|
|
76
|
+
const source = globalThis.crypto;
|
|
77
|
+
if (!source?.subtle) {
|
|
78
|
+
throw new Error('Web Crypto is unavailable: globalThis.crypto.subtle is missing. ' +
|
|
79
|
+
'Encrypting campaign receivers needs Node 18+ or a secure browser context (https or localhost).');
|
|
80
|
+
}
|
|
81
|
+
return source.subtle;
|
|
82
|
+
};
|
|
83
|
+
exports.subtle = subtle;
|
|
84
|
+
//# sourceMappingURL=bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/internal/bytes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DevicePlatform } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* A label a person would recognise their own browser by, e.g. `Chrome on Windows`.
|
|
4
|
+
*
|
|
5
|
+
* `undefined` rather than a placeholder when there is nothing to go on -- the
|
|
6
|
+
* field is optional, and an omitted label reads back as `''`, which a UI can
|
|
7
|
+
* render as "this device" far better than a string like `Unknown on Unknown`
|
|
8
|
+
* can.
|
|
9
|
+
*
|
|
10
|
+
* Only the family and the system, never the version. A version would change the
|
|
11
|
+
* label every few weeks on a device that has not changed, and the label exists
|
|
12
|
+
* to be recognised rather than to be precise.
|
|
13
|
+
*/
|
|
14
|
+
export declare const describeDevice: () => string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* `'web'` when there is a DOM, `undefined` otherwise.
|
|
17
|
+
*
|
|
18
|
+
* Keyed on `document` and not on `navigator`, which is the distinction that
|
|
19
|
+
* matters: React Native defines a `navigator` but no `document`, so a
|
|
20
|
+
* navigator-based check would quietly register every mobile device as a browser
|
|
21
|
+
* and the send path would fill in the `webpush` block instead of `android`/`apns`
|
|
22
|
+
* -- a notification that is accepted by FCM and never shown.
|
|
23
|
+
*/
|
|
24
|
+
export declare const detectPlatform: () => DevicePlatform | undefined;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectPlatform = exports.describeDevice = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* What the current runtime is, for the two fields a caller should not have to
|
|
6
|
+
* fill in by hand.
|
|
7
|
+
*
|
|
8
|
+
* Both functions here are best-effort and both are cosmetic-or-defaultable:
|
|
9
|
+
* nothing in the send path depends on getting the label right, and a platform
|
|
10
|
+
* that cannot be detected is asked for rather than guessed.
|
|
11
|
+
*
|
|
12
|
+
* ## Why this is not the `user-agents` package
|
|
13
|
+
*
|
|
14
|
+
* The legacy panel sent its `device` field as `new UserAgent().data` from the
|
|
15
|
+
* `user-agents` npm package. That package **generates a random plausible user
|
|
16
|
+
* agent**; it does not read the browser's own. So every device row ever written
|
|
17
|
+
* by the old panel describes a machine that does not exist, which is why the
|
|
18
|
+
* replacement stores a caller-supplied label instead of a parsed object, and why
|
|
19
|
+
* the default below reads `navigator.userAgent` directly.
|
|
20
|
+
*/
|
|
21
|
+
/** The browser's own user agent, or `undefined` outside a browser. */
|
|
22
|
+
const userAgent = () => {
|
|
23
|
+
const nav = globalThis.navigator;
|
|
24
|
+
return typeof nav?.userAgent === 'string' && nav.userAgent ? nav.userAgent : undefined;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Browser families, **most specific first**.
|
|
28
|
+
*
|
|
29
|
+
* The order is the whole correctness of this table: Edge and Opera both carry
|
|
30
|
+
* `Chrome/` in their user agent, and every Chromium browser carries `Safari/`.
|
|
31
|
+
* Matching in declaration order is what keeps Edge from reading as Chrome and
|
|
32
|
+
* Chrome from reading as Safari.
|
|
33
|
+
*/
|
|
34
|
+
const BROWSERS = [
|
|
35
|
+
[/\bEdg(?:e|A|iOS)?\//, 'Edge'],
|
|
36
|
+
[/\bOPR\/|\bOpera\//, 'Opera'],
|
|
37
|
+
[/\bSamsungBrowser\//, 'Samsung Internet'],
|
|
38
|
+
[/\bFirefox\/|\bFxiOS\//, 'Firefox'],
|
|
39
|
+
// Chrome on iOS is `CriOS`: it is Safari's engine wearing Chrome's name, and
|
|
40
|
+
// the name is what a user would recognise in a device list.
|
|
41
|
+
[/\bChrome\/|\bCriOS\//, 'Chrome'],
|
|
42
|
+
[/\bSafari\//, 'Safari'],
|
|
43
|
+
];
|
|
44
|
+
/** Operating systems, also most specific first -- an Android UA also says `Linux`. */
|
|
45
|
+
const SYSTEMS = [
|
|
46
|
+
[/\bWindows\b/, 'Windows'],
|
|
47
|
+
[/\bAndroid\b/, 'Android'],
|
|
48
|
+
[/\b(?:iPhone|iPad|iPod)\b/, 'iOS'],
|
|
49
|
+
[/\bCrOS\b/, 'ChromeOS'],
|
|
50
|
+
[/\bMac OS X\b|\bMacintosh\b/, 'macOS'],
|
|
51
|
+
[/\bLinux\b/, 'Linux'],
|
|
52
|
+
];
|
|
53
|
+
const match = (table, ua) => table.find(([pattern]) => pattern.test(ua))?.[1];
|
|
54
|
+
/**
|
|
55
|
+
* A label a person would recognise their own browser by, e.g. `Chrome on Windows`.
|
|
56
|
+
*
|
|
57
|
+
* `undefined` rather than a placeholder when there is nothing to go on -- the
|
|
58
|
+
* field is optional, and an omitted label reads back as `''`, which a UI can
|
|
59
|
+
* render as "this device" far better than a string like `Unknown on Unknown`
|
|
60
|
+
* can.
|
|
61
|
+
*
|
|
62
|
+
* Only the family and the system, never the version. A version would change the
|
|
63
|
+
* label every few weeks on a device that has not changed, and the label exists
|
|
64
|
+
* to be recognised rather than to be precise.
|
|
65
|
+
*/
|
|
66
|
+
const describeDevice = () => {
|
|
67
|
+
const ua = userAgent();
|
|
68
|
+
if (!ua)
|
|
69
|
+
return undefined;
|
|
70
|
+
const browser = match(BROWSERS, ua);
|
|
71
|
+
const system = match(SYSTEMS, ua);
|
|
72
|
+
if (browser && system)
|
|
73
|
+
return `${browser} on ${system}`;
|
|
74
|
+
return browser ?? system;
|
|
75
|
+
};
|
|
76
|
+
exports.describeDevice = describeDevice;
|
|
77
|
+
/**
|
|
78
|
+
* `'web'` when there is a DOM, `undefined` otherwise.
|
|
79
|
+
*
|
|
80
|
+
* Keyed on `document` and not on `navigator`, which is the distinction that
|
|
81
|
+
* matters: React Native defines a `navigator` but no `document`, so a
|
|
82
|
+
* navigator-based check would quietly register every mobile device as a browser
|
|
83
|
+
* and the send path would fill in the `webpush` block instead of `android`/`apns`
|
|
84
|
+
* -- a notification that is accepted by FCM and never shown.
|
|
85
|
+
*/
|
|
86
|
+
const detectPlatform = () => typeof globalThis.document === 'object' &&
|
|
87
|
+
globalThis.document !== null
|
|
88
|
+
? 'web'
|
|
89
|
+
: undefined;
|
|
90
|
+
exports.detectPlatform = detectPlatform;
|
|
91
|
+
//# sourceMappingURL=device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../src/internal/device.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,sEAAsE;AACtE,MAAM,SAAS,GAAG,GAAuB,EAAE;IACzC,MAAM,GAAG,GAAI,UAAsD,CAAC,SAAS,CAAC;IAC9E,OAAO,OAAO,GAAG,EAAE,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AACzF,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,QAAQ,GAAgC;IAC5C,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAC/B,CAAC,mBAAmB,EAAE,OAAO,CAAC;IAC9B,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;IAC1C,CAAC,uBAAuB,EAAE,SAAS,CAAC;IACpC,6EAA6E;IAC7E,4DAA4D;IAC5D,CAAC,sBAAsB,EAAE,QAAQ,CAAC;IAClC,CAAC,YAAY,EAAE,QAAQ,CAAC;CACzB,CAAC;AAEF,sFAAsF;AACtF,MAAM,OAAO,GAAgC;IAC3C,CAAC,aAAa,EAAE,SAAS,CAAC;IAC1B,CAAC,aAAa,EAAE,SAAS,CAAC;IAC1B,CAAC,0BAA0B,EAAE,KAAK,CAAC;IACnC,CAAC,UAAU,EAAE,UAAU,CAAC;IACxB,CAAC,4BAA4B,EAAE,OAAO,CAAC;IACvC,CAAC,WAAW,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,KAAkC,EAAE,EAAU,EAAsB,EAAE,CACnF,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEnD;;;;;;;;;;;GAWG;AACI,MAAM,cAAc,GAAG,GAAuB,EAAE;IACrD,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IAE1B,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAElC,IAAI,OAAO,IAAI,MAAM;QAAE,OAAO,GAAG,OAAO,OAAO,MAAM,EAAE,CAAC;IACxD,OAAO,OAAO,IAAI,MAAM,CAAC;AAC3B,CAAC,CAAC;AATW,QAAA,cAAc,kBASzB;AAEF;;;;;;;;GAQG;AACI,MAAM,cAAc,GAAG,GAA+B,EAAE,CAC7D,OAAQ,UAAqC,CAAC,QAAQ,KAAK,QAAQ;IAClE,UAAqC,CAAC,QAAQ,KAAK,IAAI;IACtD,CAAC,CAAC,KAAK;IACP,CAAC,CAAC,SAAS,CAAC;AAJH,QAAA,cAAc,kBAIX"}
|