@cloudsignal/pwa-sdk 1.2.2 → 1.2.3

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/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.3] - 2026-01-19
9
+
10
+ ### Added
11
+
12
+ - **Auto Installation Tracking** - Automatically registers PWA installations with the backend when detected
13
+ - `registerInstallation()` method for manual installation tracking without push subscription
14
+ - `isInstallationRegistered()` method to check if installation is already tracked
15
+ - `getInstallationId()` method to get stored installation registration ID
16
+ - `install:registered` event emitted when installation is registered with backend
17
+ - Installation tracking works with both HMAC (anonymous) and JWT (authenticated) modes
18
+
19
+ ### Changed
20
+
21
+ - `initialize()` now auto-calls `registerInstallation()` when PWA is detected as installed
22
+ - Prevents duplicate registrations using localStorage tracking
23
+
24
+ ### Backend Support
25
+
26
+ - `/api/v1/registration/install-only` endpoint now supports JWT authentication
27
+ - Installation registrations include `auth_method`, `auth_provider`, and `idp_user_id` for JWT mode
28
+
8
29
  ## [1.2.0] - 2025-01-17
9
30
 
10
31
  ### Added
package/dist/index.cjs CHANGED
@@ -1141,6 +1141,15 @@ function removeRegistrationId(organizationId, serviceId) {
1141
1141
  const key = `registration_${organizationId}_${serviceId}`;
1142
1142
  return removeStorageItem(key);
1143
1143
  }
1144
+ function isInstallationRegistered(organizationId, serviceId) {
1145
+ const key = `install_registered_${organizationId}_${serviceId}`;
1146
+ return getStorageItem(key) === true;
1147
+ }
1148
+ function markInstallationRegistered(organizationId, serviceId, registrationId) {
1149
+ const key = `install_registered_${organizationId}_${serviceId}`;
1150
+ setStorageItem(`install_id_${organizationId}_${serviceId}`, registrationId);
1151
+ return setStorageItem(key, true);
1152
+ }
1144
1153
  var IndexedDBStorage = class {
1145
1154
  constructor(dbName = "CloudSignalPWA", dbVersion = 1) {
1146
1155
  this.db = null;
@@ -1586,6 +1595,72 @@ var PushNotificationManager = class {
1586
1595
  return null;
1587
1596
  }
1588
1597
  }
1598
+ /**
1599
+ * Register PWA installation without push subscription.
1600
+ * This tracks users who installed the PWA but haven't subscribed to notifications.
1601
+ * Called automatically when installation is detected.
1602
+ *
1603
+ * @returns Installation registration result or null if already registered/failed
1604
+ */
1605
+ async registerInstallation() {
1606
+ try {
1607
+ if (isInstallationRegistered(this.organizationId, this.serviceId)) {
1608
+ this.log("Installation already registered, skipping");
1609
+ return null;
1610
+ }
1611
+ const fingerprint = await generateBrowserFingerprint();
1612
+ const deviceInfo = this.deviceDetector.getDeviceInfo();
1613
+ const platformInfo = this.deviceDetector.getPlatformInfo();
1614
+ const installationData = {
1615
+ service_id: this.serviceId,
1616
+ browser_fingerprint: fingerprint || void 0,
1617
+ device_type: deviceInfo.deviceType,
1618
+ device_model: deviceInfo.deviceModel,
1619
+ browser_name: platformInfo.browser,
1620
+ browser_version: platformInfo.browserVersion,
1621
+ os_name: platformInfo.os,
1622
+ os_version: platformInfo.osVersion,
1623
+ user_agent: platformInfo.userAgent,
1624
+ display_mode: "standalone",
1625
+ is_installed: true,
1626
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
1627
+ language: navigator.language || "en-US"
1628
+ };
1629
+ const url = `${this.serviceUrl}/api/v1/registration/install-only`;
1630
+ const response = await makeAuthenticatedRequestWithContext(
1631
+ this.authContext,
1632
+ "POST",
1633
+ url,
1634
+ installationData,
1635
+ this.onTokenExpired
1636
+ );
1637
+ if (!response.ok) {
1638
+ const errorText = await response.text();
1639
+ throw new Error(`Installation registration failed: ${response.status} - ${errorText}`);
1640
+ }
1641
+ const result = await response.json();
1642
+ markInstallationRegistered(this.organizationId, this.serviceId, result.registration_id);
1643
+ this.log(`Installation registered successfully: ${result.registration_id}`);
1644
+ return { registrationId: result.registration_id };
1645
+ } catch (error) {
1646
+ const err = error instanceof Error ? error : new Error(String(error));
1647
+ this.log(`Installation registration failed: ${err.message}`, "error");
1648
+ this.onError?.(err);
1649
+ return null;
1650
+ }
1651
+ }
1652
+ /**
1653
+ * Check if installation is already registered
1654
+ */
1655
+ isInstallationRegistered() {
1656
+ return isInstallationRegistered(this.organizationId, this.serviceId);
1657
+ }
1658
+ /**
1659
+ * Get stored installation registration ID
1660
+ */
1661
+ getInstallationId() {
1662
+ return getStorageItem(`install_id_${this.organizationId}_${this.serviceId}`);
1663
+ }
1589
1664
  /**
1590
1665
  * Request notification permission
1591
1666
  */
@@ -3117,7 +3192,7 @@ var IOSInstallBanner = class {
3117
3192
 
3118
3193
  // src/CloudSignalPWA.ts
3119
3194
  var DEFAULT_SERVICE_URL = "https://pwa.cloudsignal.app";
3120
- var SDK_VERSION = "1.2.0";
3195
+ var SDK_VERSION = "1.2.3";
3121
3196
  var CloudSignalPWA = class {
3122
3197
  constructor(config) {
3123
3198
  this.initialized = false;
@@ -3258,11 +3333,20 @@ var CloudSignalPWA = class {
3258
3333
  this.configureNotificationAnalytics(swReg);
3259
3334
  }
3260
3335
  if (this.iosInstallBanner && this.config.iosInstallBanner?.showOnFirstVisit !== false) {
3261
- const installState = this.installationManager.getState();
3262
- if (!installState.isInstalled) {
3336
+ const installState2 = this.installationManager.getState();
3337
+ if (!installState2.isInstalled) {
3263
3338
  this.iosInstallBanner.show();
3264
3339
  }
3265
3340
  }
3341
+ const installState = this.installationManager.getState();
3342
+ if (installState.isInstalled) {
3343
+ this.log("PWA installation detected, registering...");
3344
+ const installResult = await this.pushNotificationManager.registerInstallation();
3345
+ if (installResult) {
3346
+ this.log(`Installation registered: ${installResult.registrationId}`);
3347
+ this.emit("install:registered", { registrationId: installResult.registrationId });
3348
+ }
3349
+ }
3266
3350
  this.initialized = true;
3267
3351
  const result = {
3268
3352
  success: true,