@jibb-open/jssdk 3.5.5

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/.babelrc +31 -0
  2. package/README.md +3 -0
  3. package/package.json +72 -0
  4. package/src/api/admin.js +333 -0
  5. package/src/api/auth.js +208 -0
  6. package/src/api/eventbus.js +246 -0
  7. package/src/api/index.js +26 -0
  8. package/src/api/meeting.js +421 -0
  9. package/src/api/recording.js +225 -0
  10. package/src/api/superadmin.js +84 -0
  11. package/src/api/user.js +46 -0
  12. package/src/api/webexbot.js +32 -0
  13. package/src/api/whiteboard.js +175 -0
  14. package/src/config.js +12 -0
  15. package/src/examples/browser/462.jibb.js +1 -0
  16. package/src/examples/browser/index.html +13 -0
  17. package/src/examples/browser/jibb.js +2 -0
  18. package/src/examples/browser/startSession.js +112 -0
  19. package/src/examples/examples.js +5 -0
  20. package/src/examples/webexDevicesMacros/cameraPresets/jibb.js +338 -0
  21. package/src/examples/webexDevicesMacros/simplestExample/jibb.js +212 -0
  22. package/src/examples/webexDevicesMacros/webexDevice JSSDK/jibb_WebexXapi.js +2 -0
  23. package/src/examples/webexDevicesMacros/withCameraControl/jibb.js +303 -0
  24. package/src/index.webex-devices.js +13 -0
  25. package/src/post-processing.js +39 -0
  26. package/src/types/exceptions.js +48 -0
  27. package/src/types/jibb.pb.js +1426 -0
  28. package/src/types/proto.js +7 -0
  29. package/src/types/types.js +64 -0
  30. package/src/utils/cached_variable.js +23 -0
  31. package/src/utils/future.js +24 -0
  32. package/src/utils/http/http.axios.js +34 -0
  33. package/src/utils/http/http.xapi.js +87 -0
  34. package/src/utils/http/index.js +8 -0
  35. package/src/utils/index.js +5 -0
  36. package/src/utils/logger/index.js +11 -0
  37. package/src/utils/logger/logger.empty.js +25 -0
  38. package/src/utils/logger/logger.pino.js +15 -0
  39. package/src/ws/connection_base.js +81 -0
  40. package/src/ws/eventbus.js +363 -0
  41. package/src/ws/index.js +15 -0
  42. package/src/ws/ipsa.js +238 -0
  43. package/src/ws/meeting.js +170 -0
  44. package/src/ws/observable_connection.js +84 -0
  45. package/src/ws/retry_connection.js +82 -0
  46. package/webpack.config.cjs +144 -0
