@cloudsignal/pwa-sdk 2.0.0 → 2.1.0

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,19 @@ 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
+ ## [2.1.0] - 2026-04-23
9
+
10
+ ### Added
11
+
12
+ - **Auto-register PWA installations on `initialize()`** — when the SDK detects it is running in standalone / installed mode, it automatically POSTs to `/api/v1/registration/install-only` so the device shows up in the Clients tab without requiring the user to enable push first. A subsequent `registerForPush()` call upgrades the same row server-side (matched by browser fingerprint).
13
+ - `registerInstallation()` public method on `CloudSignalPWA` for manual install tracking.
14
+ - `install:registered` event fires after the backend acknowledges the install registration. Payload: `{ registrationId }`.
15
+ - Installation registrations are guarded by a localStorage flag (`isInstallationRegistered` / `markInstallationRegistered`) so repeat `initialize()` calls within the same storage session are no-ops.
16
+
17
+ ### Fixed
18
+
19
+ - Restores the auto-install-registration feature originally shipped in 1.2.3 that was inadvertently removed in commit `42935abf`.
20
+
8
21
  ## [2.0.0] - 2026-04-23
9
22
 
10
23
  ### Changed (BREAKING)
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;
@@ -1473,6 +1482,64 @@ var PushNotificationManager = class {
1473
1482
  return null;
1474
1483
  }
1475
1484
  }
1485
+ /**
1486
+ * Register a PWA installation without a push subscription.
1487
+ *
1488
+ * Tracks users who installed the PWA (standalone display mode) but
1489
+ * haven't granted notification permission yet. A subsequent
1490
+ * ``registerForPush()`` call upgrades the same row to a full push
1491
+ * registration (matched server-side by browser fingerprint).
1492
+ *
1493
+ * Guarded by a localStorage flag so repeat ``initialize()`` calls in
1494
+ * the same storage session are no-ops.
1495
+ */
1496
+ async registerInstallation() {
1497
+ try {
1498
+ if (isInstallationRegistered(this.organizationId, this.serviceId)) {
1499
+ this.log("Installation already registered, skipping");
1500
+ return null;
1501
+ }
1502
+ const fingerprint = await generateBrowserFingerprint();
1503
+ const deviceInfo = this.deviceDetector.getDeviceInfo();
1504
+ const platformInfo = this.deviceDetector.getPlatformInfo();
1505
+ const installationData = {
1506
+ service_id: this.serviceId,
1507
+ browser_fingerprint: fingerprint || void 0,
1508
+ device_type: deviceInfo.deviceType,
1509
+ device_model: deviceInfo.deviceModel,
1510
+ browser_name: platformInfo.browser,
1511
+ browser_version: platformInfo.browserVersion,
1512
+ os_name: platformInfo.os,
1513
+ os_version: platformInfo.osVersion,
1514
+ user_agent: platformInfo.userAgent,
1515
+ display_mode: "standalone",
1516
+ is_installed: true,
1517
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
1518
+ language: navigator.language || "en-US"
1519
+ };
1520
+ const url = `${this.serviceUrl}/api/v1/registration/install-only`;
1521
+ const response = await makeAuthenticatedRequestWithContext(
1522
+ this.authContext,
1523
+ "POST",
1524
+ url,
1525
+ installationData,
1526
+ this.onTokenExpired
1527
+ );
1528
+ if (!response.ok) {
1529
+ const errorText = await response.text();
1530
+ throw new Error(`Installation registration failed: ${response.status} - ${errorText}`);
1531
+ }
1532
+ const result = await response.json();
1533
+ markInstallationRegistered(this.organizationId, this.serviceId, result.registration_id);
1534
+ this.log(`Installation registered: ${result.registration_id}`);
1535
+ return { registrationId: result.registration_id };
1536
+ } catch (error) {
1537
+ const err = error instanceof Error ? error : new Error(String(error));
1538
+ this.log(`Installation registration failed: ${err.message}`, "error");
1539
+ this.onError?.(err);
1540
+ return null;
1541
+ }
1542
+ }
1476
1543
  /**
1477
1544
  * Unregister from push notifications
1478
1545
  */
@@ -3258,11 +3325,19 @@ var CloudSignalPWA = class {
3258
3325
  this.configureNotificationAnalytics(swReg);
3259
3326
  }
3260
3327
  if (this.iosInstallBanner && this.config.iosInstallBanner?.showOnFirstVisit !== false) {
3261
- const installState = this.installationManager.getState();
3262
- if (!installState.isInstalled) {
3328
+ const installState2 = this.installationManager.getState();
3329
+ if (!installState2.isInstalled) {
3263
3330
  this.iosInstallBanner.show();
3264
3331
  }
3265
3332
  }
3333
+ const installState = this.installationManager.getState();
3334
+ if (installState.isInstalled) {
3335
+ this.log("PWA installation detected, registering\u2026");
3336
+ const installResult = await this.pushNotificationManager.registerInstallation();
3337
+ if (installResult) {
3338
+ this.emit("install:registered", { registrationId: installResult.registrationId });
3339
+ }
3340
+ }
3266
3341
  this.initialized = true;
3267
3342
  const result = {
3268
3343
  success: true,