@tencentcloud/web-push 1.0.2 → 1.0.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.
Files changed (46) hide show
  1. package/README.md +102 -175
  2. package/dist/index.d.ts +259 -0
  3. package/{index.esm.js → dist/index.esm.js} +1118 -158
  4. package/dist/index.umd.js +1 -0
  5. package/dist/src/components/message-popup.d.ts +63 -0
  6. package/{src → dist/src}/core/web-push-sdk.d.ts +23 -1
  7. package/{src → dist/src}/index.d.ts +1 -0
  8. package/{src → dist/src}/types/inner.d.ts +2 -10
  9. package/dist/src/types/outer.d.ts +120 -0
  10. package/{src → dist/src}/utils/logger.d.ts +6 -0
  11. package/{src → dist/src}/utils/validator.d.ts +0 -13
  12. package/dist/sw.js +1 -0
  13. package/package.json +47 -9
  14. package/src/__tests__/index.test.ts +120 -0
  15. package/src/__tests__/integration.test.ts +285 -0
  16. package/src/__tests__/setup.ts +210 -0
  17. package/src/__tests__/types.test.ts +303 -0
  18. package/src/__tests__/web-push-sdk.test.ts +257 -0
  19. package/src/components/message-popup.ts +1007 -0
  20. package/src/core/event-emitter.ts +61 -0
  21. package/src/core/service-worker-manager.ts +614 -0
  22. package/src/core/web-push-sdk.ts +690 -0
  23. package/src/debug/GenerateTestUserSig.js +37 -0
  24. package/src/debug/index.d.ts +6 -0
  25. package/src/debug/index.js +1 -0
  26. package/src/debug/lib-generate-test-usersig-es.min.js +2 -0
  27. package/src/index.ts +9 -0
  28. package/src/service-worker/sw.ts +494 -0
  29. package/src/types/index.ts +2 -0
  30. package/src/types/inner.ts +44 -0
  31. package/src/types/outer.ts +142 -0
  32. package/src/utils/browser-support.ts +412 -0
  33. package/src/utils/logger.ts +66 -0
  34. package/src/utils/storage.ts +51 -0
  35. package/src/utils/validator.ts +267 -0
  36. package/CHANGELOG.md +0 -55
  37. package/index.d.ts +0 -110
  38. package/index.umd.js +0 -1
  39. package/src/types/outer.d.ts +0 -66
  40. package/sw.js +0 -1
  41. /package/{src → dist/src}/core/event-emitter.d.ts +0 -0
  42. /package/{src → dist/src}/core/service-worker-manager.d.ts +0 -0
  43. /package/{src → dist/src}/service-worker/sw.d.ts +0 -0
  44. /package/{src → dist/src}/types/index.d.ts +0 -0
  45. /package/{src → dist/src}/utils/browser-support.d.ts +0 -0
  46. /package/{src → dist/src}/utils/storage.d.ts +0 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Parameter validation utility class
