bm-webapp-sdk 0.1.2 → 0.1.4

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/dist/index.d.ts CHANGED
@@ -1,63 +1,7 @@
1
- interface HandlerOptions {
2
- sessionHash?: string;
3
- scenarioCode?: string;
4
- initVariables?: TData;
5
- botTokenParamName?: string;
6
- userApiToken?: string;
7
- retryDelayOnTimeout?: number;
8
- requestTimeout?: number;
9
- responseVar?: string;
10
- apiEndpoint?: string;
11
- }
12
- type TData = {
13
- [key: string]: any;
14
- };
15
- interface INodeEventsDecl {
16
- inbox: boolean;
17
- outbox: boolean;
18
- anyInbox: boolean;
19
- dialogClosed: boolean;
20
- invoicePaid: boolean;
21
- externalRequest: boolean;
22
- buttons: boolean;
23
- customEvents: boolean;
24
- }
25
- interface INode {
26
- id: number;
27
- title: string;
28
- typeName: "basic" | "event" | "eventListener" | "condition" | "conditionBranch";
29
- waitingForEvents?: INodeEventsDecl;
30
- }
31
- type TScenarioSessionStatus = "active" | "stopped" | "ended" | "unknownError" | "tunnelDisabled" | "expired" | "userDisabled" | "stepDeleted" | "transitionsLimit" | "parentStopped";
32
- interface ScenarioSession {
33
- id: number;
34
- hash: string;
35
- statusName: TScenarioSessionStatus;
36
- ref: string | null;
37
- variables: TData;
38
- isTransitioning: boolean;
39
- currentNode: INode | null;
40
- }
41
- export default class WebAppHandler {
42
- readonly options: HandlerOptions;
43
- data?: ScenarioSession;
44
- private currentRequest?;
45
- constructor(options: HandlerOptions);
46
- isActive(): boolean;
47
- init(): Promise<WebAppHandler>;
48
- refreshData(): Promise<WebAppHandler>;
49
- request(code: string, params?: TData, async?: boolean): Promise<WebAppHandler>;
50
- abort(): void;
51
- isTelegramInitAvailable(): boolean;
52
- protected initNewSession(): Promise<WebAppHandler>;
53
- protected makeRequest(method: string, path: string, json?: TData, signal?: AbortSignal): Promise<any>;
54
- private waitUntilSessionFinishesTransition;
55
- }
56
-
1
+ import WebAppHandler from './WebAppHandler';
57
2
  export { WebAppHandler };
58
3
  declare global {
59
4
  interface Window {
60
5
  Telegram: any;
61
6
  }
62
7
  }
