@maxzima/wa-communicator 0.0.7 → 0.0.10

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/README.md CHANGED
@@ -52,13 +52,21 @@ communicator.sendMessage({
52
52
 
53
53
  ```javascript
54
54
  const communicator = new CommunicatorReceiver({
55
- senderOrigin: 'clients.google.com',
56
- callback: (message) => {
57
- if (message.target === CommunicatorTargetEnum.SIGN_UP && message.action[CommunicatorActionEnum.GOTO]) {
58
- window.location.href = message.action[CommunicatorActionEnum.GOTO].url;
59
- }
60
- }
55
+ senderOrigin: 'clients.google.com'
56
+ });
57
+
58
+ // subscribe
59
+ communicator.subscribe({
60
+ target: CommunicatorTargetEnum.SIGN_UP,
61
+ action: CommunicatorActionEnum.CLOSE,
62
+ callback: message => {
63
+ console.log('close', message);
64
+ },
65
+ });
66
+
67
+ // unsubscribe
68
+ receiver.unsubscribe({
69
+ action: CommunicatorActionEnum.CLOSE
61
70
  });
62
71
 
63
- communicator.watch();
64
72
  ```
@@ -1,8 +1,9 @@
1
- import { TReceiverProps } from '../types';
1
+ import { TReceiverProps, TReceiverSubscribeParams, TReceiverUnsubscribeMessageParams } from '../types';
2
2
  export declare class CommunicatorReceiver {
3
- private readonly callback;
4
3
  private readonly senderOrigin;
4
+ private queue;
5
5
  constructor(props: TReceiverProps);
6
- watch(): void;
7
6
  private onMessage;
7
+ subscribe: (params: TReceiverSubscribeParams) => void;
8
+ unsubscribe: (params?: TReceiverUnsubscribeMessageParams) => boolean;
8
9
  }
@@ -1,29 +1,85 @@
1
+ import { isValidMessage, modifyOrigin } from "./utils";
2
+ import { CommunicatorTargetEnum_isCorrect } from '../enums/CommunicatorTargetEnum';
3
+ import { CommunicatorActionEnum_isCorrect } from '../enums/CommunicatorActionEnum';
1
4
  export class CommunicatorReceiver {
2
5
  constructor(props) {
6
+ this.queue = [];
3
7
  this.onMessage = (event) => {
4
8
  if (!event || !event.origin || !event.data) {
5
9
  return;
6
10
  }
11
+ if (this.senderOrigin !== event.origin) {
12
+ return;
13
+ }
7
14
  let message;
8
15
  try {
9
16
  message = JSON.parse(event.data);
10
17
  }
11
18
  catch (error) {
12
- console.log('PostMessage read error');
13
19
  return;
14
20
  }
15
- if (this.senderOrigin !== event.origin) {
21
+ if (!isValidMessage(message)) {
16
22
  return;
17
23
  }
18
- if (typeof this.callback !== 'function') {
19
- return;
24
+ const queue = this.queue.filter(item => item.target === message.target && message.action.hasOwnProperty(item.action));
25
+ if (queue.length) {
26
+ queue.forEach(item => {
27
+ if (typeof item.params.callback === 'function') {
28
+ item.params.callback(message);
29
+ }
30
+ });
20
31
  }
21
- this.callback(message);
22
32
  };
23
- this.callback = props.callback;
24
- this.senderOrigin = props.senderOrigin;
25
- }
26
- watch() {
27
- window.addEventListener('message', this.onMessage, false);
33
+ this.subscribe = (params) => {
34
+ if (params.code && typeof params.code !== 'string') {
35
+ throw new Error('WAC: code can only be a string!');
36
+ }
37
+ if ((!params.target || !CommunicatorTargetEnum_isCorrect(params.target)) ||
38
+ (!params.action || !CommunicatorActionEnum_isCorrect(params.action))) {
39
+ throw new Error('WAC: target or action is not allowed!');
40
+ }
41
+ if (this.queue.find(item => {
42
+ return (!params.code || item.code === params.code) &&
43
+ item.target === params.target &&
44
+ item.action === params.action;
45
+ })) {
46
+ console.log(`WAB: subscribe is exists!`);
47
+ }
48
+ const newQueueItem = {
49
+ target: params.target,
50
+ action: params.action,
51
+ params: {
52
+ callback: params.callback,
53
+ }
54
+ };
55
+ if (params.code) {
56
+ newQueueItem['code'] = params.code;
57
+ }
58
+ this.queue.push(newQueueItem);
59
+ };
60
+ this.unsubscribe = (params) => {
61
+ if (!params) {
62
+ this.queue = [];
63
+ return true;
64
+ }
65
+ const queueForRemove = this.queue.filter(item => {
66
+ return (!params.code || item.code === params.code) &&
67
+ (!params.target || item.target === params.target) &&
68
+ (!params.action || item.action === params.action);
69
+ });
70
+ if (queueForRemove.length) {
71
+ const toRemove = new Set(queueForRemove);
72
+ this.queue = this.queue.filter(x => !toRemove.has(x));
73
+ return true;
74
+ }
75
+ return false;
76
+ };
77
+ this.senderOrigin = modifyOrigin(props.senderOrigin);
78
+ if (this.senderOrigin) {
79
+ window.addEventListener('message', this.onMessage, false);
80
+ }
81
+ else {
82
+ throw new Error('WAC: senderOrigin is broken!');
83
+ }
28
84
  }
29
85
  }
@@ -1,15 +1,19 @@
1
- import { modifyUrl } from './utils';
2
- import { CommunicatorTargetEnum_isCorrect } from '../enums/CommunicatorTargetEnum';
1
+ import { isValidMessage, modifyOrigin } from './utils';
3
2
  export class CommunicatorSender {
4
3
  constructor(props) {
5
4
  this.otherWindow = props.otherWindow;
6
- this.receiverOrigin = modifyUrl(props.receiverOrigin);
5
+ this.receiverOrigin = modifyOrigin(props.receiverOrigin);
6
+ if (!this.receiverOrigin) {
7
+ throw new Error('WAC: receiverOrigin is broken!');
8
+ }
7
9
  }
8
10
  sendMessage(message) {
9
- if (!this.receiverOrigin ||
10
- !CommunicatorTargetEnum_isCorrect(message.target)) {
11
+ if (!this.receiverOrigin) {
11
12
  return;
12
13
  }
14
+ if (!isValidMessage(message)) {
15
+ throw new Error(`WAC: Message not valid!`);
16
+ }
13
17
  const jsonMessage = JSON.stringify(message);
14
18
  this.otherWindow.postMessage(jsonMessage, this.receiverOrigin);
15
19
  }
@@ -1 +1,3 @@
1
- export declare function modifyUrl(address: string): string;
1
+ import { TCommunicatorMessage } from "../types";
2
+ export declare function modifyOrigin(address: string): string;
3
+ export declare function isValidMessage(message: TCommunicatorMessage): boolean;
@@ -1,4 +1,6 @@
1
- export function modifyUrl(address) {
1
+ import { CommunicatorTargetEnum_isCorrect } from "../enums/CommunicatorTargetEnum";
2
+ import { CommunicatorActionEnum_isCorrect } from "../enums/CommunicatorActionEnum";
3
+ export function modifyOrigin(address) {
2
4
  let url;
3
5
  try {
4
6
  let targetOrigin = address.trim();
@@ -8,5 +10,21 @@ export function modifyUrl(address) {
8
10
  catch (_) {
9
11
  return null;
10
12
  }
11
- return url.toString();
13
+ return url.origin;
14
+ }
15
+ export function isValidMessage(message) {
16
+ const isValidTarget = message.target && CommunicatorTargetEnum_isCorrect(message.target);
17
+ const actions = message.action;
18
+ let isValidActions = typeof actions === 'object';
19
+ if (isValidTarget && isValidActions) {
20
+ for (const prop in actions) {
21
+ if (actions.hasOwnProperty(prop)) {
22
+ isValidActions = actions.hasOwnProperty(prop) && CommunicatorActionEnum_isCorrect(prop);
23
+ if (!isValidActions) {
24
+ break;
25
+ }
26
+ }
27
+ }
28
+ }
29
+ return isValidTarget && isValidActions;
12
30
  }
@@ -2,6 +2,7 @@ export declare enum CommunicatorActionEnum {
2
2
  CLOSE = "close",
3
3
  OPEN = "open",
4
4
  GOTO = "goto",
5
- RESIZE = "resize"
5
+ RESIZE = "resize",
6
+ TOKEN = "token"
6
7
  }
7
8
  export declare function CommunicatorActionEnum_isCorrect(item: string): boolean;
@@ -4,6 +4,7 @@ export var CommunicatorActionEnum;
4
4
  CommunicatorActionEnum["OPEN"] = "open";
5
5
  CommunicatorActionEnum["GOTO"] = "goto";
6
6
  CommunicatorActionEnum["RESIZE"] = "resize";
7
+ CommunicatorActionEnum["TOKEN"] = "token";
7
8
  })(CommunicatorActionEnum || (CommunicatorActionEnum = {}));
8
9
  export function CommunicatorActionEnum_isCorrect(item) {
9
10
  return Object.values(CommunicatorActionEnum).includes(item);
@@ -2,4 +2,5 @@ import { CommunicatorReceiver } from "./engine/CommunicatorReceiver";
2
2
  import { CommunicatorTargetEnum } from "./enums/CommunicatorTargetEnum";
3
3
  import { CommunicatorActionEnum } from "./enums/CommunicatorActionEnum";
4
4
  import * as types from "./types";
5
- export { CommunicatorReceiver, CommunicatorTargetEnum, CommunicatorActionEnum, types, };
5
+ import { isValidMessage as communicatorMessageIsValid } from "./engine/utils";
6
+ export { CommunicatorReceiver, CommunicatorTargetEnum, CommunicatorActionEnum, types, communicatorMessageIsValid };
package/dist/receiver.js CHANGED
@@ -2,4 +2,5 @@ import { CommunicatorReceiver } from "./engine/CommunicatorReceiver";
2
2
  import { CommunicatorTargetEnum } from "./enums/CommunicatorTargetEnum";
3
3
  import { CommunicatorActionEnum } from "./enums/CommunicatorActionEnum";
4
4
  import * as types from "./types";
5
- export { CommunicatorReceiver, CommunicatorTargetEnum, CommunicatorActionEnum, types, };
5
+ import { isValidMessage as communicatorMessageIsValid } from "./engine/utils";
6
+ export { CommunicatorReceiver, CommunicatorTargetEnum, CommunicatorActionEnum, types, communicatorMessageIsValid };
@@ -5,7 +5,6 @@ export declare type TSenderProps = {
5
5
  otherWindow: Window;
6
6
  };
7
7
  export declare type TReceiverProps = {
8
- callback: TReceiverCallback;
9
8
  senderOrigin: string;
10
9
  };
11
10
  export declare type TReceiverCallback = (message: TCommunicatorMessage) => void;
@@ -22,8 +21,29 @@ export declare type TCommunicatorSenderActionMap = {
22
21
  [CommunicatorActionEnum.GOTO]?: TCommunicatorActionGotoParams;
23
22
  [CommunicatorActionEnum.CLOSE]?: true;
24
23
  [CommunicatorActionEnum.OPEN]?: CommunicatorTargetEnum;
24
+ [CommunicatorActionEnum.TOKEN]?: string;
25
25
  };
26
26
  export declare type TCommunicatorMessage = {
27
27
  target: CommunicatorTargetEnum;
28
28
  action: TCommunicatorSenderActionMap;
29
29
  };
30
+ export declare type TReceiverSubscribeParams = {
31
+ code?: string;
32
+ target: CommunicatorTargetEnum;
33
+ action: CommunicatorActionEnum;
34
+ callback: TReceiverCallback;
35
+ };
36
+ export declare type TReceiverMessageQueue = TReceiverMessageQueueItem[];
37
+ export declare type TReceiverMessageQueueItem = {
38
+ code?: string;
39
+ target: CommunicatorTargetEnum;
40
+ action: CommunicatorActionEnum;
41
+ params?: {
42
+ callback: TReceiverCallback;
43
+ };
44
+ };
45
+ export declare type TReceiverUnsubscribeMessageParams = {
46
+ code?: string;
47
+ target?: CommunicatorTargetEnum;
48
+ action?: CommunicatorActionEnum;
49
+ };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.7",
2
+ "version": "0.0.10",
3
3
  "name": "@maxzima/wa-communicator",
4
4
  "description": "",
5
5
  "author": "Noname",
@@ -1,19 +1,27 @@
1
- import {TCommunicatorMessage, TReceiverCallback, TReceiverProps} from '../types';
1
+ import {
2
+ TCommunicatorMessage,
3
+ TReceiverMessageQueue,
4
+ TReceiverProps,
5
+ TReceiverSubscribeParams,
6
+ TReceiverUnsubscribeMessageParams,
7
+ } from '../types';
8
+ import {isValidMessage, modifyOrigin} from "./utils";
9
+ import {CommunicatorTargetEnum_isCorrect} from '../enums/CommunicatorTargetEnum';
10
+ import {CommunicatorActionEnum_isCorrect} from '../enums/CommunicatorActionEnum';
2
11
 
3
12
  export class CommunicatorReceiver {
4
- private readonly callback: TReceiverCallback;
5
13
  private readonly senderOrigin: string;
14
+ private queue: TReceiverMessageQueue = [];
6
15
 
7
16
  constructor(props: TReceiverProps) {
8
- this.callback = props.callback;
9
- this.senderOrigin = props.senderOrigin;
10
- }
17
+ this.senderOrigin = modifyOrigin(props.senderOrigin);
11
18
 
12
- /**
13
- * Watch Messages
14
- */
15
- public watch() {
16
- window.addEventListener('message', this.onMessage, false);
19
+ if (this.senderOrigin) {
20
+ // Watch Messages
21
+ window.addEventListener('message', this.onMessage, false);
22
+ } else {
23
+ throw new Error('WAC: senderOrigin is broken!');
24
+ }
17
25
  }
18
26
 
19
27
  /**
@@ -25,24 +33,96 @@ export class CommunicatorReceiver {
25
33
  return;
26
34
  }
27
35
 
36
+ if (this.senderOrigin !== event.origin) {
37
+ return;
38
+ }
39
+
28
40
  let message: TCommunicatorMessage;
29
41
 
30
42
  try {
31
43
  message = JSON.parse(event.data);
32
44
  } catch (error) {
33
- console.log('PostMessage read error');
34
45
  return;
35
46
  }
36
47
 
37
- if (this.senderOrigin !== event.origin) {
48
+ if (!isValidMessage(message)) {
38
49
  return;
39
50
  }
40
51
 
41
- if (typeof this.callback !== 'function') {
42
- return;
43
- }
52
+ // Find queue by target and action
53
+ const queue = this.queue.filter(item => item.target === message.target && message.action.hasOwnProperty(item.action));
44
54
 
45
- this.callback(message);
55
+ if (queue.length) {
56
+ queue.forEach(item => {
57
+ if (typeof item.params.callback === 'function') {
58
+ item.params.callback(message);
59
+ }
60
+ })
61
+ }
46
62
  };
63
+
64
+ /**
65
+ * Subscribe by target and action
66
+ * @param params
67
+ */
68
+ public subscribe = (params: TReceiverSubscribeParams): void => {
69
+ if (params.code && typeof params.code !== 'string') {
70
+ throw new Error('WAC: code can only be a string!');
71
+ }
72
+
73
+ if (
74
+ (!params.target || !CommunicatorTargetEnum_isCorrect(params.target)) ||
75
+ (!params.action || !CommunicatorActionEnum_isCorrect(params.action))
76
+ ) {
77
+ throw new Error('WAC: target or action is not allowed!');
78
+ }
79
+
80
+ if (this.queue.find(item => {
81
+ return (!params.code || item.code === params.code) &&
82
+ item.target === params.target &&
83
+ item.action === params.action;
84
+ })) {
85
+ console.log(`WAB: subscribe is exists!`);
86
+ }
87
+
88
+ const newQueueItem = {
89
+ target: params.target,
90
+ action: params.action,
91
+ params: {
92
+ callback: params.callback,
93
+ }
94
+ };
95
+
96
+ if (params.code) {
97
+ newQueueItem['code'] = params.code;
98
+ }
99
+
100
+ this.queue.push(newQueueItem);
101
+ }
102
+
103
+ /**
104
+ * Subscribe by code or target or action
105
+ * @param params
106
+ */
107
+ public unsubscribe = (params?: TReceiverUnsubscribeMessageParams): boolean => {
108
+ if (!params) {
109
+ this.queue = [];
110
+ return true;
111
+ }
112
+
113
+ const queueForRemove = this.queue.filter(item => {
114
+ return (!params.code || item.code === params.code) &&
115
+ (!params.target || item.target === params.target) &&
116
+ (!params.action || item.action === params.action);
117
+ });
118
+
119
+ if (queueForRemove.length) {
120
+ const toRemove = new Set(queueForRemove);
121
+ this.queue = this.queue.filter(x => !toRemove.has(x));
122
+ return true;
123
+ }
124
+
125
+ return false;
126
+ }
47
127
  }
48
128
 
@@ -1,6 +1,5 @@
1
1
  import {TCommunicatorMessage, TSenderProps} from '../types';
2
- import {modifyUrl} from './utils';
3
- import {CommunicatorTargetEnum_isCorrect} from '../enums/CommunicatorTargetEnum';
2
+ import {isValidMessage, modifyOrigin} from './utils';
4
3
 
5
4
  export class CommunicatorSender {
6
5
  private readonly otherWindow: Window;
@@ -8,7 +7,11 @@ export class CommunicatorSender {
8
7
 
9
8
  constructor(props: TSenderProps) {
10
9
  this.otherWindow = props.otherWindow;
11
- this.receiverOrigin = modifyUrl(props.receiverOrigin);
10
+ this.receiverOrigin = modifyOrigin(props.receiverOrigin);
11
+
12
+ if (!this.receiverOrigin) {
13
+ throw new Error('WAC: receiverOrigin is broken!');
14
+ }
12
15
  }
13
16
 
14
17
  /**
@@ -16,13 +19,14 @@ export class CommunicatorSender {
16
19
  * @param message
17
20
  */
18
21
  public sendMessage(message: TCommunicatorMessage) {
19
- if (
20
- !this.receiverOrigin ||
21
- !CommunicatorTargetEnum_isCorrect(message.target)
22
- ) {
22
+ if (!this.receiverOrigin) {
23
23
  return;
24
24
  }
25
25
 
26
+ if (!isValidMessage(message)) {
27
+ throw new Error(`WAC: Message not valid!`);
28
+ }
29
+
26
30
  const jsonMessage = JSON.stringify(message);
27
31
  this.otherWindow.postMessage(jsonMessage, this.receiverOrigin);
28
32
  }
@@ -1,4 +1,12 @@
1
- export function modifyUrl(address: string): string {
1
+ import {TCommunicatorMessage} from "../types";
2
+ import {CommunicatorTargetEnum_isCorrect} from "../enums/CommunicatorTargetEnum";
3
+ import {CommunicatorActionEnum_isCorrect} from "../enums/CommunicatorActionEnum";
4
+
5
+ /**
6
+ *
7
+ * @param address
8
+ */
9
+ export function modifyOrigin(address: string): string {
2
10
  let url: URL;
3
11
  try {
4
12
  let targetOrigin = address.trim();
@@ -7,5 +15,28 @@ export function modifyUrl(address: string): string {
7
15
  } catch (_) {
8
16
  return null;
9
17
  }
10
- return url.toString();
18
+ return url.origin;
19
+ }
20
+
21
+ /**
22
+ * Check the message for validity
23
+ * @param message
24
+ */
25
+ export function isValidMessage(message: TCommunicatorMessage) {
26
+ const isValidTarget = message.target && CommunicatorTargetEnum_isCorrect(message.target);
27
+ const actions = message.action;
28
+ let isValidActions = typeof actions === 'object';
29
+
30
+ if (isValidTarget && isValidActions) {
31
+ for (const prop in actions) {
32
+ if(actions.hasOwnProperty(prop)) {
33
+ isValidActions = actions.hasOwnProperty(prop) && CommunicatorActionEnum_isCorrect(prop);
34
+ if (!isValidActions) {
35
+ break;
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ return isValidTarget && isValidActions;
11
42
  }
@@ -3,6 +3,7 @@ export enum CommunicatorActionEnum {
3
3
  OPEN = 'open',
4
4
  GOTO = 'goto',
5
5
  RESIZE = 'resize',
6
+ TOKEN = 'token',
6
7
  }
7
8
 
8
9
  export function CommunicatorActionEnum_isCorrect(item: string): boolean {
package/src/receiver.ts CHANGED
@@ -2,10 +2,12 @@ import {CommunicatorReceiver} from "./engine/CommunicatorReceiver"
2
2
  import {CommunicatorTargetEnum} from "./enums/CommunicatorTargetEnum"
3
3
  import {CommunicatorActionEnum} from "./enums/CommunicatorActionEnum"
4
4
  import * as types from "./types";
5
+ import {isValidMessage as communicatorMessageIsValid} from "./engine/utils";
5
6
 
6
7
  export {
7
8
  CommunicatorReceiver,
8
9
  CommunicatorTargetEnum,
9
10
  CommunicatorActionEnum,
10
11
  types,
12
+ communicatorMessageIsValid
11
13
  }
@@ -7,7 +7,6 @@ export type TSenderProps = {
7
7
  }
8
8
 
9
9
  export type TReceiverProps = {
10
- callback: TReceiverCallback,
11
10
  senderOrigin: string,
12
11
  }
13
12
 
@@ -28,9 +27,34 @@ export type TCommunicatorSenderActionMap = {
28
27
  [CommunicatorActionEnum.GOTO]?: TCommunicatorActionGotoParams,
29
28
  [CommunicatorActionEnum.CLOSE]?: true,
30
29
  [CommunicatorActionEnum.OPEN]?: CommunicatorTargetEnum,
30
+ [CommunicatorActionEnum.TOKEN]?: string,
31
31
  }
32
32
 
33
33
  export type TCommunicatorMessage = {
34
34
  target: CommunicatorTargetEnum,
35
35
  action: TCommunicatorSenderActionMap
36
36
  }
37
+
38
+ export type TReceiverSubscribeParams = {
39
+ code?: string;
40
+ target: CommunicatorTargetEnum,
41
+ action: CommunicatorActionEnum,
42
+ callback: TReceiverCallback,
43
+ }
44
+
45
+ export type TReceiverMessageQueue = TReceiverMessageQueueItem[]
46
+
47
+ export type TReceiverMessageQueueItem = {
48
+ code?: string;
49
+ target: CommunicatorTargetEnum,
50
+ action: CommunicatorActionEnum,
51
+ params?: {
52
+ callback: TReceiverCallback,
53
+ }
54
+ }
55
+
56
+ export type TReceiverUnsubscribeMessageParams = {
57
+ code?: string;
58
+ target?: CommunicatorTargetEnum,
59
+ action?: CommunicatorActionEnum,
60
+ }
package/tsconfig.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "outDir": "dist",
17
17
  "alwaysStrict": true,
18
18
  "removeComments": true,
19
- "noImplicitReturns": true,
19
+ "noImplicitReturns": false,
20
20
  "noEmit": false,
21
21
  "noFallthroughCasesInSwitch": true,
22
22
  "noUnusedLocals": true,