@@ -0,0 +1,170 @@
1
+ import {Auth} from '../api/auth.js';
2
+ import {Config} from "../config.js";
3
+ import {logger} from "../utils/logger/index.js"
4
+ import {RetryConnection} from "./retry_connection.js";
5
+ import {ConnectionStatus} from "./connection_base.js";
6
+ import {MeetingClaims} from "../types/types.js";
7
+
8
+ import {meeting, types} from "../types/proto.js"
9
+ let Message = meeting.Message
10
+ let ErrorCode = types.Code
11
+
12
+ if (globalThis?.WebSocket == undefined) {
13
+ import("isomorphic-ws").then((webSocket) => {
14
+ globalThis.WebSocket = webSocket.default;
15
+ });
16
+ }
17
+
18
+ class MeetingConnectionImp extends RetryConnection {
19
+ #expiryTimer
20
+ constructor() {
21
+ super('meeting')
22
+ this.meetingId = null
23
+ this.meetingToken = null
24
+ this.#expiryTimer = null
25
+ }
26
+
27
+ getName() {
28
+ return `${super.getName()}-${this.meetingId}`
29
+ }
30
+
31
+ async start(meetingToken) {
32
+ this.meetingToken = meetingToken
33
+ this.meetingClaims = new MeetingClaims(meetingToken)
34
+ this.meetingId = this.meetingClaims.meetindId
35
+ let seconds = this.meetingClaims.getSecondsUntilExpiry()
36
+ if (seconds <= 0) {
37
+ this.onErrorMessage(ErrorCode.ERR_TIMEOUT, "meeting token expired");
38
+ return
39
+ }
40
+ this.#expiryTimer = setTimeout(() => {
41
+ this.stop()
42
+ this.onErrorMessage(ErrorCode.ERR_TIMEOUT, "meeting token expired");
43
+ }, seconds)
44
+ super.start()
45
+ }
46
+
47
+ async stop() {
48
+ clearTimeout(this.#expiryTimer)
49
+ super.stop()
50
+ }
51
+
52
+ disconnect() {
53
+ if (this.socket != null) {
54
+ this.socket.close();
55
+ this.socket = null;
56
+ // this.fireOnError(ErrorLevel.ERROR, ErrorCode.ERR_CLOSED, "closed") //this one fired after diconnection error causes multiple connection (it call retray connection again)
57
+ logger.info("meeting disconnect ", this.meetingId);
58
+ }
59
+
60
+ super.disconnect()
61
+ }
62
+
63
+ async connect() {
64
+ if (this.getConnectionStatus() != ConnectionStatus.DISCONNECTED)
65
+ return
66
+
67
+ super.connect()
68
+ let self = this;
69
+
70
+ try {
71
+ if (this.meetingClaims.isExpired()) {
72
+ self.onErrorMessage(ErrorCode.ERR_TIMEOUT, "meeting token expired");
73
+ return;
74
+ }
75
+ } catch (e) {
76
+ self.onErrorMessage(ErrorCode.ERR_BAD_REQUEST, "invalid meeting token");
77
+ return
78
+ }
79
+
80
+ let base = new URL(Config.apiBaseURL)
81
+ let uri = "wss://" + base.hostname + "/ws/meetings/" + this.meetingId + "?meeting_token=" + this.meetingToken;
82
+
83
+ this.socket = new WebSocket(uri);
84
+ this.socket.binaryType = "arraybuffer"
85
+ this.socket.addEventListener("open", function () {
86
+ self.onConnected()
87
+ });
88
+ this.socket.addEventListener("close", function () {
89
+ self.onDisconnected()
90
+ });
91
+ this.socket.addEventListener("message", function (event) {
92
+ self.#handleMessage(event.data)
93
+ });
94
+ this.socket.addEventListener("error", function (err) {
95
+ self.onWarningMessage(ErrorCode.ERR_IO, err);
96
+ });
97
+ }
98
+
99
+ async #handleMessage(msg) {
100
+ try {
101
+ if (msg instanceof ArrayBuffer) {
102
+ let buffer = new Uint8Array(msg)
103
+ let event = Message.decode(buffer);
104
+
105
+ if (event?.update)
106
+ this.notify('onMeetingUpdate', event.update)
107
+ if (event?.drawing)
108
+ this.notify('onDrawing', event.drawing)
109
+ if (event?.pointer)
110
+ this.notify('onPointer', event)
111
+ else if (event?.join)
112
+ this.notify('onMeetingJoin', event.join)
113
+ else if (event?.leave)
114
+ this.notify('onMeetingLeave', event.leave)
115
+ return
116
+ }
117
+ } catch (err) {
118
+ logger.error(err)
119
+ }
120
+
121
+ try {
122
+ let Error = JSON.parse(msg);
123
+ switch (Error.code) {
124
+ case ErrorCode.ERR_TOO_MANY_CONNECTIONS:
125
+ case ErrorCode.ERR_UNAUTHORIZED:
126
+ case ErrorCode.ERR_BAD_REQUEST:
127
+ case ErrorCode.ERR_TIMEOUT:
128
+ this.onErrorMessage(Error.code, Error.reason)
129
+ break
130
+ default:
131
+ this.onInfoMessage(Error.code, Error.reason)
132
+ break
133
+ }
134
+ } catch (e) {
135
+ logger.error(e)
136
+ this.onWarningMessage(ErrorCode.ERR_IO, msg)
137
+ }
138
+ }
139
+
140
+ async sendPointer(x, y) {
141
+ await super.waitForConnection()
142
+ let claims = await Auth.getUserClaims()
143
+ let msg = Message.fromObject({
144
+ pointer: {
145
+ email: claims.email,
146
+ x: x,
147
+ y: y,
148
+ }
149
+ })
150
+
151
+ let buf = Message.encode(msg).finish();
152
+ this.socket.send(buf)
153
+ }
154
+
155
+ async sendDrawing({email, data}) {
156
+ await super.waitForConnection()
157
+ let msg = Message.fromObject({
158
+ drawing: {
159
+ email: email,
160
+ data: data,
161
+ }
162
+ })
163
+ logger.debug(`${this.getName()}.Drawing: `, Message.toObject(msg))
164
+
165
+ let buf = Message.encode(msg).finish();
166
+ this.socket.send(buf)
167
+ }
168
+ }
169
+
170
+ export let MeetingConnection = new MeetingConnectionImp()
@@ -0,0 +1,84 @@
1
+ import {logger} from "../utils/logger/index.js"
2
+ import {ConnectionBase} from "./connection_base.js"
3
+
4
+ export class ObservableConnection extends ConnectionBase {
5
+ constructor(connectionName) {
6
+ super(connectionName)
7
+ this.observers = new Map()
8
+ }
9
+
10
+ subscribe(id, observer) {
11
+ this.observers.set(id, observer)
12
+ }
13
+
14
+ unsubscribeAll() {
15
+ this.observers = new Map()
16
+ }
17
+
18
+ unsubscribe(id) {
19
+ try {
20
+ this.observers.delete(id)
21
+ } catch (err) {
22
+ logger.error(err)
23
+ }
24
+ }
25
+
26
+ notify(eventName, ...args) {
27
+ this.observers.forEach((o) => {
28
+ try {
29
+ let fn = o[eventName]
30
+ if (fn !== undefined) fn(...args)
31
+ } catch (err) {
32
+ logger.error(`Error occured notifying event ${eventName}`, err)
33
+ }
34
+ })
35
+ }
36
+
37
+ callSubscribers(functionName, ...args) {
38
+ let promises = []
39
+
40
+ this.observers.forEach((o) => {
41
+ try {
42
+ let fn = o[functionName]
43
+ if (fn !== undefined) {
44
+ let res = fn(...args)
45
+ promises.push(res)
46
+ }
47
+ } catch (error) {
48
+ logger.error(error)
49
+ }
50
+ })
51
+
52
+ return Promise.any(promises)
53
+ }
54
+
55
+ onDisconnected() {
56
+ super.onDisconnected()
57
+ this.notify("onDisconnected")
58
+ }
59
+
60
+ onConnected() {
61
+ super.onConnected()
62
+ this.notify("onConnected")
63
+ }
64
+
65
+ onStopped() {
66
+ super.onStopped()
67
+ this.notify("onStopped")
68
+ }
69
+
70
+ onErrorMessage(code, reason) {
71
+ super.onErrorMessage(code, reason)
72
+ this.notify("onErrorMessage", code, reason)
73
+ }
74
+
75
+ onWarningMessage(code, reason) {
76
+ super.onWarningMessage(code, reason)
77
+ this.notify("onWarningMessage", code, reason)
78
+ }
79
+
80
+ onInfoMessage(code, reason) {
81
+ super.onInfoMessage(code, reason)
82
+ this.notify("onInfoMessage", code, reason)
83
+ }
84
+ }
@@ -0,0 +1,82 @@
1
+ import { logger } from "../utils/logger/index.js"
2
+ import { ObservableConnection } from "./observable_connection.js"
3
+
4
+ export class RetryConnection extends ObservableConnection {
5
+ #started
6
+
7
+ constructor(connectionName, maxRetryCount = 10, minRetryIntervalMs = 500, maxRetryIntervalMs = 32000) {
8
+ super(connectionName)
9
+
10
+ this.maxRetryCount = maxRetryCount
11
+ this.minRetryIntervalMs = minRetryIntervalMs
12
+ this.maxRetryIntervalMs = maxRetryIntervalMs
13
+ this.retryCount = 0
14
+ this.retryIntervalMs = minRetryIntervalMs
15
+ this.lastConnectionTime = Date.now() - maxRetryIntervalMs
16
+ this.retryTimer = null
17
+ this.#started = false
18
+ }
19
+
20
+ start() {
21
+ if (!this.isStarted()) {
22
+ logger.info(`${this.getName()}: starting...`)
23
+ this.#started = true
24
+ this.connect()
25
+ }
26
+ }
27
+
28
+ stop() {
29
+ logger.info(`${this.getName()}: stopping...`)
30
+ this.#started = false
31
+ this.disconnect()
32
+ }
33
+
34
+ isStarted() {
35
+ return this.#started
36
+ }
37
+
38
+ onDisconnected() {
39
+ super.onDisconnected()
40
+ if (this.isStarted()) this.#reconnect()
41
+ }
42
+
43
+ connect() {
44
+ if (this.isStarted()) super.connect()
45
+ }
46
+
47
+ disconnect() {
48
+ if (this.retryTimer) {
49
+ clearTimeout(this.retryTimer)
50
+ this.retryTimer = null
51
+ }
52
+ super.disconnect()
53
+ }
54
+
55
+ #reconnect() {
56
+ let self = this
57
+
58
+ if (Date.now() - this.lastConnectionTime < this.retryIntervalMs) {
59
+ this.retryIntervalMs = Math.min(this.retryIntervalMs * 2, this.maxRetryIntervalMs)
60
+ this.retryCount = this.retryCount + 1
61
+ } else {
62
+ this.retryCount = 1
63
+ this.retryIntervalMs = this.minRetryIntervalMs
64
+ }
65
+
66
+ if (this.retryCount >= this.maxRetryCount) {
67
+ this.stop()
68
+ return
69
+ }
70
+
71
+ this.retryTimer = setTimeout(() => {
72
+ logger.info(`${this.getName()}: retrying connection... [interval: ${this.retryIntervalMs}ms]`)
73
+ self.lastConnectionTime = Date.now() + 4000
74
+ self.connect()
75
+ }, this.retryIntervalMs)
76
+ }
77
+
78
+ onErrorMessage(code, reason) {
79
+ super.onErrorMessage(code, reason)
80
+ this.stop()
81
+ }
82
+ }
@@ -0,0 +1,144 @@
1
+ const path = require('path');
2
+ const webpack = require("webpack")
3
+
4
+ var BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin
5
+
6
+ const webConfig = {
7
+ mode: "production",
8
+ target: "web",
9
+ entry: "./src/api/index.js",
10
+ output: {
11
+ filename: "jibb.js",
12
+ path: path.resolve(__dirname, "dist/web"),
13
+ globalObject: "globalThis",
14
+ library: {
15
+ name: "JIBB",
16
+ type: "umd",
17
+ export: "default",
18
+ },
19
+ },
20
+ module: {
21
+ rules: [
22
+ {
23
+ test: /\.js$/,
24
+ exclude: ["/(node_modules)/"],
25
+ use: {
26
+ loader: "babel-loader",
27
+ options: {
28
+ presets: ["@babel/preset-env"],
29
+ plugins: [
30
+ [
31
+ "babel-plugin-transform-import-ignore",
32
+ {
33
+ patterns: ["*xapi*", "**/*.webex-devices.js"],
34
+ },
35
+ ],
36
+ ],
37
+ },
38
+ },
39
+ },
40
+ ],
41
+ },
42
+ plugins: [
43
+ // new BundleAnalyzerPlugin(),
44
+ new webpack.EnvironmentPlugin({
45
+ API_BASE_URL: "https://api.jibb.ai",
46
+ }),
47
+ ],
48
+ externals: { xapi: "xapi" },
49
+ }
50
+
51
+ const nodeConfig = {
52
+ target: "node",
53
+ entry: ["./src/api/index.js"],
54
+ output: {
55
+ filename: "jibb.cjs",
56
+ path: path.resolve(__dirname, "dist/node"),
57
+ globalObject: "globalThis",
58
+ library: {
59
+ name: "JIBB",
60
+ type: "commonjs",
61
+ export: "default",
62
+ },
63
+ },
64
+ module: {
65
+ rules: [
66
+ {
67
+ test: /\.js$/,
68
+ exclude: ["/(node_modules)/", "/utils/http/http.xapi.js"],
69
+ use: {
70
+ loader: "babel-loader",
71
+ options: {
72
+ presets: ["@babel/preset-env"],
73
+ plugins: [
74
+ [
75
+ "babel-plugin-transform-import-ignore",
76
+ {
77
+ patterns: [".webex-devices.js", "*xapi*"],
78
+ },
79
+ ],
80
+ ],
81
+ },
82
+ },
83
+ },
84
+ ],
85
+ },
86
+ externals: { xapi: "xapi" },
87
+ }
88
+
89
+ const webeXapiConfig = {
90
+ mode: "production",
91
+ target: "node",
92
+ entry: ["./src/index.webex-devices.js"],
93
+ resolve: {
94
+ alias: {
95
+ // "@jibb/jibbapis/bundle.js": path.resolve(__dirname, `webex_device_specific/jibbapis_replacment.js`),
96
+ },
97
+ },
98
+ output: {
99
+ filename: "jibb_WebexXapi.js",
100
+ path: path.resolve(__dirname, "dist/webex"),
101
+ globalObject: "global",
102
+ library: {
103
+ name: "JIBB",
104
+ type: "umd",
105
+ export: "default",
106
+ },
107
+ },
108
+ externals: { xapi: "xapi" },
109
+ externalsPresets: {
110
+ node: true, // in order to ignore built-in modules like path, fs, etc.
111
+ },
112
+ module: {
113
+ rules: [
114
+ {
115
+ test: /\.js$/,
116
+ exclude: /(node_modules)/,
117
+ use: {
118
+ loader: "babel-loader",
119
+ options: {
120
+ presets: ["@babel/preset-env"],
121
+ plugins: [
122
+ [
123
+ "babel-plugin-transform-import-ignore",
124
+ {
125
+ patterns: ["*axios*"],
126
+ },
127
+ ],
128
+ ],
129
+ },
130
+ },
131
+ },
132
+ ],
133
+ },
134
+
135
+ plugins: [
136
+ // new BundleAnalyzerPlugin(),
137
+ new webpack.EnvironmentPlugin({
138
+ API_BASE_URL: "https://api.jibb.ai", // use 'development' unless process.env.NODE_ENV is defined
139
+ }),
140
+ ],
141
+ }
142
+
143
+ module.exports = [webConfig, webeXapiConfig, nodeConfig]
144
+