@tencentcloud/web-push 1.0.1 → 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 (47) hide show
  1. package/README.md +149 -136
  2. package/dist/index.d.ts +259 -0
  3. package/dist/index.esm.js +6857 -0
  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 -50
  37. package/index.d.ts +0 -110
  38. package/index.esm.js +0 -21437
  39. package/index.umd.js +0 -1
  40. package/src/types/outer.d.ts +0 -66
  41. package/sw.js +0 -1
  42. /package/{src → dist/src}/core/event-emitter.d.ts +0 -0
  43. /package/{src → dist/src}/core/service-worker-manager.d.ts +0 -0
  44. /package/{src → dist/src}/service-worker/sw.d.ts +0 -0
  45. /package/{src → dist/src}/types/index.d.ts +0 -0
  46. /package/{src → dist/src}/utils/browser-support.d.ts +0 -0
  47. /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,50 +0,0 @@
1
- # Changelog
2
-
3
- ## [1.0.1] - 2025-12-19
4
-
5
- - Optimize subscription logic
6
- - Optimized state persistence logic, only persisting VAPID public key while resetting temporary states each session
7
-
8
- ## [1.0.0] - 2025-12-17
9
-
10
- ### Added
11
-
12
- - 🎉 Initial release
13
- - ✨ Service Worker-based push notification support
14
- - ✨ Complete TypeScript type definitions
15
- - ✨ Event-driven message handling mechanism
16
- - ✨ Built-in analytics functionality
17
- - ✨ Local state persistence
18
- - ✨ VAPID authentication support
19
- - ✨ Cross-platform push notification support
20
-
21
- ### Features
22
-
23
- - 📱 Support for message received, notification clicked, and message revoked events
24
- - 🔧 Flexible device identifier management
25
- - 📊 Automatic message delivery and click rate statistics
26
- - 🎯 Seamless integration with Chat SDK
27
- - 💾 Automatic state recovery
28
- - 🔒 Secure push subscription management
29
-
30
- ### API Interface
31
-
32
- - `registerPush()` - Register push service
33
- - `unRegisterPush()` - Unregister push service
34
- - `addPushListener()` - Add event listener
35
- - `removePushListener()` - Remove event listener
36
-
37
- ### Browser Support
38
-
39
- - Chrome 50+
40
- - Firefox 44+
41
- - Safari 16+
42
- - Edge 17+
43
-
44
- ### Development Tools
45
-
46
- - Vite build tool
47
- - TypeScript support
48
- - Jest unit testing
49
- - ESLint code linting
50
- - 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 { }