@cloudsignal/pwa-sdk 1.2.4 → 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.
@@ -52,10 +52,10 @@ async function generateHMACSignature(secret, organizationId, timestamp, method,
52
52
  const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(canonicalString));
53
53
  return toBase64(signature);
54
54
  }
55
- async function generateAuthHeaders(organizationId, organizationSecret, method, url, body) {
55
+ async function generateAuthHeaders(organizationId, organizationPublishableKey, method, url, body) {
56
56
  const timestamp = Math.floor(Date.now() / 1e3).toString();
57
57
  const signature = await generateHMACSignature(
58
- organizationSecret,
58
+ organizationPublishableKey,
59
59
  organizationId,
60
60
  timestamp,
61
61
  method,
@@ -69,11 +69,11 @@ async function generateAuthHeaders(organizationId, organizationSecret, method, u
69
69
  "Content-Type": "application/json"
70
70
  };
71
71
  }
72
- async function makeAuthenticatedRequest(organizationId, organizationSecret, method, url, body) {
72
+ async function makeAuthenticatedRequest(organizationId, organizationPublishableKey, method, url, body) {
73
73
  const bodyStr = body ? JSON.stringify(body) : void 0;
74
74
  const headers = await generateAuthHeaders(
75
75
  organizationId,
76
- organizationSecret,
76
+ organizationPublishableKey,
77
77
  method,
78
78
  url,
79
79
  bodyStr
@@ -93,5 +93,5 @@ function isValidUUID(value) {
93
93
  }
94
94
 
95
95
  export { generateAuthHeaders, generateHMACSignature, isValidUUID, makeAuthenticatedRequest };
96
- //# sourceMappingURL=chunk-IMM7VF4N.js.map
97
- //# sourceMappingURL=chunk-IMM7VF4N.js.map
96
+ //# sourceMappingURL=chunk-IQHSODT4.js.map
97
+ //# sourceMappingURL=chunk-IQHSODT4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/hmac.ts"],"names":[],"mappings":"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","file":"chunk-IQHSODT4.js","sourcesContent":["/**\n * HMAC Authentication Utilities\n * Implements CloudSignal's HMAC signature scheme for API authentication\n */\n\n/**\n * Convert ArrayBuffer to hex string\n */\nfunction toHex(buffer: ArrayBuffer): string {\n return Array.from(new Uint8Array(buffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * Convert ArrayBuffer to base64 string\n */\nfunction toBase64(buffer: ArrayBuffer): string {\n return btoa(String.fromCharCode(...new Uint8Array(buffer)))\n}\n\n/**\n * Generate HMAC signature for CloudSignal API requests\n *\n * @param secret - Signing key (organization publishable key, pk_*)\n * @param organizationId - Organization UUID\n * @param timestamp - Unix timestamp string\n * @param method - HTTP method (GET, POST, etc.)\n * @param url - Full URL or path\n * @param body - Request body (optional)\n * @returns Base64-encoded HMAC signature\n */\nexport async function generateHMACSignature(\n secret: string,\n organizationId: string,\n timestamp: string,\n method: string,\n url: string,\n body: string = ''\n): Promise<string> {\n const encoder = new TextEncoder()\n\n // Parse URL to extract path and query\n let path: string\n let query: string\n\n try {\n const urlObj = url.startsWith('http')\n ? new URL(url)\n : new URL(url, 'https://pwa.cloudsignal.app')\n path = urlObj.pathname\n query = urlObj.search ? urlObj.search.slice(1) : ''\n } catch {\n // Fallback for simple paths\n const queryIndex = url.indexOf('?')\n if (queryIndex > -1) {\n path = url.slice(0, queryIndex)\n query = url.slice(queryIndex + 1)\n } else {\n path = url\n query = ''\n }\n }\n\n // Build canonical string parts\n const canonicalParts = [\n method.toUpperCase(),\n path,\n query,\n organizationId,\n timestamp,\n ]\n\n // Add body hash if body is present\n if (body && body.length > 0) {\n const bodyHashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(body))\n const bodyHashHex = toHex(bodyHashBuffer)\n canonicalParts.push(bodyHashHex)\n }\n\n // Join parts with newlines\n const canonicalString = canonicalParts.join('\\n')\n\n // Import secret as HMAC key\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n )\n\n // Sign the canonical string\n const signature = await crypto.subtle.sign('HMAC', key, encoder.encode(canonicalString))\n\n return toBase64(signature)\n}\n\n/**\n * Generate authentication headers for CloudSignal API requests\n *\n * @param organizationId - Organization UUID\n * @param organizationPublishableKey - Organization publishable key (pk_*)\n * @param method - HTTP method\n * @param url - Request URL\n * @param body - Request body (optional)\n * @returns Headers object with authentication headers\n */\nexport async function generateAuthHeaders(\n organizationId: string,\n organizationPublishableKey: string,\n method: string,\n url: string,\n body?: string\n): Promise<Record<string, string>> {\n const timestamp = Math.floor(Date.now() / 1000).toString()\n\n const signature = await generateHMACSignature(\n organizationPublishableKey,\n organizationId,\n timestamp,\n method,\n url,\n body || ''\n )\n\n return {\n 'X-CloudSignal-Organization-ID': organizationId,\n 'X-CloudSignal-Timestamp': timestamp,\n 'X-CloudSignal-Signature': signature,\n 'Content-Type': 'application/json',\n }\n}\n\n/**\n * Make an authenticated request to CloudSignal API\n *\n * @param organizationId - Organization UUID\n * @param organizationPublishableKey - Organization publishable key (pk_*)\n * @param method - HTTP method\n * @param url - Request URL\n * @param body - Request body (optional)\n * @returns Fetch Response\n */\nexport async function makeAuthenticatedRequest(\n organizationId: string,\n organizationPublishableKey: string,\n method: string,\n url: string,\n body?: Record<string, any>\n): Promise<Response> {\n const bodyStr = body ? JSON.stringify(body) : undefined\n\n const headers = await generateAuthHeaders(\n organizationId,\n organizationPublishableKey,\n method,\n url,\n bodyStr\n )\n\n const options: RequestInit = {\n method,\n headers,\n }\n\n if (bodyStr) {\n options.body = bodyStr\n }\n\n return fetch(url, options)\n}\n\n/**\n * Validate UUID format\n * \n * @param value - String to validate\n * @returns Whether the string is a valid UUID\n */\nexport function isValidUUID(value: string | null | undefined): boolean {\n if (!value || typeof value !== 'string') return false\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export { generateAuthHeaders, generateHMACSignature, isValidUUID, makeAuthenticatedRequest } from './chunk-IQHSODT4.js';
2
+ //# sourceMappingURL=hmac-WITZIX2O.js.map
3
+ //# sourceMappingURL=hmac-WITZIX2O.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"hmac-LWLR6F7Z.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"hmac-WITZIX2O.js"}
package/dist/index.cjs CHANGED
@@ -72,10 +72,10 @@ async function generateHMACSignature(secret, organizationId, timestamp, method,
72
72
  const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(canonicalString));
73
73
  return toBase64(signature);
74
74
  }
75
- async function generateAuthHeaders(organizationId, organizationSecret, method, url, body) {
75
+ async function generateAuthHeaders(organizationId, organizationPublishableKey, method, url, body) {
76
76
  const timestamp = Math.floor(Date.now() / 1e3).toString();
77
77
  const signature = await generateHMACSignature(
78
- organizationSecret,
78
+ organizationPublishableKey,
79
79
  organizationId,
80
80
  timestamp,
81
81
  method,
@@ -89,11 +89,11 @@ async function generateAuthHeaders(organizationId, organizationSecret, method, u
89
89
  "Content-Type": "application/json"
90
90
  };
91
91
  }
92
- async function makeAuthenticatedRequest(organizationId, organizationSecret, method, url, body) {
92
+ async function makeAuthenticatedRequest(organizationId, organizationPublishableKey, method, url, body) {
93
93
  const bodyStr = body ? JSON.stringify(body) : void 0;
94
94
  const headers = await generateAuthHeaders(
95
95
  organizationId,
96
- organizationSecret,
96
+ organizationPublishableKey,
97
97
  method,
98
98
  url,
99
99
  bodyStr
@@ -1046,13 +1046,13 @@ function createAuthContext(config) {
1046
1046
  onTokenExpired: config.onTokenExpired
1047
1047
  };
1048
1048
  }
1049
- if (!config.organizationSecret) {
1050
- throw new Error("Either userToken or organizationSecret is required");
1049
+ if (!config.organizationPublishableKey) {
1050
+ throw new Error("Either userToken or organizationPublishableKey is required");
1051
1051
  }
1052
1052
  return {
1053
1053
  mode: "hmac",
1054
1054
  organizationId: config.organizationId,
1055
- organizationSecret: config.organizationSecret
1055
+ organizationPublishableKey: config.organizationPublishableKey
1056
1056
  };
1057
1057
  }
1058
1058
  async function makeAuthenticatedRequestWithContext(authContext, method, url, body, onTokenExpired) {
@@ -1073,12 +1073,12 @@ async function makeAuthenticatedRequestWithContext(authContext, method, url, bod
1073
1073
  );
1074
1074
  }
1075
1075
  const { makeAuthenticatedRequest: makeAuthenticatedRequest4 } = await Promise.resolve().then(() => (init_hmac(), hmac_exports));
1076
- if (!authContext.organizationSecret) {
1077
- throw new Error("organizationSecret required for HMAC auth mode");
1076
+ if (!authContext.organizationPublishableKey) {
1077
+ throw new Error("organizationPublishableKey required for HMAC auth mode");
1078
1078
  }
1079
1079
  return makeAuthenticatedRequest4(
1080
1080
  authContext.organizationId,
1081
- authContext.organizationSecret,
1081
+ authContext.organizationPublishableKey,
1082
1082
  method,
1083
1083
  url,
1084
1084
  body
@@ -1356,7 +1356,7 @@ var PushNotificationManager = class {
1356
1356
  this.deviceDetector = new DeviceDetector();
1357
1357
  this.authContext = createAuthContext({
1358
1358
  organizationId: options.organizationId,
1359
- organizationSecret: options.organizationSecret,
1359
+ organizationPublishableKey: options.organizationPublishableKey,
1360
1360
  userToken: options.userToken
1361
1361
  });
1362
1362
  this.onRegistered = options.onRegistered;
@@ -1482,6 +1482,64 @@ var PushNotificationManager = class {
1482
1482
  return null;
1483
1483
  }
1484
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
+ }
1485
1543
  /**
1486
1544
  * Unregister from push notifications
1487
1545
  */
@@ -1595,72 +1653,6 @@ var PushNotificationManager = class {
1595
1653
  return null;
1596
1654
  }
1597
1655
  }
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
- }
1664
1656
  /**
1665
1657
  * Request notification permission
1666
1658
  */
@@ -1755,7 +1747,7 @@ var HeartbeatManager = class {
1755
1747
  this.onTokenExpired = options.onTokenExpired;
1756
1748
  this.authContext = createAuthContext({
1757
1749
  organizationId: options.organizationId,
1758
- organizationSecret: options.organizationSecret,
1750
+ organizationPublishableKey: options.organizationPublishableKey,
1759
1751
  userToken: options.userToken
1760
1752
  });
1761
1753
  this.config = {
@@ -3192,7 +3184,7 @@ var IOSInstallBanner = class {
3192
3184
 
3193
3185
  // src/CloudSignalPWA.ts
3194
3186
  var DEFAULT_SERVICE_URL = "https://pwa.cloudsignal.app";
3195
- var SDK_VERSION = "1.2.3";
3187
+ var SDK_VERSION = "1.2.0";
3196
3188
  var CloudSignalPWA = class {
3197
3189
  constructor(config) {
3198
3190
  this.initialized = false;
@@ -3206,12 +3198,12 @@ var CloudSignalPWA = class {
3206
3198
  this.config = config;
3207
3199
  this.serviceUrl = config.serviceUrl || DEFAULT_SERVICE_URL;
3208
3200
  this.debug = config.debug ?? false;
3209
- if (!config.organizationSecret && !config.userToken) {
3210
- throw new Error("Either organizationSecret or userToken must be provided");
3201
+ if (!config.organizationPublishableKey && !config.userToken) {
3202
+ throw new Error("Either organizationPublishableKey or userToken must be provided");
3211
3203
  }
3212
3204
  this.authContext = createAuthContext({
3213
3205
  organizationId: config.organizationId,
3214
- organizationSecret: config.organizationSecret,
3206
+ organizationPublishableKey: config.organizationPublishableKey,
3215
3207
  userToken: config.userToken
3216
3208
  });
3217
3209
  this.deviceDetector = new DeviceDetector();
@@ -3232,7 +3224,7 @@ var CloudSignalPWA = class {
3232
3224
  this.pushNotificationManager = new PushNotificationManager({
3233
3225
  serviceUrl: this.serviceUrl,
3234
3226
  organizationId: config.organizationId,
3235
- organizationSecret: config.organizationSecret,
3227
+ organizationPublishableKey: config.organizationPublishableKey,
3236
3228
  userToken: config.userToken,
3237
3229
  onTokenExpired: config.onTokenExpired,
3238
3230
  serviceId: config.serviceId,
@@ -3251,7 +3243,7 @@ var CloudSignalPWA = class {
3251
3243
  this.heartbeatManager = new HeartbeatManager({
3252
3244
  serviceUrl: this.serviceUrl,
3253
3245
  organizationId: config.organizationId,
3254
- organizationSecret: config.organizationSecret,
3246
+ organizationPublishableKey: config.organizationPublishableKey,
3255
3247
  userToken: config.userToken,
3256
3248
  onTokenExpired: config.onTokenExpired,
3257
3249
  config: config.heartbeat,
@@ -3340,10 +3332,9 @@ var CloudSignalPWA = class {
3340
3332
  }
3341
3333
  const installState = this.installationManager.getState();
3342
3334
  if (installState.isInstalled) {
3343
- this.log("PWA installation detected, registering...");
3335
+ this.log("PWA installation detected, registering\u2026");
3344
3336
  const installResult = await this.pushNotificationManager.registerInstallation();
3345
3337
  if (installResult) {
3346
- this.log(`Installation registered: ${installResult.registrationId}`);
3347
3338
  this.emit("install:registered", { registrationId: installResult.registrationId });
3348
3339
  }
3349
3340
  }