@markwharton/pwa-push 1.5.3 → 2.0.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.
Files changed (40) hide show
  1. package/dist/client.d.ts +181 -0
  2. package/dist/client.js +412 -0
  3. package/dist/index.d.ts +9 -0
  4. package/dist/index.js +9 -0
  5. package/dist/pwa-push-sw.js +61 -39
  6. package/dist/{server/send.d.ts → server.d.ts} +6 -2
  7. package/dist/{server/send.js → server.js} +9 -7
  8. package/dist/shared.d.ts +22 -2
  9. package/dist/shared.js +9 -6
  10. package/dist/sw.d.ts +1 -1
  11. package/dist/sw.js +2 -2
  12. package/package.json +11 -8
  13. package/dist/__tests__/client/deviceId.test.d.ts +0 -1
  14. package/dist/__tests__/client/deviceId.test.js +0 -134
  15. package/dist/__tests__/client/encoding.test.d.ts +0 -1
  16. package/dist/__tests__/client/encoding.test.js +0 -89
  17. package/dist/__tests__/client/indexedDb.test.d.ts +0 -1
  18. package/dist/__tests__/client/indexedDb.test.js +0 -195
  19. package/dist/__tests__/client/renewal.test.d.ts +0 -1
  20. package/dist/__tests__/client/renewal.test.js +0 -170
  21. package/dist/__tests__/client/subscribe.test.d.ts +0 -1
  22. package/dist/__tests__/client/subscribe.test.js +0 -299
  23. package/dist/__tests__/server/send.test.d.ts +0 -1
  24. package/dist/__tests__/server/send.test.js +0 -226
  25. package/dist/client/deviceId.d.ts +0 -23
  26. package/dist/client/deviceId.js +0 -49
  27. package/dist/client/encoding.d.ts +0 -17
  28. package/dist/client/encoding.js +0 -32
  29. package/dist/client/index.d.ts +0 -4
  30. package/dist/client/index.js +0 -20
  31. package/dist/client/indexedDb.d.ts +0 -38
  32. package/dist/client/indexedDb.js +0 -89
  33. package/dist/client/renewal.d.ts +0 -31
  34. package/dist/client/renewal.js +0 -80
  35. package/dist/client/subscribe.d.ts +0 -88
  36. package/dist/client/subscribe.js +0 -176
  37. package/dist/server/index.d.ts +0 -1
  38. package/dist/server/index.js +0 -11
  39. package/dist/types.d.ts +0 -39
  40. package/dist/types.js +0 -11