3
+ */
4
+
5
+ export interface ValidationRule {
6
+ required?: boolean;
7
+ type?: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'function';
8
+ min?: number;
9
+ max?: number;
10
+ pattern?: RegExp;
11
+ custom?: (value: any) => boolean | string;
12
+ message?: string;
13
+ }
14
+
15
+ export interface ValidationSchema {
16
+ [key: string]: ValidationRule;
17
+ }
18
+
19
+ export class ValidationError extends Error {
20
+ public field: string;
21
+ public value: any;
22
+
23
+ constructor(field: string, message: string, value?: any) {
24
+ super(`Parameter validation failed: ${field} - ${message}`);
25
+ this.name = 'ValidationError';
26
+ this.field = field;
27
+ this.value = value;
28
+ }
29
+ }
30
+
31
+ export class Validator {
32
+ /**
33
+ * Validate single value
34
+ */
35
+ static validateValue(
36
+ fieldName: string,
37
+ value: any,
38
+ rule: ValidationRule
39
+ ): void {
40
+ if (
41
+ rule.required &&
42
+ (value === undefined || value === null || value === '')
43
+ ) {
44
+ throw new ValidationError(
45
+ fieldName,
46
+ rule.message || `${fieldName} is required`,
47
+ value
48
+ );
49
+ }
50
+
51
+ if (
52
+ !rule.required &&
53
+ (value === undefined || value === null || value === '')
54
+ ) {
55
+ return;
56
+ }
57
+
58
+ if (rule.type && !this.checkType(value, rule.type)) {
59
+ throw new ValidationError(
60
+ fieldName,
61
+ rule.message || `${fieldName} must be of type ${rule.type}`,
62
+ value
63
+ );
64
+ }
65
+
66
+ if (rule.type === 'string' && typeof value === 'string') {
67
+ if (rule.min !== undefined && value.length < rule.min) {
68
+ throw new ValidationError(
69
+ fieldName,
70
+ rule.message ||
71
+ `${fieldName} length cannot be less than ${rule.min} characters`,
72
+ value
73
+ );
74
+ }
75
+ if (rule.max !== undefined && value.length > rule.max) {
76
+ throw new ValidationError(
77
+ fieldName,
78
+ rule.message ||
79
+ `${fieldName} length cannot exceed ${rule.max} characters`,
80
+ value
81
+ );
82
+ }
83
+ }
84
+
85
+ if (rule.type === 'number' && typeof value === 'number') {
86
+ if (rule.min !== undefined && value < rule.min) {
87
+ throw new ValidationError(
88
+ fieldName,
89
+ rule.message || `${fieldName} cannot be less than ${rule.min}`,
90
+ value
91
+ );
92
+ }
93
+ if (rule.max !== undefined && value > rule.max) {
94
+ throw new ValidationError(
95
+ fieldName,
96
+ rule.message || `${fieldName} cannot be greater than ${rule.max}`,
97
+ value
98
+ );
99
+ }
100
+ }
101
+
102
+ if (rule.pattern && typeof value === 'string') {
103
+ if (!rule.pattern.test(value)) {
104
+ throw new ValidationError(
105
+ fieldName,
106
+ rule.message || `${fieldName} format is incorrect`,
107
+ value
108
+ );
109
+ }
110
+ }
111
+
112
+ if (rule.custom) {
113
+ const result = rule.custom(value);
114
+ if (result !== true) {
115
+ const message =
116
+ typeof result === 'string'
117
+ ? result
118
+ : rule.message || `${fieldName} validation failed`;
119
+ throw new ValidationError(fieldName, message, value);
120
+ }
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Validate object
126
+ */
127
+ static validateObject(obj: any, schema: ValidationSchema): void {
128
+ if (!obj || typeof obj !== 'object') {
129
+ throw new ValidationError('root', 'Parameter must be an object type');
130
+ }
131
+
132
+ for (const [fieldName, rule] of Object.entries(schema)) {
133
+ const value = obj[fieldName];
134
+ this.validateValue(fieldName, value, rule);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Check type
140
+ */
141
+ private static checkType(value: any, expectedType: string): boolean {
142
+ switch (expectedType) {
143
+ case 'string':
144
+ return typeof value === 'string';
145
+ case 'number':
146
+ return typeof value === 'number' && !isNaN(value);
147
+ case 'boolean':
148
+ return typeof value === 'boolean';
149
+ case 'object':
150
+ return (
151
+ value !== null && typeof value === 'object' && !Array.isArray(value)
152
+ );
153
+ case 'array':
154
+ return Array.isArray(value);
155
+ case 'function':
156
+ return typeof value === 'function';
157
+ default:
158
+ return false;
159
+ }
160
+ }
161
+
162
+ static validateSDKAppID(SDKAppID: any): void {
163
+ this.validateValue('SDKAppID', SDKAppID, {
164
+ required: true,
165
+ type: 'number',
166
+ custom: (value) => {
167
+ if (!Number.isInteger(value)) {
168
+ return 'SDKAppID must be an integer';
169
+ }
170
+ return true;
171
+ },
172
+ message: 'SDKAppID must be an integer between 1-999999999',
173
+ });
174
+ }
175
+
176
+ static validateAppKey(appKey: any): void {
177
+ this.validateValue('appKey', appKey, {
178
+ required: true,
179
+ type: 'string',
180
+ pattern: /^[a-zA-Z0-9_-]+$/,
181
+ message:
182
+ 'appKey must be a 1-256 character string composed of letters, numbers, underscores or hyphens',
183
+ });
184
+ }
185
+
186
+ static validateUserID(userID: any): void {
187
+ this.validateValue('userID', userID, {
188
+ required: true,
189
+ type: 'string',
190
+ pattern: /^[a-zA-Z0-9_.-]+$/,
191
+ message:
192
+ 'userID must be a 1-128 character string composed of letters, numbers, underscores, dots or hyphens',
193
+ });
194
+ }
195
+
196
+ static validateEventType(eventType: any): void {
197
+ const validEvents = [
198
+ 'message_received',
199
+ 'message_revoked',
200
+ 'notification_clicked',
201
+ ];
202
+ this.validateValue('eventType', eventType, {
203
+ required: true,
204
+ type: 'string',
205
+ custom: (value) => {
206
+ if (!validEvents.includes(value)) {
207
+ return `eventType must be one of: ${validEvents.join(', ')}`;
208
+ }
209
+ return true;
210
+ },
211
+ });
212
+ }
213
+
214
+ static validateListener(listener: any): void {
215
+ this.validateValue('listener', listener, {
216
+ required: true,
217
+ type: 'function',
218
+ message: 'listener must be a function',
219
+ });
220
+ }
221
+
222
+ static validateRegisterPushOptions(options: any): void {
223
+ if (!options) {
224
+ throw new ValidationError(
225
+ 'options',
226
+ 'Registration options cannot be empty'
227
+ );
228
+ }
229
+
230
+ const schema: ValidationSchema = {
231
+ SDKAppID: {
232
+ required: true,
233
+ type: 'number',
234
+ custom: (value) => {
235
+ if (!Number.isInteger(value)) {
236
+ return 'SDKAppID must be an integer';
237
+ }
238
+ return true;
239
+ },
240
+ },
241
+ appKey: {
242
+ required: true,
243
+ type: 'string',
244
+ pattern: /^[a-zA-Z0-9_-]+$/,
245
+ },
246
+ userID: {
247
+ required: true,
248
+ type: 'string',
249
+ pattern: /^[a-zA-Z0-9_.-]+$/,
250
+ },
251
+ };
252
+
253
+ this.validateObject(options, schema);
254
+ }
255
+
256
+ /**
257
+ * Validate Service Worker path
258
+ */
259
+ static validateServiceWorkerPath(path: any): void {
260
+ this.validateValue('serviceWorkerPath', path, {
261
+ required: false,
262
+ type: 'string',
263
+ pattern: /^[a-zA-Z0-9_./-]+\.js$/,
264
+ message: 'serviceWorkerPath must be a valid JavaScript file path',
265
+ });
266
+ }
267
+ }
package/CHANGELOG.md DELETED
@@ -1,55 +0,0 @@
1
- # Changelog
2
-
3
- ## [1.0.2] - 2025-01-16
4
-
5
- - ✨ Added UMD build support for direct `<script>` tag integration
6
- - 📚 Enhanced UMD usage documentation and examples
7
-
8
- ## [1.0.1] - 2025-12-19
9
-
10
- - Optimize subscription logic
11
- - Optimized state persistence logic, only persisting VAPID public key while resetting temporary states each session
12
-
13
- ## [1.0.0] - 2025-12-17
14
-
15
- ### Added
16
-
17
- - 🎉 Initial release
18
- - ✨ Service Worker-based push notification support
19
- - ✨ Complete TypeScript type definitions
20
- - ✨ Event-driven message handling mechanism
21
- - ✨ Built-in analytics functionality
22
- - ✨ Local state persistence
23
- - ✨ VAPID authentication support
24
- - ✨ Cross-platform push notification support
25
-
26
- ### Features
27
-
28
- - 📱 Support for message received, notification clicked, and message revoked events
29
- - 🔧 Flexible device identifier management
30
- - 📊 Automatic message delivery and click rate statistics
31
- - 🎯 Seamless integration with Chat SDK
32
- - 💾 Automatic state recovery
33
- - 🔒 Secure push subscription management
34
-
35
- ### API Interface
36
-
37
- - `registerPush()` - Register push service
38
- - `unRegisterPush()` - Unregister push service
39
- - `addPushListener()` - Add event listener
40
- - `removePushListener()` - Remove event listener
41
-
42
- ### Browser Support
43
-
44
- - Chrome 50+
45
- - Firefox 44+
46
- - Safari 16+
47
- - Edge 17+
48
-
49
- ### Development Tools
50
-
51
- - Vite build tool
52
- - TypeScript support
53
- - Jest unit testing
54
- - ESLint code linting
55
- - Complete example application
package/index.d.ts DELETED
@@ -1,110 +0,0 @@
1
- export declare enum EVENT {
2
- MESSAGE_RECEIVED = "message_received",
3
- MESSAGE_REVOKED = "message_revoked",
4
- NOTIFICATION_CLICKED = "notification_clicked"
5
- }
6
-
7
- export declare interface EventResult {
8
- data: MessageReceivedResult | MessageRevokedResult | MessageNotificationClickedResult;
9
- }
10
-
11
- export declare interface Message {
12
- ID: String;
13
- type: 'TIMTextElem' | 'TIMImageElem' | 'TIMSoundElem' | 'TIMVideoFileElem' | 'TIMFileElem' | 'TIMCustomElem' | 'TIMRelayElem' | 'TIMLocationElem' | 'TIMFaceElem';
14
- payload: any;
15
- conversationID: String;
16
- conversationType: 'C2C' | 'GROUP';
17
- to: String;
18
- from: String;
19
- flow: String;
20
- time: Number;
21
- status: String;
22
- isRevoked: Boolean;
23
- nick: String;
24
- avatar: String;
25
- isPeerRead: Boolean;
26
- nameCard: String;
27
- atUserList: String[];
28
- cloudCustomData: String;
29
- isDeleted: Boolean;
30
- isModified: Boolean;
31
- needReadReceipt: Boolean;
32
- readReceiptInfo: any;
33
- isBroadcastMessage: Boolean;
34
- isSupportExtension: Boolean;
35
- receiverList?: String[];
36
- revoker: String;
37
- sequence: Number;
38
- progress: Number;
39
- revokerInfo: {
40
- userID: String;
41
- nick: String;
42
- avatar: String;
43
- };
44
- revokeReason: String;
45
- hasRiskContent: Boolean;
46
- }
47
-
48
- export declare interface MessageNotificationClickedResult {
49
- ext: String;
50
- }
51
-
52
- export declare interface MessageReceivedResult {
53
- message: Message;
54
- }
55
-
56
- export declare interface MessageRevokedResult {
57
- messageID: String;
58
- }
59
-
60
- export declare interface RegisterPushOptions {
61
- SDKAppID: number;
62
- appKey: string;
63
- userID: string;
64
- serviceWorkerPath?: string;
65
- chat?: any;
66
- }
67
-
68
- declare const webPush: WebPushSDK_2;
69
- export default webPush;
70
- export { webPush }
71
-
72
- export declare interface WebPushSDK {
73
- registerPush(options?: RegisterPushOptions): Promise<any>;
74
- unRegisterPush(): Promise<any>;
75
- addPushListener(eventName: EVENT, listener: (data: EventResult) => void): any;
76
- removePushListener(eventName: EVENT, listener: (data: EventResult) => void): any;
77
- }
78
-
79
- declare class WebPushSDK_2 implements WebPushSDK {
80
- static instance: WebPushSDK_2;
81
- private eventEmitter;
82
- private serviceWorkerManager;
83
- private isRegistered;
84
- private registrationID;
85
- private chat;
86
- private SDKAppID;
87
- private appKey;
88
- private vapidPublicKey;
89
- EVENT: typeof EVENT;
90
- VERSION: string;
91
- constructor();
92
- static getInstance(): WebPushSDK_2;
93
- registerPush(options?: RegisterPushOptions): Promise<string>;
94
- unRegisterPush(): Promise<boolean>;
95
- addPushListener(eventName: EVENT, listener: Function): string;
96
- removePushListener(eventName: EVENT, listener: Function): boolean;
97
- private checkBrowserSupport;
98
- private requestNotificationPermission;
99
- private chatLogin;
100
- private getSystemPermissionMessage;
101
- private showSystemPermissionAlert;
102
- private getBrowserInstType;
103
- private setToken;
104
- private initializeBrowserCompatibility;
105
- private setupInternalListeners;
106
- private pushStatistics;
107
- private clearState;
108
- }
109
-
110
- export { }