63
-
@@ -0,0 +1,61 @@
1
+ export interface HandlerOptions {
2
+ sessionHash?: string;
3
+ scenarioCode?: string;
4
+ initVariables?: TData;
5
+ botTokenParamName?: string;
6
+ userApiToken?: string;
7
+ retryDelayOnTimeout?: number;
8
+ requestTimeout?: number;
9
+ responseVar?: string;
10
+ apiEndpoint?: string;
11
+ }
12
+ export type TData = {
13
+ [key: string]: any;
14
+ };
15
+ export interface INodeEventsDecl {
16
+ inbox: boolean;
17
+ outbox: boolean;
18
+ anyInbox: boolean;
19
+ dialogClosed: boolean;
20
+ invoicePaid: boolean;
21
+ externalRequest: boolean;
22
+ buttons: boolean;
23
+ customEvents: boolean;
24
+ }
25
+ export interface INode {
26
+ id: number;
27
+ title: string;
28
+ typeName: "basic" | "event" | "eventListener" | "condition" | "conditionBranch";
29
+ waitingForEvents?: INodeEventsDecl;
30
+ }
31
+ export type TScenarioSessionStatus = "active" | "stopped" | "ended" | "unknownError" | "tunnelDisabled" | "expired" | "userDisabled" | "stepDeleted" | "transitionsLimit" | "parentStopped";
32
+ export interface ScenarioSession {
33
+ id: number;
34
+ hash: string;
35
+ statusName: TScenarioSessionStatus;
36
+ ref: string | null;
37
+ variables: TData;
38
+ isTransitioning: boolean;
39
+ currentNode: INode | null;
40
+ }
41
+ export interface ICurrentRequest {
42
+ controller: AbortController | null;
43
+ timeoutId: number;
44
+ retryTimeoutId?: number;
45
+ reject?: (reason?: any) => void;
46
+ }
47
+ export default class WebAppHandler {
48
+ readonly options: HandlerOptions;
49
+ data?: ScenarioSession;
50
+ private currentRequest?;
51
+ constructor(options: HandlerOptions);
52
+ isActive(): boolean;
53
+ init(): Promise<WebAppHandler>;
54
+ refreshData(): Promise<WebAppHandler>;
55
+ request(code: string, params?: TData, async?: boolean): Promise<WebAppHandler>;
56
+ abort(): void;
57
+ isTelegramInitAvailable(): boolean;
58
+ protected initNewSession(): Promise<WebAppHandler>;
59
+ protected makeRequest(method: string, path: string, json?: TData, signal?: AbortSignal): Promise<any>;
60
+ private waitUntilSessionFinishesTransition;
61
+ }
@@ -0,0 +1,138 @@
1
+ const DEFAULTS = {
2
+ retryDelayOnTimeout: 2000,
3
+ requestTimeout: 60000,
4
+ responseVar: 'response',
5
+ apiEndpoint: 'https://console.bot-marketing.com/api/public',
6
+ };
7
+ export default class WebAppHandler {
8
+ constructor(options) {
9
+ this.options = { ...DEFAULTS, ...options };
10
+ }
11
+ isActive() {
12
+ return this.data?.statusName === "active";
13
+ }
14
+ async init() {
15
+ if (this.data)
16
+ throw new Error("Handler already initialized");
17
+ if (this.options.sessionHash) {
18
+ await this.refreshData();
19
+ if (!this.isActive() && this.isTelegramInitAvailable())
20
+ return this.initNewSession();
21
+ return this;
22
+ }
23
+ else if (this.isTelegramInitAvailable()) {
24
+ return this.initNewSession();
25
+ }
26
+ else {
27
+ throw new Error('Failed to init handler. You must specify `sessionId`, or `scenarioId` when working with Telegram');
28
+ }
29
+ }
30
+ async refreshData() {
31
+ const sessionId = this.data?.hash || this.options.sessionHash;
32
+ if (!sessionId)
33
+ throw new Error('Cannot refresh data: session id is missing');
34
+ try {
35
+ this.data = await this.makeRequest("GET", `tunnelSessions/${sessionId}`);
36
+ return this;
37
+ }
38
+ catch (error) {
39
+ throw new Error(`Failed to get session data: ${error.message}`);
40
+ }
41
+ }
42
+ async request(code, params, async) {
43
+ if (this.currentRequest)
44
+ throw new Error('Please wait until pending request is finished');
45
+ if (!this.data)
46
+ await this.init();
47
+ if (!this.isActive())
48
+ throw new Error('Cannot make request: session is not active');
49
+ if (async) {
50
+ // noinspection ES6MissingAwait
51
+ this.makeRequest("POST", `tunnelSessions/${this.data.hash}/request`, { code, params });
52
+ return this;
53
+ }
54
+ try {
55
+ this.currentRequest = {
56
+ controller: new AbortController(),
57
+ timeoutId: setTimeout(() => this.abort(), this.options.requestTimeout),
58
+ };
59
+ this.data = await this.makeRequest("POST", `tunnelSessions/${this.data.hash}/request`, { code, params, }, this.currentRequest.controller.signal);
60
+ this.currentRequest = null;
61
+ return this;
62
+ }
63
+ catch (error) {
64
+ if (error.message === 'request_timeout')
65
+ return this.waitUntilSessionFinishesTransition();
66
+ this.currentRequest = null;
67
+ throw error;
68
+ }
69
+ }
70
+ abort() {
71
+ if (!this.currentRequest)
72
+ return;
73
+ // Main request is still running, we can just abort it
74
+ // The rest is done inside request method
75
+ if (this.currentRequest.controller) {
76
+ this.currentRequest.controller.abort('Request timeout');
77
+ }
78
+ else {
79
+ // At this point we are trying to wait until session is finished transitioning
80
+ clearTimeout(this.currentRequest.retryTimeoutId);
81
+ this.currentRequest.reject('Request timeout');
82
+ this.currentRequest = null;
83
+ }
84
+ }
85
+ isTelegramInitAvailable() {
86
+ return window.Telegram !== undefined && this.options.scenarioCode !== undefined;
87
+ }
88
+ async initNewSession() {
89
+ try {
90
+ this.data = await this.makeRequest("POST", `tunnel/${this.options.scenarioCode}/initWebApp`, {
91
+ initData: Telegram.WebApp.initData,
92
+ botTokenParamName: this.options.botTokenParamName,
93
+ variables: this.options.initVariables,
94
+ });
95
+ return this;
96
+ }
97
+ catch (error) {
98
+ throw new Error(`Failed to init new session: ${error.message}`);
99
+ }
100
+ }
101
+ async makeRequest(method, path, json, signal) {
102
+ const resp = await fetch(`${this.options.apiEndpoint}/${path}`, {
103
+ method: method,
104
+ signal,
105
+ ...(method === "POST" ? {
106
+ body: JSON.stringify(json),
107
+ headers: {
108
+ "Content-Type": "application/json",
109
+ "Accept": "application/json",
110
+ },
111
+ } : {
112
+ headers: { "Accept": "application/json" },
113
+ }),
114
+ });
115
+ if (resp.status >= 400) {
116
+ const data = await resp.json();
117
+ throw new Error(data.message || `Http Error ${resp.status}`);
118
+ }
119
+ return resp.json();
120
+ }
121
+ waitUntilSessionFinishesTransition() {
122
+ return new Promise((resolve, reject) => {
123
+ this.currentRequest.reject = reject;
124
+ const resetTimeout = () => {
125
+ this.currentRequest.retryTimeoutId = setTimeout(async () => {
126
+ await this.refreshData();
127
+ if (this.data.isTransitioning) {
128
+ resetTimeout();
129
+ }
130
+ else {
131
+ resolve(this);
132
+ }
133
+ }, this.options.retryDelayOnTimeout);
134
+ };
135
+ resetTimeout();
136
+ });
137
+ }
138
+ }
package/esm/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import WebAppHandler from './WebAppHandler';
2
+ export { WebAppHandler };
3
+ declare global {
4
+ interface Window {
5
+ Telegram: any;
6
+ }
7
+ }
package/esm/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import WebAppHandler from './WebAppHandler';
2
+ export { WebAppHandler };
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "bm-webapp-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "",
5
- "main": "dist/bundle.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "esm/index.js",
6
+ "types": "esm/index.d.ts",
7
7
  "scripts": {
8
8
  "develop": "webpack-dev-server --mode development",
9
9
  "build": "webpack --mode production"
10
10
  },
11
11
  "repository": "https://gitlab.com/b4494/bm-webapp-sdk",
12
12
  "files": [
13
- "/dist"
13
+ "/dist",
14
+ "/esm"
14
15
  ],
15
16
  "keywords": [],
16
17
  "author": "lazychaser@gmail.com",