@@ -31,23 +31,55 @@ var PwaPush = (() => {
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
- // ../core/dist/types.js
35
- var require_types = __commonJS({
36
- "../core/dist/types.js"(exports) {
34
+ // ../core/dist/shared.js
35
+ var require_shared = __commonJS({
36
+ "../core/dist/shared.js"(exports) {
37
37
  "use strict";
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.HTTP_STATUS = void 0;
39
40
  exports.ok = ok2;
40
- exports.okVoid = okVoid3;
41
- exports.err = err3;
41
+ exports.okVoid = okVoid2;
42
+ exports.err = err2;
43
+ exports.hasUsername = hasUsername;
44
+ exports.hasRole = hasRole;
45
+ exports.isAdmin = isAdmin;
46
+ exports.getErrorMessage = getErrorMessage2;
42
47
  function ok2(data) {
43
48
  return { ok: true, data };
44
49
  }
45
- function okVoid3() {
50
+ function okVoid2() {
46
51
  return { ok: true };
47
52
  }
48
- function err3(error, statusCode) {
53
+ function err2(error, statusCode) {
49
54
  return statusCode !== void 0 ? { ok: false, error, statusCode } : { ok: false, error };
50
55
  }
56
+ function hasUsername(payload) {
57
+ return "username" in payload && typeof payload.username === "string";
58
+ }
59
+ function hasRole(payload) {
60
+ return "role" in payload;
61
+ }
62
+ function isAdmin(payload) {
63
+ return hasRole(payload) && payload.role === "admin";
64
+ }
65
+ exports.HTTP_STATUS = {
66
+ OK: 200,
67
+ CREATED: 201,
68
+ NO_CONTENT: 204,
69
+ BAD_REQUEST: 400,
70
+ UNAUTHORIZED: 401,
71
+ FORBIDDEN: 403,
72
+ NOT_FOUND: 404,
73
+ CONFLICT: 409,
74
+ GONE: 410,
75
+ UNPROCESSABLE_ENTITY: 422,
76
+ TOO_MANY_REQUESTS: 429,
77
+ INTERNAL_ERROR: 500,
78
+ SERVICE_UNAVAILABLE: 503
79
+ };
80
+ function getErrorMessage2(error, fallback) {
81
+ return error instanceof Error ? error.message : fallback;
82
+ }
51
83
  }
52
84
  });
53
85
 
@@ -57,10 +89,8 @@ var PwaPush = (() => {
57
89
  handleSubscriptionChange: () => handleSubscriptionChange
58
90
  });
59
91
 
60
- // src/client/renewal.ts
61
- var import_types2 = __toESM(require_types());
62
-
63
- // src/client/encoding.ts
92
+ // src/client.ts
93
+ var import_shared = __toESM(require_shared());
64
94
  function urlBase64ToUint8Array(base64String) {
65
95
  const padding = "=".repeat((4 - base64String.length % 4) % 4);
66
96
  const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
@@ -72,8 +102,6 @@ var PwaPush = (() => {
72
102
  }
73
103
  return outputArray;
74
104
  }
75
-
76
- // src/client/indexedDb.ts
77
105
  var DB_NAME = "PushSubscriptionDB";
78
106
  var STORE_NAME = "subscriptionData";
79
107
  var DATA_KEY = "current";
@@ -108,9 +136,6 @@ var PwaPush = (() => {
108
136
  );
109
137
  return result || null;
110
138
  }
111
-
112
- // src/client/subscribe.ts
113
- var import_types = __toESM(require_types());
114
139
  function toPushSubscription(browserSub) {
115
140
  const json = browserSub.toJSON();
116
141
  return {
@@ -121,17 +146,30 @@ var PwaPush = (() => {
121
146
  }
122
147
  };
123
148
  }
124
-
125
- // src/client/renewal.ts
149
+ async function resubscribe(data) {
150
+ try {
151
+ const self = globalThis;
152
+ const registration = self.registration;
153
+ const applicationServerKey = urlBase64ToUint8Array(data.publicKey);
154
+ const subscription = await registration.pushManager.subscribe({
155
+ userVisibleOnly: true,
156
+ applicationServerKey
157
+ });
158
+ return toPushSubscription(subscription);
159
+ } catch (error) {
160
+ console.error("Resubscribe failed:", error);
161
+ return null;
162
+ }
163
+ }
126
164
  async function handleSubscriptionChange(event, renewEndpoint) {
127
165
  try {
128
166
  const data = await getSubscriptionData();
129
167
  if (!data) {
130
- return (0, import_types2.err)("No subscription data found for renewal");
168
+ return (0, import_shared.err)("No subscription data found for renewal");
131
169
  }
132
170
  const newSubscription = await resubscribe(data);
133
171
  if (!newSubscription) {
134
- return (0, import_types2.err)("Failed to create new subscription");
172
+ return (0, import_shared.err)("Failed to create new subscription");
135
173
  }
136
174
  const renewalRequest = {
137
175
  subscription: newSubscription,
@@ -144,27 +182,11 @@ var PwaPush = (() => {
144
182
  body: JSON.stringify(renewalRequest)
145
183
  });
146
184
  if (!response.ok) {
147
- return (0, import_types2.err)(`Renewal request failed: ${response.status}`);
185
+ return (0, import_shared.err)(`Renewal request failed: ${response.status}`);
148
186
  }
149
- return (0, import_types2.okVoid)();
187
+ return (0, import_shared.okVoid)();
150
188
  } catch (error) {
151
- const message = error instanceof Error ? error.message : "Subscription renewal failed";
152
- return (0, import_types2.err)(message);
153
- }
154
- }
155
- async function resubscribe(data) {
156
- try {
157
- const self = globalThis;
158
- const registration = self.registration;
159
- const applicationServerKey = urlBase64ToUint8Array(data.publicKey);
160
- const subscription = await registration.pushManager.subscribe({
161
- userVisibleOnly: true,
162
- applicationServerKey
163
- });
164
- return toPushSubscription(subscription);
165
- } catch (error) {
166
- console.error("Resubscribe failed:", error);
167
- return null;
189
+ return (0, import_shared.err)((0, import_shared.getErrorMessage)(error, "Subscription renewal failed"));
168
190
  }
169
191
  }
170
192
  return __toCommonJS(sw_exports);
@@ -1,5 +1,9 @@
1
- import { Result } from '@markwharton/pwa-core/types';
2
- import { PushSubscription, NotificationPayload } from '../shared';
1
+ /**
2
+ * pwa-push/server - Server-side Web Push notification utilities
3
+ *
4
+ * Requires: web-push package
5
+ */
6
+ import { Result, PushSubscription, NotificationPayload } from './shared';
3
7
  /**
4
8
  * Initializes VAPID configuration for Web Push. Call once at application startup.
5
9
  * @param config - VAPID configuration
@@ -1,4 +1,9 @@
1
1
  "use strict";
2
+ /**
3
+ * pwa-push/server - Server-side Web Push notification utilities
4
+ *
5
+ * Requires: web-push package
6
+ */
2
7
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
8
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
9
  };
@@ -11,10 +16,7 @@ exports.sendPushToAll = sendPushToAll;
11
16
  exports.sendPushWithDetails = sendPushWithDetails;
12
17
  exports.isSubscriptionExpired = isSubscriptionExpired;
13
18
  const web_push_1 = __importDefault(require("web-push"));
14
- const types_1 = require("@markwharton/pwa-core/types");
15
- /**
16
- * Server-side Web Push notification utilities
17
- */
19
+ const shared_1 = require("./shared");
18
20
  let vapidConfig = null;
19
21
  /**
20
22
  * Initializes VAPID configuration for Web Push. Call once at application startup.
@@ -112,7 +114,7 @@ async function sendPushToAll(subscriptions, payload) {
112
114
  */
113
115
  async function sendPushWithDetails(subscription, payload) {
114
116
  if (!vapidConfig) {
115
- return (0, types_1.err)('Push not initialized');
117
+ return (0, shared_1.err)('Push not initialized');
116
118
  }
117
119
  // Auto-inject basePath from subscription if not set in payload
118
120
  const payloadWithBasePath = {
@@ -121,11 +123,11 @@ async function sendPushWithDetails(subscription, payload) {
121
123
  };
122
124
  try {
123
125
  await web_push_1.default.sendNotification(subscription, JSON.stringify(payloadWithBasePath));
124
- return (0, types_1.okVoid)();
126
+ return (0, shared_1.okVoid)();
125
127
  }
126
128
  catch (error) {
127
129
  const webPushError = error;
128
- return (0, types_1.err)(webPushError.message || 'Unknown error', webPushError.statusCode);
130
+ return (0, shared_1.err)(webPushError.message || 'Unknown error', webPushError.statusCode);
129
131
  }
130
132
  }
131
133
  /**
package/dist/shared.d.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  /**
2
- * Push notification types - shared between server and client
2
+ * pwa-push/shared - Push notification types shared between server and client
3
+ *
4
+ * This module has NO Node.js dependencies and can be safely imported in browsers.
5
+ */
6
+ export { Result, ok, okVoid, err, getErrorMessage } from '@markwharton/pwa-core/shared';
7
+ /**
8
+ * Browser push subscription for backend storage.
3
9
  */
4
- export { Result, ok, okVoid, err } from '@markwharton/pwa-core/types';
5
10
  export interface PushSubscription {
6
11
  endpoint: string;
7
12
  keys: {
@@ -10,6 +15,9 @@ export interface PushSubscription {
10
15
  };
11
16
  basePath?: string;
12
17
  }
18
+ /**
19
+ * Notification payload for push messages.
20
+ */
13
21
  export interface NotificationPayload {
14
22
  title: string;
15
23
  body: string;
@@ -21,19 +29,31 @@ export interface NotificationPayload {
21
29
  timestamp?: string;
22
30
  basePath?: string;
23
31
  }
32
+ /**
33
+ * VAPID configuration for web push.
34
+ */
24
35
  export interface VapidConfig {
25
36
  publicKey: string;
26
37
  privateKey: string;
27
38
  subject: string;
28
39
  }
40
+ /**
41
+ * Subscription request sent to backend.
42
+ */
29
43
  export interface SubscriptionRequest {
30
44
  subscription: PushSubscription;
31
45
  deviceId: string;
32
46
  basePath?: string;
33
47
  }
48
+ /**
49
+ * Data stored in IndexedDB for service worker renewal.
50
+ */
34
51
  export interface SubscriptionData {
35
52
  publicKey: string;
36
53
  deviceId: string;
37
54
  basePath: string;
38
55
  }
56
+ /**
57
+ * Browser notification permission state.
58
+ */
39
59
  export type PushPermissionState = 'granted' | 'denied' | 'default';
package/dist/shared.js CHANGED
@@ -1,11 +1,14 @@
1
1
  "use strict";
2
2
  /**
3
- * Push notification types - shared between server and client
3
+ * pwa-push/shared - Push notification types shared between server and client
4
+ *
5
+ * This module has NO Node.js dependencies and can be safely imported in browsers.
4
6
  */
5
7
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.err = exports.okVoid = exports.ok = void 0;
8
+ exports.getErrorMessage = exports.err = exports.okVoid = exports.ok = void 0;
7
9
  // Re-export Result from pwa-core for convenience
8
- var types_1 = require("@markwharton/pwa-core/types");
9
- Object.defineProperty(exports, "ok", { enumerable: true, get: function () { return types_1.ok; } });
10
- Object.defineProperty(exports, "okVoid", { enumerable: true, get: function () { return types_1.okVoid; } });
11
- Object.defineProperty(exports, "err", { enumerable: true, get: function () { return types_1.err; } });
10
+ var shared_1 = require("@markwharton/pwa-core/shared");
11
+ Object.defineProperty(exports, "ok", { enumerable: true, get: function () { return shared_1.ok; } });
12
+ Object.defineProperty(exports, "okVoid", { enumerable: true, get: function () { return shared_1.okVoid; } });
13
+ Object.defineProperty(exports, "err", { enumerable: true, get: function () { return shared_1.err; } });
14
+ Object.defineProperty(exports, "getErrorMessage", { enumerable: true, get: function () { return shared_1.getErrorMessage; } });
package/dist/sw.d.ts CHANGED
@@ -11,4 +11,4 @@
11
11
  * });
12
12
  * ```
13
13
  */
14
- export { handleSubscriptionChange } from './client/renewal';
14
+ export { handleSubscriptionChange } from './client';
package/dist/sw.js CHANGED
@@ -14,5 +14,5 @@
14
14
  */
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.handleSubscriptionChange = void 0;
17
- var renewal_1 = require("./client/renewal");
18
- Object.defineProperty(exports, "handleSubscriptionChange", { enumerable: true, get: function () { return renewal_1.handleSubscriptionChange; } });
17
+ var client_1 = require("./client");
18
+ Object.defineProperty(exports, "handleSubscriptionChange", { enumerable: true, get: function () { return client_1.handleSubscriptionChange; } });
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@markwharton/pwa-push",
3
- "version": "1.5.3",
3
+ "version": "2.0.0",
4
4
  "description": "Web push notifications for Azure PWA projects",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
8
8
  ".": "./dist/index.js",
9
- "./server": "./dist/server/index.js",
10
- "./client": "./dist/client/index.js",
9
+ "./server": "./dist/server.js",
10
+ "./client": "./dist/client.js",
11
11
  "./shared": "./dist/shared.js",
12
12
  "./sw": "./dist/pwa-push-sw.js"
13
13
  },
14
14
  "typesVersions": {
15
15
  "*": {
16
16
  "server": [
17
- "dist/server/index.d.ts"
17
+ "dist/server.d.ts"
18
18
  ],
19
19
  "client": [
20
- "dist/client/index.d.ts"
20
+ "dist/client.d.ts"
21
21
  ],
22
22
  "shared": [
23
23
  "dist/shared.d.ts"
@@ -30,11 +30,11 @@
30
30
  "clean": "rm -rf dist"
31
31
  },
32
32
  "peerDependencies": {
33
- "@markwharton/pwa-core": "^1.8.0",
33
+ "@markwharton/pwa-core": "^2.0.0",
34
34
  "web-push": "^3.6.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@markwharton/pwa-core": "^1.8.0",
37
+ "@markwharton/pwa-core": "^2.0.0",
38
38
  "@types/node": "^20.10.0",
39
39
  "@types/web-push": "^3.6.4",
40
40
  "esbuild": "^0.27.2",
@@ -50,5 +50,8 @@
50
50
  "directory": "packages/push"
51
51
  },
52
52
  "author": "Mark Wharton",
53
- "license": "MIT"
53
+ "license": "MIT",
54
+ "engines": {
55
+ "node": ">=20"
56
+ }
54
57
  }
@@ -1 +0,0 @@
1
- export {};
@@ -1,134 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- const vitest_1 = require("vitest");
37
- // Storage for mock
38
- let mockStore = {};
39
- // Mock localStorage
40
- const localStorageMock = {
41
- getItem: vitest_1.vi.fn((key) => mockStore[key] || null),
42
- setItem: vitest_1.vi.fn((key, value) => { mockStore[key] = value; }),
43
- removeItem: vitest_1.vi.fn((key) => { delete mockStore[key]; }),
44
- clear: vitest_1.vi.fn(() => { mockStore = {}; })
45
- };
46
- // Mock crypto.getRandomValues
47
- const mockGetRandomValues = vitest_1.vi.fn((array) => {
48
- for (let i = 0; i < array.length; i++) {
49
- array[i] = Math.floor(Math.random() * 256);
50
- }
51
- return array;
52
- });
53
- // Helper to setup global mocks (needed after vi.resetModules)
54
- function setupGlobalMocks() {
55
- Object.defineProperty(global, 'localStorage', {
56
- value: localStorageMock,
57
- writable: true,
58
- configurable: true
59
- });
60
- Object.defineProperty(global, 'crypto', {
61
- value: { getRandomValues: mockGetRandomValues },
62
- writable: true,
63
- configurable: true
64
- });
65
- }
66
- (0, vitest_1.beforeEach)(() => {
67
- vitest_1.vi.resetModules();
68
- mockStore = {};
69
- localStorageMock.getItem.mockClear();
70
- localStorageMock.setItem.mockClear();
71
- localStorageMock.removeItem.mockClear();
72
- setupGlobalMocks();
73
- });
74
- (0, vitest_1.describe)('Device ID utilities', () => {
75
- (0, vitest_1.describe)('getDeviceId', () => {
76
- (0, vitest_1.it)('returns existing deviceId from localStorage', async () => {
77
- mockStore['push_device_id'] = 'existing-uuid';
78
- const { getDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
79
- const result = getDeviceId();
80
- (0, vitest_1.expect)(result).toBe('existing-uuid');
81
- });
82
- (0, vitest_1.it)('generates new UUID if not in localStorage', async () => {
83
- const { getDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
84
- const result = getDeviceId();
85
- (0, vitest_1.expect)(result).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
86
- });
87
- (0, vitest_1.it)('saves generated UUID to localStorage', async () => {
88
- const { getDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
89
- const result = getDeviceId();
90
- (0, vitest_1.expect)(localStorageMock.setItem).toHaveBeenCalledWith('push_device_id', result);
91
- });
92
- (0, vitest_1.it)('returns same ID on repeated calls', async () => {
93
- const { getDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
94
- const id1 = getDeviceId();
95
- const id2 = getDeviceId();
96
- (0, vitest_1.expect)(id1).toBe(id2);
97
- });
98
- });
99
- (0, vitest_1.describe)('clearDeviceId', () => {
100
- (0, vitest_1.it)('removes deviceId from localStorage', async () => {
101
- mockStore['push_device_id'] = 'test-uuid';
102
- const { clearDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
103
- clearDeviceId();
104
- (0, vitest_1.expect)(localStorageMock.removeItem).toHaveBeenCalledWith('push_device_id');
105
- });
106
- (0, vitest_1.it)('allows new ID generation after clear', async () => {
107
- const { getDeviceId, clearDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
108
- getDeviceId();
109
- clearDeviceId();
110
- // Verify removeItem was called
111
- (0, vitest_1.expect)(localStorageMock.removeItem).toHaveBeenCalledWith('push_device_id');
112
- });
113
- });
114
- (0, vitest_1.describe)('UUID format', () => {
115
- (0, vitest_1.it)('generates valid UUID v4 format', async () => {
116
- const { getDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
117
- const uuid = getDeviceId();
118
- // UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
119
- // where y is 8, 9, a, or b
120
- (0, vitest_1.expect)(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
121
- });
122
- (0, vitest_1.it)('generates unique UUIDs across module resets', async () => {
123
- const uuids = new Set();
124
- for (let i = 0; i < 10; i++) {
125
- vitest_1.vi.resetModules();
126
- mockStore = {};
127
- setupGlobalMocks();
128
- const { getDeviceId } = await Promise.resolve().then(() => __importStar(require('../../client/deviceId')));
129
- uuids.add(getDeviceId());
130
- }
131
- (0, vitest_1.expect)(uuids.size).toBe(10);
132
- });
133
- });
134
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,89 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- const vitest_1 = require("vitest");
37
- // Mock atob for Node.js environment
38
- (0, vitest_1.beforeEach)(() => {
39
- global.atob = (str) => Buffer.from(str, 'base64').toString('binary');
40
- });
41
- (0, vitest_1.describe)('urlBase64ToUint8Array', () => {
42
- (0, vitest_1.it)('converts standard base64 to Uint8Array', async () => {
43
- const { urlBase64ToUint8Array } = await Promise.resolve().then(() => __importStar(require('../../client/encoding')));
44
- const base64 = 'SGVsbG8gV29ybGQ='; // "Hello World"
45
- const result = urlBase64ToUint8Array(base64);
46
- (0, vitest_1.expect)(result).toBeInstanceOf(Uint8Array);
47
- const decoded = new TextDecoder().decode(result);
48
- (0, vitest_1.expect)(decoded).toBe('Hello World');
49
- });
50
- (0, vitest_1.it)('handles URL-safe base64 characters', async () => {
51
- const { urlBase64ToUint8Array } = await Promise.resolve().then(() => __importStar(require('../../client/encoding')));
52
- // URL-safe base64 uses - instead of + and _ instead of /
53
- const urlSafeBase64 = 'SGVsbG8-V29ybGRf'; // Contains - and _
54
- const result = urlBase64ToUint8Array(urlSafeBase64);
55
- (0, vitest_1.expect)(result).toBeInstanceOf(Uint8Array);
56
- (0, vitest_1.expect)(result.length).toBeGreaterThan(0);
57
- });
58
- (0, vitest_1.it)('adds padding when needed', async () => {
59
- const { urlBase64ToUint8Array } = await Promise.resolve().then(() => __importStar(require('../../client/encoding')));
60
- // Base64 without padding (should be 'ab==' with padding)
61
- const noPadding = 'YWI';
62
- const result = urlBase64ToUint8Array(noPadding);
63
- (0, vitest_1.expect)(result).toBeInstanceOf(Uint8Array);
64
- const decoded = new TextDecoder().decode(result);
65
- (0, vitest_1.expect)(decoded).toBe('ab');
66
- });
67
- (0, vitest_1.it)('works with VAPID-like keys', async () => {
68
- const { urlBase64ToUint8Array } = await Promise.resolve().then(() => __importStar(require('../../client/encoding')));
69
- // Typical VAPID public key format (65 bytes)
70
- const vapidKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
71
- const result = urlBase64ToUint8Array(vapidKey);
72
- (0, vitest_1.expect)(result).toBeInstanceOf(Uint8Array);
73
- (0, vitest_1.expect)(result.length).toBe(65); // VAPID public keys are 65 bytes
74
- });
75
- (0, vitest_1.it)('returns correct byte values', async () => {
76
- const { urlBase64ToUint8Array } = await Promise.resolve().then(() => __importStar(require('../../client/encoding')));
77
- // 'AQID' decodes to bytes [1, 2, 3]
78
- const result = urlBase64ToUint8Array('AQID');
79
- (0, vitest_1.expect)(result[0]).toBe(1);
80
- (0, vitest_1.expect)(result[1]).toBe(2);
81
- (0, vitest_1.expect)(result[2]).toBe(3);
82
- });
83
- (0, vitest_1.it)('handles empty string', async () => {
84
- const { urlBase64ToUint8Array } = await Promise.resolve().then(() => __importStar(require('../../client/encoding')));
85
- const result = urlBase64ToUint8Array('');
86
- (0, vitest_1.expect)(result).toBeInstanceOf(Uint8Array);
87
- (0, vitest_1.expect)(result.length).toBe(0);
88
- });
89
- });
@@ -1 +0,0 @@
1
- export {};