diff --git a/README.md b/README.md index 3b3baddb..94e25e3c 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,7 @@ The data-channel name must be in the `manifest.json` along with all the permissi { "name": "channel-name", "pushPermission": ["moderator","presenter"], - "replaceOrDeletePermission": ["moderator", "sender"] + "replaceOrDeletePermission": ["moderator", "creator"] } ] } diff --git a/package-lock.json b/package-lock.json index 229d1279..41a8d95f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -376,13 +376,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz", - "integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", + "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright": "1.51.1" + "playwright": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -1000,9 +999,9 @@ } }, "node_modules/axios": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", + "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", @@ -3681,13 +3680,12 @@ } }, "node_modules/playwright": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", - "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.51.1" + "playwright-core": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -3700,11 +3698,10 @@ } }, "node_modules/playwright-core": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", - "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", "dev": true, - "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -4328,9 +4325,9 @@ "dev": true }, "node_modules/to-buffer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", - "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", "dev": true, "dependencies": { "isarray": "^2.0.5", diff --git a/samples/sample-actions-bar-plugin/src/sample-actions-bar-plugin/component.tsx b/samples/sample-actions-bar-plugin/src/sample-actions-bar-plugin/component.tsx index c6ea75f4..a04840ca 100644 --- a/samples/sample-actions-bar-plugin/src/sample-actions-bar-plugin/component.tsx +++ b/samples/sample-actions-bar-plugin/src/sample-actions-bar-plugin/component.tsx @@ -7,6 +7,7 @@ import { PluginApi, UsersBasicInfoResponseFromGraphqlWrapper, pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; + import { SampleActionsBarPluginProps } from './types'; function SampleActionsBarPlugin({ diff --git a/samples/sample-data-channel-plugin/manifest.json b/samples/sample-data-channel-plugin/manifest.json index e4431be4..839c2930 100644 --- a/samples/sample-data-channel-plugin/manifest.json +++ b/samples/sample-data-channel-plugin/manifest.json @@ -1,13 +1,25 @@ { "requiredSdkVersion": "~0.0.59", "name": "SampleDataChannelPlugin", + "version": "0.0.8-beta1", "javascriptEntrypointUrl": "SampleDataChannelPlugin.js", "localesBaseUrl": "https://cdn.dominio.com/pluginabc/", - "dataChannels":[ + "loggerSettings": { + "console": { + "level": "error" + } + }, + "dataChannels": [ { "name": "public-channel", - "pushPermission": ["moderator","presenter"], - "replaceOrDeletePermission": ["moderator", "sender"] + "pushPermission": [ + "moderator", + "presenter" + ], + "replaceOrDeletePermission": [ + "moderator", + "creator" + ] } ] } diff --git a/samples/sample-presentation-dropdown-plugin/src/components/sample-presentation-dropdown-plugin/component.tsx b/samples/sample-presentation-dropdown-plugin/src/components/sample-presentation-dropdown-plugin/component.tsx index 923e014a..ebd43927 100644 --- a/samples/sample-presentation-dropdown-plugin/src/components/sample-presentation-dropdown-plugin/component.tsx +++ b/samples/sample-presentation-dropdown-plugin/src/components/sample-presentation-dropdown-plugin/component.tsx @@ -4,10 +4,10 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, - pluginLogger, PresentationDropdownInterface, PresentationDropdownOption, PresentationDropdownSeparator, + pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; import { SamplePresentationDropdownPluginProps } from './types'; diff --git a/samples/sample-screenshare-helper-plugin/src/sample-screenshare-helper-plugin/component.tsx b/samples/sample-screenshare-helper-plugin/src/sample-screenshare-helper-plugin/component.tsx index 14ede133..e72be8f2 100644 --- a/samples/sample-screenshare-helper-plugin/src/sample-screenshare-helper-plugin/component.tsx +++ b/samples/sample-screenshare-helper-plugin/src/sample-screenshare-helper-plugin/component.tsx @@ -4,14 +4,14 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, - pluginLogger, ScreenshareHelperItemPosition, ScreenshareHelperButton, + pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; import { SampleUserCameraDropdownPluginProps } from './types'; function SampleUserCameraDropdownPlugin({ pluginUuid: uuid }: SampleUserCameraDropdownPluginProps): -React.ReactElement { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); diff --git a/samples/sample-ui-events-plugin/src/sample-ui-events-plugin-item/component.tsx b/samples/sample-ui-events-plugin/src/sample-ui-events-plugin-item/component.tsx index 145bd8f3..6eb4fc1f 100644 --- a/samples/sample-ui-events-plugin/src/sample-ui-events-plugin-item/component.tsx +++ b/samples/sample-ui-events-plugin/src/sample-ui-events-plugin-item/component.tsx @@ -9,7 +9,7 @@ import { import { SampleUiEventsPluginProps } from './types'; function SampleUiEventsPlugin({ pluginUuid: uuid }: SampleUiEventsPluginProps): -React.ReactElement { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); const userListOpened = pluginApi diff --git a/samples/sample-use-meeting/src/sample-use-meeting/component.tsx b/samples/sample-use-meeting/src/sample-use-meeting/component.tsx index 1eb33e84..6b2f01cb 100644 --- a/samples/sample-use-meeting/src/sample-use-meeting/component.tsx +++ b/samples/sample-use-meeting/src/sample-use-meeting/component.tsx @@ -7,7 +7,7 @@ import { import { SampleUseMeetingPluginProps } from './types'; function SampleUseMeetingPlugin({ pluginUuid: uuid }: SampleUseMeetingPluginProps): -React.ReactElement { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); const meetingInfoGraphqlResponse = pluginApi.useMeeting(); diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx index 3590e6e1..23189a17 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx @@ -4,15 +4,15 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, - pluginLogger, UserCameraDropdownOption, UserCameraDropdownSeparator, + pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; import { SampleUserCameraDropdownPluginProps, VideoStreamsSubscriptionResultType } from './types'; import { VIDEO_STREAMS_SUBSCRIPTION } from '../queries'; function SampleUserCameraDropdownPlugin({ pluginUuid: uuid }: SampleUserCameraDropdownPluginProps): -React.ReactElement { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); diff --git a/samples/sample-user-camera-helper-plugin/src/sample-user-camera-helper-plugin/component.tsx b/samples/sample-user-camera-helper-plugin/src/sample-user-camera-helper-plugin/component.tsx index c3a63e4d..79c8671c 100644 --- a/samples/sample-user-camera-helper-plugin/src/sample-user-camera-helper-plugin/component.tsx +++ b/samples/sample-user-camera-helper-plugin/src/sample-user-camera-helper-plugin/component.tsx @@ -4,15 +4,15 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, - pluginLogger, UserCameraHelperButton, UserCameraHelperItemPosition, + pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; import { SampleUserCameraHelperPluginProps, VideoStreamsSubscriptionResultType } from './types'; import { VIDEO_STREAMS_SUBSCRIPTION } from '../queries'; function SampleUserCameraHelperPlugin({ pluginUuid: uuid }: SampleUserCameraHelperPluginProps): -React.ReactElement { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); diff --git a/samples/sample-user-list-dropdown-plugin/src/sample-user-list-dropdown-plugin-item/component.tsx b/samples/sample-user-list-dropdown-plugin/src/sample-user-list-dropdown-plugin-item/component.tsx index 62c74a15..92fc84d6 100644 --- a/samples/sample-user-list-dropdown-plugin/src/sample-user-list-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-list-dropdown-plugin/src/sample-user-list-dropdown-plugin-item/component.tsx @@ -4,11 +4,11 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, - pluginLogger, UserListDropdownFixedContentInformation, UserListDropdownInterface, UserListDropdownOption, UserListDropdownSeparator, + pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; import { SampleUserListDropdownPluginProps } from './types'; @@ -21,48 +21,48 @@ function SampleUserListDropdownPlugin({ useEffect(() => { if (loadedUserList !== undefined && loadedUserList.length > 0) { const listOfInformationToSend: - Array = loadedUserList.map( - (user) => { - const buttonToUserListItem: - UserListDropdownInterface = new UserListDropdownFixedContentInformation({ - label: 'Warning test', - iconRight: 'warning', - userId: user.userId, - textColor: 'red', - allowed: true, - }); - return buttonToUserListItem as UserListDropdownInterface; - }, - ); + Array = loadedUserList.map( + (user) => { + const buttonToUserListItem: + UserListDropdownInterface = new UserListDropdownFixedContentInformation({ + label: 'Warning test', + iconRight: 'warning', + userId: user.userId, + textColor: 'red', + allowed: true, + }); + return buttonToUserListItem as UserListDropdownInterface; + }, + ); const listOfOptionsToSend: - Array = loadedUserList.map( - (user) => { - const buttonToUserListItem: - UserListDropdownInterface = new UserListDropdownOption({ - label: 'Click to log something in the console', - icon: 'user', - userId: user.userId, - tooltip: 'This will log something in the console', - allowed: true, - onClick: () => { - pluginLogger.info('Log from sample user-list-dropdown-plugin'); - }, - }); - return buttonToUserListItem as UserListDropdownInterface; - }, - ); + Array = loadedUserList.map( + (user) => { + const buttonToUserListItem: + UserListDropdownInterface = new UserListDropdownOption({ + label: 'Click to log something in the console', + icon: 'user', + userId: user.userId, + tooltip: 'This will log something in the console', + allowed: true, + onClick: () => { + pluginLogger.info('Log from sample user-list-dropdown-plugin'); + }, + }); + return buttonToUserListItem as UserListDropdownInterface; + }, + ); const listOfDropdownsToSend: - Array = loadedUserList.map( - (user) => { - const dropdownToUserListItem: - UserListDropdownInterface = new UserListDropdownSeparator({ - userId: user.userId, - }); - return dropdownToUserListItem as UserListDropdownInterface; - }, - ); + Array = loadedUserList.map( + (user) => { + const dropdownToUserListItem: + UserListDropdownInterface = new UserListDropdownSeparator({ + userId: user.userId, + }); + return dropdownToUserListItem as UserListDropdownInterface; + }, + ); pluginApi.setUserListDropdownItems( [...listOfInformationToSend, ...listOfDropdownsToSend, ...listOfOptionsToSend], ); diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 90d06ded..52bf5f38 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -206,7 +206,6 @@ export abstract class BbbPluginSdk { localesBaseUrl, }; } - return window.bbb_plugins[uuid]; } } diff --git a/src/core/api/types.ts b/src/core/api/types.ts index 48a66821..b34a4b11 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -1,3 +1,4 @@ +import { Logger } from 'browser-bunyan'; import { UiCommands } from '../../ui-commands/types'; import { UseChatMessageDomElementsFunction } from '../../dom-element-manipulation/chat/message/types'; import { ActionButtonDropdownInterface } from '../../extensible-areas/action-button-dropdown-item/types'; @@ -308,6 +309,30 @@ export interface PluginApi { * */ persistEvent?: PersistEventFunction; + /** + * Function used to log in the console. + */ + logger?: Logger; +} + +export interface Console { + enabled: boolean + level: string +} + +export interface External { + enabled: boolean + level: string + url: string + method: string + throttleInterval: number + flushOnClose: boolean + logTag: string +} + +export interface ClientLog { + console: Console + external: External } export interface MeetingClientSettings { @@ -315,6 +340,7 @@ export interface MeetingClientSettings { app: { bbbWebBase: string; } + clientLog: ClientLog; } } diff --git a/src/utils/logger/logger.ts b/src/utils/logger/logger.ts index feb2e4be..4cd498b4 100644 --- a/src/utils/logger/logger.ts +++ b/src/utils/logger/logger.ts @@ -1,7 +1,12 @@ -import { createLogger, INFO, stdSerializers } from 'browser-bunyan'; +import { + createLogger, INFO, stdSerializers, Logger, StreamOptions, +} from 'browser-bunyan'; import { ConsoleFormattedStream } from '@browser-bunyan/console-formatted-stream'; +import { BbbPluginSdk } from '../../core'; -const pluginLogger = createLogger({ +const uuid = document.currentScript?.getAttribute('uuid') || 'root'; + +export const fallbackLogger: Logger = createLogger({ name: 'PluginLogger', streams: [ { @@ -9,9 +14,56 @@ const pluginLogger = createLogger({ stream: new ConsoleFormattedStream(), }, ], - serializers: stdSerializers, src: true, }); +function isValidLogger(obj: unknown): obj is Logger { + return ( + typeof obj === 'object' + && obj !== null + && typeof (obj as Logger).info === 'function' + && typeof (obj as Logger).error === 'function' + ); +} + +function getLogger(): Logger { + try { + const api = BbbPluginSdk.getPluginApi(uuid); + const logger = api?.logger; + + if (isValidLogger(logger)) { + return logger; + } + return fallbackLogger; + } catch (err) { + return fallbackLogger; + } +} + +type LoggerArgument = string | Error | Record; + +function logWith(level: T, ...args: LoggerArgument[]): void { + const logger = getLogger(); + const method = logger[level] as (...params: LoggerArgument[]) => void; + + try { + method.call(logger, ...args); + } catch (err) { + console.error(`[pluginLogger.${String(level)}] fallback`, err, ...args); + } +} + +const pluginLogger = { + error: (...args: LoggerArgument[]) => logWith('error', ...args), + warn: (...args: LoggerArgument[]) => logWith('warn', ...args), + info: (...args: LoggerArgument[]) => logWith('info', ...args), + debug: (...args: LoggerArgument[]) => logWith('debug', ...args), + trace: (...args: LoggerArgument[]) => logWith('trace', ...args), + addStream(stream: StreamOptions) { + const logger = getLogger(); + logger.addStream.call(logger, stream); + }, +} as Logger; + export default pluginLogger;