From 6426fe0708f403cd8f835d2650eb6e0716d1159c Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Wed, 3 Jul 2024 11:12:20 +0200 Subject: [PATCH 1/9] Fix error on muted track renegotiation --- examples/ts-client/simple-app/package.json | 1 - packages/react-client/package.json | 25 ++++----- packages/react-client/src/DeviceManager.ts | 10 ++-- .../react-client/src/ScreenShareManager.ts | 7 ++- packages/react-client/src/types.ts | 2 - packages/ts-client/package.json | 27 ++++++--- packages/ts-client/src/webrtc/bitrate.ts | 22 +++++++- packages/ts-client/src/webrtc/index.ts | 1 + packages/ts-client/src/webrtc/internal.ts | 5 ++ packages/ts-client/src/webrtc/transceivers.ts | 49 ++++++++++++++++ packages/ts-client/src/webrtc/types.ts | 2 + .../ts-client/src/webrtc/webRTCEndpoint.ts | 56 +++++++------------ yarn.lock | 12 +--- 13 files changed, 139 insertions(+), 80 deletions(-) create mode 100644 packages/ts-client/src/webrtc/transceivers.ts diff --git a/examples/ts-client/simple-app/package.json b/examples/ts-client/simple-app/package.json index 711cb668..55eee322 100644 --- a/examples/ts-client/simple-app/package.json +++ b/examples/ts-client/simple-app/package.json @@ -19,7 +19,6 @@ "vite-plugin-checker": "^0.6.4" }, "dependencies": { - "@fishjam-dev/browser-media-utils": "https://github.com/fishjam-dev/browser-media-utils#1.0.0", "@fishjam-dev/ts-client": "*" } } diff --git a/packages/react-client/package.json b/packages/react-client/package.json index a027e680..723ea042 100644 --- a/packages/react-client/package.json +++ b/packages/react-client/package.json @@ -8,23 +8,21 @@ "module": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ - "dist/src" + "dist/**" ], - "bugs": { - "url": "https://github.com/fishjam-dev/react-client-sdk/issues" - }, - "homepage": "https://github.com/fishjam-dev/react-client-sdk#readme", + "repository": "github:fishjam-cloud/web-client-sdk", + "homepage": "https://github.com/fishjam-cloud/web-client-sdk#readme", + "bugs": "https://github.com/fishjam-cloud/web-client-sdk/issues", "keywords": [ "webrtc", "membrane", "fishjam" ], - "repository": { - "type": "git", - "url": "git://github.com/fishjam-dev/react-client-sdk.git" - }, "exports": { - ".": "./dist/index.js" + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } }, "typesVersions": { "*": { @@ -41,7 +39,7 @@ "format:check": "prettier --check . --ignore-path ./.eslintignore", "lint:fix": "eslint . --ext .ts,.tsx --fix", "lint:check": "eslint . --ext .ts,.tsx", - "prepare": "tsc" + "prepack": "yarn workspace @fishjam-dev/ts-client build && yarn build" }, "devDependencies": { "@playwright/test": "^1.42.1", @@ -64,11 +62,12 @@ "typescript": "^5.4.0" }, "dependencies": { - "@fishjam-dev/ts-client": "*", + "@fishjam-dev/ts-client": "workspace:*", "events": "3.3.0", "lodash.isequal": "4.5.0" }, "directories": { "example": "examples" - } + }, + "packageManager": "yarn@4.3.0" } diff --git a/packages/react-client/src/DeviceManager.ts b/packages/react-client/src/DeviceManager.ts index 478c5b4a..f78427d7 100644 --- a/packages/react-client/src/DeviceManager.ts +++ b/packages/react-client/src/DeviceManager.ts @@ -1,5 +1,4 @@ import type { - AudioOrVideoType, CurrentDevices, DeviceError, DeviceManagerConfig, @@ -25,6 +24,7 @@ import { import EventEmitter from "events"; import type TypedEmitter from "typed-emitter"; import type { TrackType } from "./ScreenShareManager"; +import { TrackKind } from "@fishjam-dev/ts-client"; const removeExact = ( trackConstraints: boolean | MediaTrackConstraints | undefined, @@ -164,7 +164,7 @@ const handleNotAllowedError = async (constraints: MediaStreamConstraints): Promi return await getMedia({ video: false, audio: false }, { video: PERMISSION_DENIED, audio: PERMISSION_DENIED }); }; -const getError = (result: GetMedia, type: AudioOrVideoType): DeviceError | null => { +const getError = (result: GetMedia, type: TrackKind): DeviceError | null => { if (result.type === "OK") { return result.previousErrors[type] || null; } @@ -477,7 +477,7 @@ export class DeviceManager extends (EventEmitter as new () => TypedEmitter { + private onTrackEnded = async (type: TrackKind, trackId: string) => { if (trackId === this?.[type].media?.track?.id) { await this.stop(type); } @@ -637,14 +637,14 @@ export class DeviceManager extends (EventEmitter as new () => TypedEmitter TypedEmitter< } } - private onTrackEnded = async (type: AudioOrVideoType, trackId: string) => { + private onTrackEnded = async (type: TrackKind, trackId: string) => { const mediaType = type === "video" ? "videoMedia" : "audioMedia"; if (trackId === this?.data[mediaType]?.track?.id) { await this.stop("audiovideo"); diff --git a/packages/react-client/src/types.ts b/packages/react-client/src/types.ts index 13c357c5..08b213e7 100644 --- a/packages/react-client/src/types.ts +++ b/packages/react-client/src/types.ts @@ -4,8 +4,6 @@ import type { PeerStatus, Selector, State, Track, TrackId, TrackWithOrigin, UseR import type { JSX, ReactNode } from "react"; import type { Client } from "./Client"; -export type AudioOrVideoType = "audio" | "video"; - export type DevicesStatus = "OK" | "Error" | "Not requested" | "Requesting"; export type MediaStatus = "OK" | "Error" | "Not requested" | "Requesting"; diff --git a/packages/ts-client/package.json b/packages/ts-client/package.json index 54c5a3b8..645b865e 100644 --- a/packages/ts-client/package.json +++ b/packages/ts-client/package.json @@ -4,9 +4,9 @@ "description": "Typescript client library for Fishjam", "license": "Apache-2.0", "author": "Software Mansion (https://swmansion.com)", - "repository": "github:fishjam-dev/ts-client-sdk", - "homepage": "https://github.com/fishjam-dev/ts-client-sdk#readme", - "bugs": "https://github.com/fishjam-dev/ts-client-sdk/issues", + "repository": "github:fishjam-cloud/web-client-sdk", + "homepage": "https://github.com/fishjam-cloud/web-client-sdk#readme", + "bugs": "https://github.com/fishjam-cloud/web-client-sdk/issues", "keywords": [ "webrtc", "membrane", @@ -15,10 +15,21 @@ "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts", "files": [ - "dist/src" + "dist/src/**" ], "exports": { - ".": "./dist/src/index.js" + ".": { + "import": "./dist/src/index.js", + "types": "./dist/src/index.d.ts" + }, + "./protos": { + "import": "./dist/src/protos/index.js", + "types": "./dist/src/protos/index.d.ts" + }, + "./webrtc": { + "import": "./dist/src/webrtc/index.js", + "types": "./dist/src/webrtc/index.d.ts" + } }, "scripts": { "build": "tsc", @@ -32,7 +43,8 @@ "test": "vitest run tests/**", "test:e2e": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test", "test:coverage": "vitest run tests/** --coverage", - "prepare": "tsc" + "prepare": "tsc", + "prepack": "yarn build" }, "dependencies": { "events": "^3.3.0", @@ -73,5 +85,6 @@ "*.(js|ts|tsx)": [ "npm run lint:check" ] - } + }, + "packageManager": "yarn@4.3.0" } diff --git a/packages/ts-client/src/webrtc/bitrate.ts b/packages/ts-client/src/webrtc/bitrate.ts index 30e59b98..edc753b8 100644 --- a/packages/ts-client/src/webrtc/bitrate.ts +++ b/packages/ts-client/src/webrtc/bitrate.ts @@ -3,6 +3,7 @@ import { RemoteTrackId, TrackContext, TrackEncoding, + TrackKind, } from './types'; import { TrackContextImpl } from './internal'; import { findSender } from './RTCPeerConnectionUtils'; @@ -73,6 +74,9 @@ export const getTrackIdToTrackBitrates = ( return trackIdToTrackBitrates; }; +const isNotSimulcastTrack = (encodings: RTCRtpEncodingParameters[]) => + encodings.length === 1 && !encodings[0].rid; + export const getTrackBitrates = ( connection: RTCPeerConnection | undefined, localTrackIdToTrack: Map< @@ -84,16 +88,28 @@ export const getTrackBitrates = ( const trackContext = localTrackIdToTrack.get(trackId); if (!trackContext) throw "Track with id ${trackId} not present in 'localTrackIdToTrack'"; - const kind = trackContext.track?.kind as 'audio' | 'video' | undefined; + + const kind = trackContext.track?.kind as TrackKind | undefined; + + if (!trackContext.track) { + if (!trackContext.trackKind) { + throw new Error('trackContext.trackKind is empty'); + } + + return defaultBitrates[trackContext.trackKind]; + } + const sender = findSender(connection, trackContext.track!.id); const encodings = sender.getParameters().encodings; - if (encodings.length == 1 && !encodings[0].rid) + if (isNotSimulcastTrack(encodings)) { return ( encodings[0].maxBitrate || (kind ? defaultBitrates[kind] : UNLIMITED_BANDWIDTH) ); - else if (kind == 'audio') throw 'Audio track cannot have multiple encodings'; + } else if (kind === 'audio') { + throw 'Audio track cannot have multiple encodings'; + } const bitrates: Record = {}; diff --git a/packages/ts-client/src/webrtc/index.ts b/packages/ts-client/src/webrtc/index.ts index dd54cd7c..bf0d9c71 100644 --- a/packages/ts-client/src/webrtc/index.ts +++ b/packages/ts-client/src/webrtc/index.ts @@ -12,6 +12,7 @@ export type { EncodingReason, Config, MetadataParser, + TrackKind } from './types'; export { WebRTCEndpoint } from './webRTCEndpoint'; diff --git a/packages/ts-client/src/webrtc/internal.ts b/packages/ts-client/src/webrtc/internal.ts index cf00586f..0604b7b5 100644 --- a/packages/ts-client/src/webrtc/internal.ts +++ b/packages/ts-client/src/webrtc/internal.ts @@ -9,10 +9,14 @@ import { TrackContext, TrackContextEvents, TrackEncoding, + TrackKind, TrackNegotiationStatus, VadStatus, } from './types'; +export const isTrackKind = (kind: string): kind is TrackKind => + kind === 'audio' || kind === 'video'; + export class TrackContextImpl extends (EventEmitter as { new (): TypedEmitter< @@ -24,6 +28,7 @@ export class TrackContextImpl endpoint: Endpoint; trackId: string; track: MediaStreamTrack | null = null; + trackKind: TrackKind | null = null; stream: MediaStream | null = null; metadata?: ParsedMetadata; rawMetadata: any; diff --git a/packages/ts-client/src/webrtc/transceivers.ts b/packages/ts-client/src/webrtc/transceivers.ts new file mode 100644 index 00000000..8d0af4b6 --- /dev/null +++ b/packages/ts-client/src/webrtc/transceivers.ts @@ -0,0 +1,49 @@ +import { EndpointWithTrackContext, TrackContextImpl } from "./internal"; +import { RemoteTrackId } from "./types"; + +export const getMidToTrackId = ( + connection: RTCPeerConnection | undefined, + localTrackIdToTrack: Map>, + midToTrackId: Map = new Map(), + localEndpoint: EndpointWithTrackContext, +): Record | null => { + if (!connection) return null; + + const active = getActive(connection, localTrackIdToTrack) + const muted = getMuted(midToTrackId, localEndpoint) + + return { ...active, ...muted }; +}; + +export const getActive = ( + connection: RTCPeerConnection, + localTrackIdToTrack: Map>, +): Record | null => + connection.getTransceivers() + .filter((transceiver) => transceiver.sender.track?.id && transceiver.mid) + .reduce((acc, transceiver) => { + const localTrackId = transceiver.sender.track!.id; + const mid = transceiver!.mid!; + + const trackContext = Array.from(localTrackIdToTrack.values()).find( + (trackContext) => trackContext?.track?.id === localTrackId, + )!; + + acc[mid] = trackContext.trackId; + + return acc + }, {} as Record); + + +export const getMuted = ( + midToTrackId: Map = new Map(), + localEndpoint: EndpointWithTrackContext, +): Record => { + return [...midToTrackId.entries()] + .filter(([_mid, trackId]) => localEndpoint.tracks.get(trackId)) + .reduce((acc, [mid, trackId]) => { + acc[mid] = trackId; + + return acc + }, {} as Record); +} diff --git a/packages/ts-client/src/webrtc/types.ts b/packages/ts-client/src/webrtc/types.ts index 0c7af5ef..51615009 100644 --- a/packages/ts-client/src/webrtc/types.ts +++ b/packages/ts-client/src/webrtc/types.ts @@ -7,6 +7,8 @@ export type MetadataParser = ( export type LocalTrackId = string; export type RemoteTrackId = string; +export type TrackKind = 'audio' | 'video'; + /** * Type describing Voice Activity Detection statuses. * diff --git a/packages/ts-client/src/webrtc/webRTCEndpoint.ts b/packages/ts-client/src/webrtc/webRTCEndpoint.ts index cd1ca7a2..58329ffa 100644 --- a/packages/ts-client/src/webrtc/webRTCEndpoint.ts +++ b/packages/ts-client/src/webrtc/webRTCEndpoint.ts @@ -10,12 +10,7 @@ import { v4 as uuidv4 } from 'uuid'; import EventEmitter from 'events'; import TypedEmitter from 'typed-emitter'; import { simulcastTransceiverConfig } from './const'; -import { - AddTrackCommand, - Command, - RemoveTrackCommand, - ReplaceTackCommand, -} from './commands'; +import { AddTrackCommand, Command, RemoveTrackCommand, ReplaceTackCommand, } from './commands'; import { Deferred } from './deferred'; import { BandwidthLimit, @@ -29,14 +24,11 @@ import { TrackEncoding, WebRTCEndpointEvents, } from './types'; -import { EndpointWithTrackContext, TrackContextImpl } from './internal'; +import { EndpointWithTrackContext, isTrackKind, TrackContextImpl } from './internal'; import { handleVoiceActivationDetectionNotification } from './voiceActivityDetection'; import { applyBandwidthLimitation } from './bandwidth'; -import { - createTrackVariantBitratesEvent, - getTrackBitrates, - getTrackIdToTrackBitrates, -} from './bitrate'; +import { createTrackVariantBitratesEvent, getTrackBitrates, getTrackIdToTrackBitrates, } from './bitrate'; +import { getMidToTrackId } from "./transceivers"; /** * Main class that is responsible for connecting to the RTC Engine, sending and receiving media. @@ -45,7 +37,7 @@ export class WebRTCEndpoint< EndpointMetadata = any, TrackMetadata = any, > extends (EventEmitter as { - new (): TypedEmitter< + new(): TypedEmitter< Required> >; }) { @@ -727,9 +719,12 @@ export class WebRTCEndpoint< this.trackMetadataParser, ); + if (!isTrackKind(track.kind)) throw new Error("Track has no kind") + trackContext.track = track; trackContext.stream = stream; trackContext.maxBandwidth = maxBandwidth; + trackContext.trackKind = track.kind; this.localEndpoint.tracks.set(trackId, trackContext); @@ -913,6 +908,8 @@ export class WebRTCEndpoint< ) { const { trackId, newTrack, newTrackMetadata } = command; + // todo add validation to track.kind, you cannot replace video with audio + const trackContext = this.localTrackIdToTrack.get(trackId)!; const track = this.trackIdToSender.get(trackId); @@ -943,8 +940,6 @@ export class WebRTCEndpoint< this.emit('localTrackUnmuted', { trackId: trackId }); } - trackContext.track = newTrack; - track.localTrackId = newTrack?.id ?? null; try { @@ -1311,23 +1306,6 @@ export class WebRTCEndpoint< } }; - private getMidToTrackId = (): Record | null => { - const localTrackMidToTrackId: Record = {}; - - if (!this.connection) return null; - this.connection.getTransceivers().forEach((transceiver) => { - const localTrackId = transceiver.sender.track?.id; - const mid = transceiver.mid; - if (localTrackId && mid) { - const trackContext = Array.from(this.localTrackIdToTrack.values()).find( - (trackContext) => trackContext!.track!.id === localTrackId, - )!; - localTrackMidToTrackId[mid] = trackContext.trackId; - } - }); - return localTrackMidToTrackId; - }; - /** * Disconnects from the room. This function should be called when user disconnects from the room * in a clean way e.g. by clicking a dedicated, custom button `disconnect`. @@ -1441,7 +1419,12 @@ export class WebRTCEndpoint< this.localTrackIdToTrack, this.localEndpoint.tracks, ), - midToTrackId: this.getMidToTrackId(), + midToTrackId: getMidToTrackId( + this.connection, + this.localTrackIdToTrack, + this.midToTrackId, + this.localEndpoint + ), }, }); this.sendMediaEvent(mediaEvent); @@ -1471,9 +1454,7 @@ export class WebRTCEndpoint< trackId: string, endpoint: EndpointWithTrackContext, ) => - Array.from(endpoint.tracks.keys()).some((track) => - trackId.startsWith(track), - ); + Array.from(endpoint.tracks.keys()).some((track) => trackId.startsWith(track)); private onOfferData = async (offerData: MediaEvent) => { if (!this.connection) { @@ -1607,13 +1588,16 @@ export class WebRTCEndpoint< const mid = event.transceiver.mid!; const trackId = this.midToTrackId.get(mid)!; + if (this.checkIfTrackBelongToEndpoint(trackId, this.localEndpoint)) return; + if (!isTrackKind(event.track.kind)) throw new Error("Track has no kind") const trackContext = this.trackIdToTrack.get(trackId)!; trackContext.stream = stream; trackContext.track = event.track; + trackContext.trackKind = event.track.kind; this.idToEndpoint .get(trackContext.endpoint.id) diff --git a/yarn.lock b/yarn.lock index b8812f60..d005a29d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -490,18 +490,11 @@ __metadata: languageName: node linkType: hard -"@fishjam-dev/browser-media-utils@https://github.com/fishjam-dev/browser-media-utils#1.0.0": - version: 0.0.1 - resolution: "@fishjam-dev/browser-media-utils@https://github.com/fishjam-dev/browser-media-utils.git#commit=86841c9962ddfa8263d846005906aa19bde16572" - checksum: 10c0/6d5bce6165f47d1fac58ae4dc564a0c1c6343eae935ff0299d4c95ecbf0026d2d4679ab988cf486e162a4fc91c6de35a669d78b0c30b35817d3bb280d5007a6f - languageName: node - linkType: hard - "@fishjam-dev/react-client@npm:*, @fishjam-dev/react-client@workspace:packages/react-client": version: 0.0.0-use.local resolution: "@fishjam-dev/react-client@workspace:packages/react-client" dependencies: - "@fishjam-dev/ts-client": "npm:*" + "@fishjam-dev/ts-client": "workspace:*" "@playwright/test": "npm:^1.42.1" "@types/events": "npm:^3.0.3" "@types/lodash.isequal": "npm:^4.5.8" @@ -525,7 +518,7 @@ __metadata: languageName: unknown linkType: soft -"@fishjam-dev/ts-client@npm:*, @fishjam-dev/ts-client@workspace:packages/ts-client": +"@fishjam-dev/ts-client@npm:*, @fishjam-dev/ts-client@workspace:*, @fishjam-dev/ts-client@workspace:packages/ts-client": version: 0.0.0-use.local resolution: "@fishjam-dev/ts-client@workspace:packages/ts-client" dependencies: @@ -4520,7 +4513,6 @@ __metadata: version: 0.0.0-use.local resolution: "simple-app-example@workspace:examples/ts-client/simple-app" dependencies: - "@fishjam-dev/browser-media-utils": "https://github.com/fishjam-dev/browser-media-utils#1.0.0" "@fishjam-dev/ts-client": "npm:*" autoprefixer: "npm:^10.4.17" daisyui: "npm:^4.7.2" From 8da58bcb2bc333f7f242782120f58173232e6768 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 4 Jul 2024 13:29:20 +0200 Subject: [PATCH 2/9] Change names and add comments --- packages/react-client/src/DeviceManager.ts | 18 ++++----- .../react-client/src/ScreenShareManager.ts | 4 +- packages/ts-client/src/webrtc/transceivers.ts | 38 ++++++++++++------- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/packages/react-client/src/DeviceManager.ts b/packages/react-client/src/DeviceManager.ts index f78427d7..d5df1522 100644 --- a/packages/react-client/src/DeviceManager.ts +++ b/packages/react-client/src/DeviceManager.ts @@ -164,9 +164,9 @@ const handleNotAllowedError = async (constraints: MediaStreamConstraints): Promi return await getMedia({ video: false, audio: false }, { video: PERMISSION_DENIED, audio: PERMISSION_DENIED }); }; -const getError = (result: GetMedia, type: TrackKind): DeviceError | null => { +const getError = (result: GetMedia, kind: TrackKind): DeviceError | null => { if (result.type === "OK") { - return result.previousErrors[type] || null; + return result.previousErrors[kind] || null; } console.warn({ name: "Unhandled DeviceManager error", result }); @@ -477,9 +477,9 @@ export class DeviceManager extends (EventEmitter as new () => TypedEmitter { - if (trackId === this?.[type].media?.track?.id) { - await this.stop(type); + private onTrackEnded = async (kind: TrackKind, trackId: string) => { + if (trackId === this?.[kind].media?.track?.id) { + await this.stop(kind); } }; @@ -637,11 +637,11 @@ export class DeviceManager extends (EventEmitter as new () => TypedEmitter TypedEmitter< } } - private onTrackEnded = async (type: TrackKind, trackId: string) => { - const mediaType = type === "video" ? "videoMedia" : "audioMedia"; + private onTrackEnded = async (kind: TrackKind, trackId: string) => { + const mediaType = kind === "video" ? "videoMedia" : "audioMedia"; if (trackId === this?.data[mediaType]?.track?.id) { await this.stop("audiovideo"); } diff --git a/packages/ts-client/src/webrtc/transceivers.ts b/packages/ts-client/src/webrtc/transceivers.ts index 8d0af4b6..55c24b4a 100644 --- a/packages/ts-client/src/webrtc/transceivers.ts +++ b/packages/ts-client/src/webrtc/transceivers.ts @@ -1,49 +1,59 @@ import { EndpointWithTrackContext, TrackContextImpl } from "./internal"; import { RemoteTrackId } from "./types"; +type Mid = string +type TrackId = string; +type MidToTrackId = Record + export const getMidToTrackId = ( connection: RTCPeerConnection | undefined, localTrackIdToTrack: Map>, midToTrackId: Map = new Map(), localEndpoint: EndpointWithTrackContext, -): Record | null => { +): MidToTrackId | null => { if (!connection) return null; - const active = getActive(connection, localTrackIdToTrack) - const muted = getMuted(midToTrackId, localEndpoint) + // - negotiated unmuted tracks: tracks added in previous negotiation, data is being transmitted + // - not yet negotiated tracks: tracks added in this negotiation, data will be transmitted after successful negotiation + const transceiver = getTransceiverMapping(connection, localTrackIdToTrack) + + // - negotiated unmuted tracks: tracks added in previous negotiation, data is being transmitted + // - negotiated muted tracks: tracks added in previous negotiation, data is not being transmitted but can be transmitted in the future + const allNegotiated = getAllNegotiatedLocalTracksMapping(midToTrackId, localEndpoint) - return { ...active, ...muted }; + return { ...transceiver, ...allNegotiated }; }; -export const getActive = ( +const getTrackContext = (localTrackIdToTrack: Map>, localTrackId: string) => Array.from(localTrackIdToTrack.values()).find( + (trackContext) => trackContext?.track?.id === localTrackId, +)!; + +const getTransceiverMapping = ( connection: RTCPeerConnection, localTrackIdToTrack: Map>, -): Record | null => +): MidToTrackId => connection.getTransceivers() .filter((transceiver) => transceiver.sender.track?.id && transceiver.mid) .reduce((acc, transceiver) => { const localTrackId = transceiver.sender.track!.id; const mid = transceiver!.mid!; - const trackContext = Array.from(localTrackIdToTrack.values()).find( - (trackContext) => trackContext?.track?.id === localTrackId, - )!; + const trackContext = getTrackContext(localTrackIdToTrack, localTrackId); acc[mid] = trackContext.trackId; return acc - }, {} as Record); - + }, {} as Record); -export const getMuted = ( +const getAllNegotiatedLocalTracksMapping = ( midToTrackId: Map = new Map(), localEndpoint: EndpointWithTrackContext, -): Record => { +): MidToTrackId => { return [...midToTrackId.entries()] .filter(([_mid, trackId]) => localEndpoint.tracks.get(trackId)) .reduce((acc, [mid, trackId]) => { acc[mid] = trackId; return acc - }, {} as Record); + }, {} as Record); } From 35f3abeb9fe87cfc4c4c01d4ca91c6fe2d783362 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 4 Jul 2024 15:43:47 +0200 Subject: [PATCH 3/9] Merge with main --- .github/workflows/node.yaml | 11 +- .github/workflows/playwright.yaml | 18 +- .gitignore | 3 + e2e-tests/react-client/app/.gitignore | 1 + e2e-tests/react-client/app/package.json | 20 + .../react-client/app/playwright.config.ts | 68 ++ .../react-client/docker-compose-test.yaml | 2 +- .../react-client/scenarios}/fishjam.spec.ts | 0 .../react-client/scenarios}/utils.ts | 0 .../react-client/setup}/globalSetupState.ts | 0 .../react-client}/setup/setupFishjam.ts | 12 +- .../react-client/setup}/teardownFishjam.ts | 0 .../ts-client/app/.gitignore | 0 .../ts-client/app/compile_proto.sh | 0 .../ts-client/app/index.html | 0 .../ts-client/app/package.json | 9 +- .../ts-client/app}/playwright.config.ts | 44 +- .../ts-client/app/src/App.tsx | 0 .../ts-client/app/src/MockComponent.tsx | 0 .../ts-client/app/src/MuteTrackTest.tsx | 2 +- .../ts-client/app/src/VideoPlayer.tsx | 0 .../app/src/VideoPlayerWithDetector.tsx | 0 .../ts-client/app/src/main.tsx | 0 .../ts-client/app/src/mocks.ts | 0 .../ts-client/app/src/vite-env.d.ts | 0 e2e-tests/ts-client/app/tsconfig.json | 24 + .../ts-client/app/tsconfig.node.json | 0 .../ts-client/app/vite.config.ts | 0 .../ts-client/docker-compose-test.yaml | 2 +- .../ts-client/scenarios/basic.spec.ts | 0 .../scenarios/metadataParsing.spec.ts | 0 .../ts-client/scenarios/raceCondition.spec.ts | 0 .../ts-client/scenarios/replaceTrack.spec.ts | 0 .../ts-client/scenarios/utils.ts | 0 .../ts-client/setup/globalSetupState.ts | 0 e2e-tests/ts-client/setup/setupFishjam.ts | 23 + .../ts-client/setup/teardownFishjam.ts | 0 e2e_tests/react-client/setupFishjam.ts | 19 - e2e_tests/ts-client/app/tsconfig.json | 7 - .../react-client/minimal-react/package.json | 2 +- examples/ts-client/minimal/package.json | 2 +- examples/ts-client/simple-app/package.json | 2 +- package.json | 7 +- yarn.lock | 1086 ++++++++++++++++- 44 files changed, 1211 insertions(+), 153 deletions(-) create mode 100644 e2e-tests/react-client/app/.gitignore create mode 100644 e2e-tests/react-client/app/package.json create mode 100644 e2e-tests/react-client/app/playwright.config.ts rename {e2e_tests => e2e-tests}/react-client/docker-compose-test.yaml (91%) rename {e2e_tests/react-client => e2e-tests/react-client/scenarios}/fishjam.spec.ts (100%) rename {e2e_tests/react-client => e2e-tests/react-client/scenarios}/utils.ts (100%) rename {e2e_tests/react-client => e2e-tests/react-client/setup}/globalSetupState.ts (100%) rename {e2e_tests/ts-client => e2e-tests/react-client}/setup/setupFishjam.ts (67%) rename {e2e_tests/react-client => e2e-tests/react-client/setup}/teardownFishjam.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/app/.gitignore (100%) rename {e2e_tests => e2e-tests}/ts-client/app/compile_proto.sh (100%) rename {e2e_tests => e2e-tests}/ts-client/app/index.html (100%) rename {e2e_tests => e2e-tests}/ts-client/app/package.json (74%) rename {packages/ts-client => e2e-tests/ts-client/app}/playwright.config.ts (66%) rename {e2e_tests => e2e-tests}/ts-client/app/src/App.tsx (100%) rename {e2e_tests => e2e-tests}/ts-client/app/src/MockComponent.tsx (100%) rename {e2e_tests => e2e-tests}/ts-client/app/src/MuteTrackTest.tsx (97%) rename {e2e_tests => e2e-tests}/ts-client/app/src/VideoPlayer.tsx (100%) rename {e2e_tests => e2e-tests}/ts-client/app/src/VideoPlayerWithDetector.tsx (100%) rename {e2e_tests => e2e-tests}/ts-client/app/src/main.tsx (100%) rename {e2e_tests => e2e-tests}/ts-client/app/src/mocks.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/app/src/vite-env.d.ts (100%) create mode 100644 e2e-tests/ts-client/app/tsconfig.json rename {e2e_tests => e2e-tests}/ts-client/app/tsconfig.node.json (100%) rename {e2e_tests => e2e-tests}/ts-client/app/vite.config.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/docker-compose-test.yaml (91%) rename {e2e_tests => e2e-tests}/ts-client/scenarios/basic.spec.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/scenarios/metadataParsing.spec.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/scenarios/raceCondition.spec.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/scenarios/replaceTrack.spec.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/scenarios/utils.ts (100%) rename {e2e_tests => e2e-tests}/ts-client/setup/globalSetupState.ts (100%) create mode 100644 e2e-tests/ts-client/setup/setupFishjam.ts rename {e2e_tests => e2e-tests}/ts-client/setup/teardownFishjam.ts (100%) delete mode 100644 e2e_tests/react-client/setupFishjam.ts delete mode 100644 e2e_tests/ts-client/app/tsconfig.json diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index a7767e96..1b95611a 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -9,12 +9,12 @@ on: jobs: build_and_test_lib: - name: Build and test + name: Build, check formatting, check linting runs-on: ubuntu-latest strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - uses: actions/checkout@v4 @@ -26,14 +26,11 @@ jobs: cache: 'npm' - name: Install dependencies โฌ‡๏ธ - run: yarn - + run: yarn --frozen-lockfile + - name: Build ๐Ÿ“ฆ run: yarn build - - name: Run types ๐Ÿ‘ฎ - run: yarn tsc - - name: Check formatting ๐ŸŽจ run: yarn format:check diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml index eac6b12a..601fb701 100644 --- a/.github/workflows/playwright.yaml +++ b/.github/workflows/playwright.yaml @@ -17,20 +17,20 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 + cache: npm - - name: Install SDK - run: npm ci + - name: Install dependencies โฌ‡๏ธ + run: yarn --immutable - - name: Install E2E dependencies - run: npm ci - working-directory: e2e/app + - name: Build ๐Ÿ“ฆ + run: yarn build - - name: Install Playwright Browsers + - name: Install Playwright Browsers ๐Ÿงญ run: npx playwright install --with-deps - - name: Run Playwright tests - run: npm run test:e2e + - name: Run Playwright tests ๐Ÿงช + run: yarn test:e2e - uses: actions/upload-artifact@v4 if: always() diff --git a/.gitignore b/.gitignore index accd19ad..ad241985 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ docs # MacOS .DS_Store + +# Playwright +playwright-report diff --git a/e2e-tests/react-client/app/.gitignore b/e2e-tests/react-client/app/.gitignore new file mode 100644 index 00000000..12b46b84 --- /dev/null +++ b/e2e-tests/react-client/app/.gitignore @@ -0,0 +1 @@ +/test-results/ diff --git a/e2e-tests/react-client/app/package.json b/e2e-tests/react-client/app/package.json new file mode 100644 index 00000000..f82ad1e3 --- /dev/null +++ b/e2e-tests/react-client/app/package.json @@ -0,0 +1,20 @@ +{ + "name": "@fishjam-e2e/react-client-e2e", + "private": true, + "version": "0.0.0", + "type": "module", + "license": "Apache-2.0", + "scripts": { + "e2e": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test", + "e2e:ui": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test --ui" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@types/node": "^20.11.18", + "@vitest/coverage-v8": "^1.6.0", + "testcontainers": "^10.3.2", + "typescript": "^5.4.5", + "vite": "^5.1.2", + "vitest": "^1.6.0" + } +} diff --git a/e2e-tests/react-client/app/playwright.config.ts b/e2e-tests/react-client/app/playwright.config.ts new file mode 100644 index 00000000..e722a51e --- /dev/null +++ b/e2e-tests/react-client/app/playwright.config.ts @@ -0,0 +1,68 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: '../.', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [ + ['list'], + ['html', { outputFolder: '../../../playwright-report/react-client-e2e', open: "never" }] + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:3007', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + extraHTTPHeaders: { + Authorization: 'Bearer development', + }, + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + launchOptions: { + args: [ + '--use-fake-ui-for-media-stream', + '--use-fake-device-for-media-stream', + ], + // default Google Chrome path on MacOS + // executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", + }, + }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'yarn run dev', + url: 'http://localhost:3007', + reuseExistingServer: !process.env.CI, + cwd: "../../../examples/react-client/minimal-react", + }, + + globalSetup: '../setup/setupFishjam', + globalTeardown: '../setup/teardownFishjam', +}); diff --git a/e2e_tests/react-client/docker-compose-test.yaml b/e2e-tests/react-client/docker-compose-test.yaml similarity index 91% rename from e2e_tests/react-client/docker-compose-test.yaml rename to e2e-tests/react-client/docker-compose-test.yaml index 3328f32d..bcc8eecf 100644 --- a/e2e_tests/react-client/docker-compose-test.yaml +++ b/e2e-tests/react-client/docker-compose-test.yaml @@ -2,7 +2,7 @@ version: "3" services: fishjam: - image: "ghcr.io/fishjam-dev/fishjam:${FISHJAM_VERSION:-0.6.2}" + image: "ghcr.io/fishjam-dev/fishjam:${FISHJAM_VERSION:-0.6.3}" container_name: fishjam restart: on-failure healthcheck: diff --git a/e2e_tests/react-client/fishjam.spec.ts b/e2e-tests/react-client/scenarios/fishjam.spec.ts similarity index 100% rename from e2e_tests/react-client/fishjam.spec.ts rename to e2e-tests/react-client/scenarios/fishjam.spec.ts diff --git a/e2e_tests/react-client/utils.ts b/e2e-tests/react-client/scenarios/utils.ts similarity index 100% rename from e2e_tests/react-client/utils.ts rename to e2e-tests/react-client/scenarios/utils.ts diff --git a/e2e_tests/react-client/globalSetupState.ts b/e2e-tests/react-client/setup/globalSetupState.ts similarity index 100% rename from e2e_tests/react-client/globalSetupState.ts rename to e2e-tests/react-client/setup/globalSetupState.ts diff --git a/e2e_tests/ts-client/setup/setupFishjam.ts b/e2e-tests/react-client/setup/setupFishjam.ts similarity index 67% rename from e2e_tests/ts-client/setup/setupFishjam.ts rename to e2e-tests/react-client/setup/setupFishjam.ts index 1e42c2e6..3ac876cc 100644 --- a/e2e_tests/ts-client/setup/setupFishjam.ts +++ b/e2e-tests/react-client/setup/setupFishjam.ts @@ -1,4 +1,4 @@ -import { Wait, DockerComposeEnvironment } from 'testcontainers'; +import { DockerComposeEnvironment, Wait } from 'testcontainers'; import { setupState } from './globalSetupState'; import { type NetworkInterfaceInfo, networkInterfaces } from 'os'; @@ -6,14 +6,12 @@ export default async function setupFishjam() { const EXTERNAL_IP = Object.values(networkInterfaces()) .flat() .filter((x): x is NetworkInterfaceInfo => x !== undefined) - .filter(({ family }) => - typeof family === 'string' ? family === 'IPv4' : family === 4, - ) + .filter(({ family }) => family === 'IPv4') .filter(({ internal }) => !internal) .map(({ address }) => address)[0]; - const container = await new DockerComposeEnvironment( - 'e2e', + setupState.fishjamContainer = await new DockerComposeEnvironment( + '../.', 'docker-compose-test.yaml', ) .withEnvironment({ EXTERNAL_IP }) @@ -22,6 +20,4 @@ export default async function setupFishjam() { Wait.forLogMessage('Access FishjamWeb.Endpoint at'), ) .up(); - - setupState.fishjamContainer = container; } diff --git a/e2e_tests/react-client/teardownFishjam.ts b/e2e-tests/react-client/setup/teardownFishjam.ts similarity index 100% rename from e2e_tests/react-client/teardownFishjam.ts rename to e2e-tests/react-client/setup/teardownFishjam.ts diff --git a/e2e_tests/ts-client/app/.gitignore b/e2e-tests/ts-client/app/.gitignore similarity index 100% rename from e2e_tests/ts-client/app/.gitignore rename to e2e-tests/ts-client/app/.gitignore diff --git a/e2e_tests/ts-client/app/compile_proto.sh b/e2e-tests/ts-client/app/compile_proto.sh similarity index 100% rename from e2e_tests/ts-client/app/compile_proto.sh rename to e2e-tests/ts-client/app/compile_proto.sh diff --git a/e2e_tests/ts-client/app/index.html b/e2e-tests/ts-client/app/index.html similarity index 100% rename from e2e_tests/ts-client/app/index.html rename to e2e-tests/ts-client/app/index.html diff --git a/e2e_tests/ts-client/app/package.json b/e2e-tests/ts-client/app/package.json similarity index 74% rename from e2e_tests/ts-client/app/package.json rename to e2e-tests/ts-client/app/package.json index 41ee7e3c..8934da96 100644 --- a/e2e_tests/ts-client/app/package.json +++ b/e2e-tests/ts-client/app/package.json @@ -1,5 +1,5 @@ { - "name": "example", + "name": "@fishjam-e2e/ts-client-e2e", "private": true, "version": "0.0.0", "type": "module", @@ -8,6 +8,8 @@ "dev": "vite", "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "e2e": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test", + "e2e:ui": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test --ui", "preview": "vite preview" }, "dependencies": { @@ -24,11 +26,14 @@ "@typescript-eslint/eslint-plugin": "^7.0.1", "@typescript-eslint/parser": "^7.0.1", "@vitejs/plugin-react": "^4.2.1", + "@vitest/coverage-v8": "^1.6.0", "eslint": "^8.56.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", + "testcontainers": "^10.3.2", "ts-proto": "^1.176.0", "typescript": "^5.4.5", - "vite": "^5.1.2" + "vite": "^5.1.2", + "vitest": "^1.6.0" } } diff --git a/packages/ts-client/playwright.config.ts b/e2e-tests/ts-client/app/playwright.config.ts similarity index 66% rename from packages/ts-client/playwright.config.ts rename to e2e-tests/ts-client/app/playwright.config.ts index f9b7aa34..ba6defc6 100644 --- a/packages/ts-client/playwright.config.ts +++ b/e2e-tests/ts-client/app/playwright.config.ts @@ -10,7 +10,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './e2e', + testDir: '../.', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ @@ -20,7 +20,10 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: [ + ['list'], + ['html', { outputFolder: '../../../playwright-report/ts-client-e2e', open: "never" }] + ], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ @@ -50,46 +53,15 @@ export default defineConfig({ }, }, }, - - // { - // name: 'firefox', - // use: { ...devices['Desktop Firefox'] }, - // }, - - // { - // name: 'webkit', - // use: { ...devices['Desktop Safari'] }, - // }, - - /* Test against mobile viewports. */ - // { - // name: 'Mobile Chrome', - // use: { ...devices['Pixel 5'] }, - // }, - // { - // name: 'Mobile Safari', - // use: { ...devices['iPhone 12'] }, - // }, - - /* Test against branded browsers. */ - // { - // name: 'Microsoft Edge', - // use: { ...devices['Desktop Edge'], channel: 'msedge' }, - // }, - // { - // name: 'Google Chrome', - // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - // }, ], /* Run your local dev server before starting the tests */ webServer: { - command: 'npm run dev', + command: 'yarn run dev', url: 'http://localhost:5173', reuseExistingServer: !process.env.CI, - cwd: 'e2e/app', }, - globalSetup: './e2e/setup/setupFishjam', - globalTeardown: './e2e/setup/teardownFishjam', + globalSetup: '../setup/setupFishjam', + globalTeardown: '../setup/teardownFishjam', }); diff --git a/e2e_tests/ts-client/app/src/App.tsx b/e2e-tests/ts-client/app/src/App.tsx similarity index 100% rename from e2e_tests/ts-client/app/src/App.tsx rename to e2e-tests/ts-client/app/src/App.tsx diff --git a/e2e_tests/ts-client/app/src/MockComponent.tsx b/e2e-tests/ts-client/app/src/MockComponent.tsx similarity index 100% rename from e2e_tests/ts-client/app/src/MockComponent.tsx rename to e2e-tests/ts-client/app/src/MockComponent.tsx diff --git a/e2e_tests/ts-client/app/src/MuteTrackTest.tsx b/e2e-tests/ts-client/app/src/MuteTrackTest.tsx similarity index 97% rename from e2e_tests/ts-client/app/src/MuteTrackTest.tsx rename to e2e-tests/ts-client/app/src/MuteTrackTest.tsx index 02f4dca6..680f8a15 100644 --- a/e2e_tests/ts-client/app/src/MuteTrackTest.tsx +++ b/e2e-tests/ts-client/app/src/MuteTrackTest.tsx @@ -2,7 +2,7 @@ import { WebRTCEndpoint } from '@fishjam-dev/ts-client'; import { brain2Mock, heart2Mock } from './MockComponent'; import { useEffect, useState } from 'react'; import { VideoPlayer } from './VideoPlayer'; -import { WebRTCEndpointEvents } from '../../../src'; +import { WebRTCEndpointEvents } from '@fishjam-dev/ts-client/webrtc'; import { EndpointMetadata, TrackMetadata } from './App'; type Props = { diff --git a/e2e_tests/ts-client/app/src/VideoPlayer.tsx b/e2e-tests/ts-client/app/src/VideoPlayer.tsx similarity index 100% rename from e2e_tests/ts-client/app/src/VideoPlayer.tsx rename to e2e-tests/ts-client/app/src/VideoPlayer.tsx diff --git a/e2e_tests/ts-client/app/src/VideoPlayerWithDetector.tsx b/e2e-tests/ts-client/app/src/VideoPlayerWithDetector.tsx similarity index 100% rename from e2e_tests/ts-client/app/src/VideoPlayerWithDetector.tsx rename to e2e-tests/ts-client/app/src/VideoPlayerWithDetector.tsx diff --git a/e2e_tests/ts-client/app/src/main.tsx b/e2e-tests/ts-client/app/src/main.tsx similarity index 100% rename from e2e_tests/ts-client/app/src/main.tsx rename to e2e-tests/ts-client/app/src/main.tsx diff --git a/e2e_tests/ts-client/app/src/mocks.ts b/e2e-tests/ts-client/app/src/mocks.ts similarity index 100% rename from e2e_tests/ts-client/app/src/mocks.ts rename to e2e-tests/ts-client/app/src/mocks.ts diff --git a/e2e_tests/ts-client/app/src/vite-env.d.ts b/e2e-tests/ts-client/app/src/vite-env.d.ts similarity index 100% rename from e2e_tests/ts-client/app/src/vite-env.d.ts rename to e2e-tests/ts-client/app/src/vite-env.d.ts diff --git a/e2e-tests/ts-client/app/tsconfig.json b/e2e-tests/ts-client/app/tsconfig.json new file mode 100644 index 00000000..f31856b9 --- /dev/null +++ b/e2e-tests/ts-client/app/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "lib": [ + "dom", + "dom.iterable", + "es2022" + ], + "module": "esnext", + "moduleResolution": "bundler", + "target": "es2022", + "jsx": "react-jsx", + "strict": true, + "incremental": true, + "skipLibCheck": true, + "esModuleInterop": true, + "declaration": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "outDir": "dist" + }, + "include": [ + "src/**/*" + ] +} diff --git a/e2e_tests/ts-client/app/tsconfig.node.json b/e2e-tests/ts-client/app/tsconfig.node.json similarity index 100% rename from e2e_tests/ts-client/app/tsconfig.node.json rename to e2e-tests/ts-client/app/tsconfig.node.json diff --git a/e2e_tests/ts-client/app/vite.config.ts b/e2e-tests/ts-client/app/vite.config.ts similarity index 100% rename from e2e_tests/ts-client/app/vite.config.ts rename to e2e-tests/ts-client/app/vite.config.ts diff --git a/e2e_tests/ts-client/docker-compose-test.yaml b/e2e-tests/ts-client/docker-compose-test.yaml similarity index 91% rename from e2e_tests/ts-client/docker-compose-test.yaml rename to e2e-tests/ts-client/docker-compose-test.yaml index ae88b151..3d742cfd 100644 --- a/e2e_tests/ts-client/docker-compose-test.yaml +++ b/e2e-tests/ts-client/docker-compose-test.yaml @@ -2,7 +2,7 @@ version: '3' services: fishjam: - image: 'ghcr.io/fishjam-dev/fishjam:${FISHJAM_VERSION:-0.6.1}' + image: 'ghcr.io/fishjam-dev/fishjam:${FISHJAM_VERSION:-0.6.3}' container_name: fishjam restart: on-failure healthcheck: diff --git a/e2e_tests/ts-client/scenarios/basic.spec.ts b/e2e-tests/ts-client/scenarios/basic.spec.ts similarity index 100% rename from e2e_tests/ts-client/scenarios/basic.spec.ts rename to e2e-tests/ts-client/scenarios/basic.spec.ts diff --git a/e2e_tests/ts-client/scenarios/metadataParsing.spec.ts b/e2e-tests/ts-client/scenarios/metadataParsing.spec.ts similarity index 100% rename from e2e_tests/ts-client/scenarios/metadataParsing.spec.ts rename to e2e-tests/ts-client/scenarios/metadataParsing.spec.ts diff --git a/e2e_tests/ts-client/scenarios/raceCondition.spec.ts b/e2e-tests/ts-client/scenarios/raceCondition.spec.ts similarity index 100% rename from e2e_tests/ts-client/scenarios/raceCondition.spec.ts rename to e2e-tests/ts-client/scenarios/raceCondition.spec.ts diff --git a/e2e_tests/ts-client/scenarios/replaceTrack.spec.ts b/e2e-tests/ts-client/scenarios/replaceTrack.spec.ts similarity index 100% rename from e2e_tests/ts-client/scenarios/replaceTrack.spec.ts rename to e2e-tests/ts-client/scenarios/replaceTrack.spec.ts diff --git a/e2e_tests/ts-client/scenarios/utils.ts b/e2e-tests/ts-client/scenarios/utils.ts similarity index 100% rename from e2e_tests/ts-client/scenarios/utils.ts rename to e2e-tests/ts-client/scenarios/utils.ts diff --git a/e2e_tests/ts-client/setup/globalSetupState.ts b/e2e-tests/ts-client/setup/globalSetupState.ts similarity index 100% rename from e2e_tests/ts-client/setup/globalSetupState.ts rename to e2e-tests/ts-client/setup/globalSetupState.ts diff --git a/e2e-tests/ts-client/setup/setupFishjam.ts b/e2e-tests/ts-client/setup/setupFishjam.ts new file mode 100644 index 00000000..3ac876cc --- /dev/null +++ b/e2e-tests/ts-client/setup/setupFishjam.ts @@ -0,0 +1,23 @@ +import { DockerComposeEnvironment, Wait } from 'testcontainers'; +import { setupState } from './globalSetupState'; +import { type NetworkInterfaceInfo, networkInterfaces } from 'os'; + +export default async function setupFishjam() { + const EXTERNAL_IP = Object.values(networkInterfaces()) + .flat() + .filter((x): x is NetworkInterfaceInfo => x !== undefined) + .filter(({ family }) => family === 'IPv4') + .filter(({ internal }) => !internal) + .map(({ address }) => address)[0]; + + setupState.fishjamContainer = await new DockerComposeEnvironment( + '../.', + 'docker-compose-test.yaml', + ) + .withEnvironment({ EXTERNAL_IP }) + .withWaitStrategy( + 'fishjam', + Wait.forLogMessage('Access FishjamWeb.Endpoint at'), + ) + .up(); +} diff --git a/e2e_tests/ts-client/setup/teardownFishjam.ts b/e2e-tests/ts-client/setup/teardownFishjam.ts similarity index 100% rename from e2e_tests/ts-client/setup/teardownFishjam.ts rename to e2e-tests/ts-client/setup/teardownFishjam.ts diff --git a/e2e_tests/react-client/setupFishjam.ts b/e2e_tests/react-client/setupFishjam.ts deleted file mode 100644 index 5ea4701e..00000000 --- a/e2e_tests/react-client/setupFishjam.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Wait, DockerComposeEnvironment } from "testcontainers"; -import { setupState } from "./globalSetupState"; -import { type NetworkInterfaceInfo, networkInterfaces } from "os"; - -export default async function setupFishjam() { - const EXTERNAL_IP = Object.values(networkInterfaces()) - .flat() - .filter((x): x is NetworkInterfaceInfo => x !== undefined) - .filter(({ family }) => (typeof family === "string" ? family === "IPv4" : family === 4)) - .filter(({ internal }) => !internal) - .map(({ address }) => address)[0]; - - const container = await new DockerComposeEnvironment("tests", "docker-compose-test.yaml") - .withEnvironment({ EXTERNAL_IP }) - .withWaitStrategy("fishjam", Wait.forLogMessage("Access FishjamWeb.Endpoint at")) - .up(); - - setupState.fishjamContainer = container; -} diff --git a/e2e_tests/ts-client/app/tsconfig.json b/e2e_tests/ts-client/app/tsconfig.json deleted file mode 100644 index 1a448ce6..00000000 --- a/e2e_tests/ts-client/app/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": ["src/**/*", "tests/**/*"] -} diff --git a/examples/react-client/minimal-react/package.json b/examples/react-client/minimal-react/package.json index f819ab8e..15d2556c 100644 --- a/examples/react-client/minimal-react/package.json +++ b/examples/react-client/minimal-react/package.json @@ -1,5 +1,5 @@ { - "name": "minimal-react-example", + "name": "@fishjam-example/minimal-react-example", "private": true, "version": "0.0.1", "type": "module", diff --git a/examples/ts-client/minimal/package.json b/examples/ts-client/minimal/package.json index b6b2e3e3..e67bae93 100644 --- a/examples/ts-client/minimal/package.json +++ b/examples/ts-client/minimal/package.json @@ -1,5 +1,5 @@ { - "name": "minimal-example", + "name": "@fishjam-example/minimal-example", "private": true, "version": "0.0.1", "type": "module", diff --git a/examples/ts-client/simple-app/package.json b/examples/ts-client/simple-app/package.json index fe82d497..276933b5 100644 --- a/examples/ts-client/simple-app/package.json +++ b/examples/ts-client/simple-app/package.json @@ -1,5 +1,5 @@ { - "name": "simple-app-example", + "name": "@fishjam-example/simple-app-example", "private": true, "version": "0.0.1", "license": "Apache-2.0", diff --git a/package.json b/package.json index 4ee2c089..54d4b187 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,14 @@ "packages/ts-client", "packages/react-client", "examples/ts-client/*", - "examples/react-client/*" + "examples/react-client/*", + "e2e-tests/ts-client/app", + "e2e-tests/react-client/app" ], "packageManager": "yarn@4.3.0", "scripts": { - "build": "yarn workspace @fishjam-dev/ts-client build && yarn workspace @fishjam-dev/react-client build", + "build": "yarn workspaces foreach -Ap --topological-dev run build", + "test:e2e": "yarn workspace @fishjam-e2e/ts-client-e2e e2e && yarn workspace @fishjam-e2e/react-client-e2e e2e", "tsc": "yarn workspaces foreach -A -p run tsc", "format": "yarn workspaces foreach -A -p run format", "format:check": "yarn workspaces foreach -A -p run format:check", diff --git a/yarn.lock b/yarn.lock index 53d8747c..902d10b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -280,6 +280,13 @@ __metadata: languageName: node linkType: hard +"@balena/dockerignore@npm:^1.0.2": + version: 1.0.2 + resolution: "@balena/dockerignore@npm:1.0.2" + checksum: 10c0/0bcb067e86f6734ab943ce4ce9a7c8611f2e983a70bccebf9d2309db57695c09dded7faf5be49c929c4c9e9a9174ae55fc625626de0fb9958823c37423d12f4e + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -537,6 +544,92 @@ __metadata: languageName: unknown linkType: soft +"@fishjam-e2e/react-client-e2e@workspace:e2e-tests/react-client/app": + version: 0.0.0-use.local + resolution: "@fishjam-e2e/react-client-e2e@workspace:e2e-tests/react-client/app" + dependencies: + "@playwright/test": "npm:^1.41.2" + "@types/node": "npm:^20.11.18" + "@vitest/coverage-v8": "npm:^1.6.0" + testcontainers: "npm:^10.3.2" + typescript: "npm:^5.4.5" + vite: "npm:^5.1.2" + vitest: "npm:^1.6.0" + languageName: unknown + linkType: soft + +"@fishjam-e2e/ts-client-e2e@workspace:e2e-tests/ts-client/app": + version: 0.0.0-use.local + resolution: "@fishjam-e2e/ts-client-e2e@workspace:e2e-tests/ts-client/app" + dependencies: + "@fishjam-dev/ts-client": "npm:*" + "@playwright/test": "npm:^1.41.2" + "@types/node": "npm:^20.11.18" + "@types/react": "npm:^18.2.55" + "@types/react-dom": "npm:^18.2.19" + "@typescript-eslint/eslint-plugin": "npm:^7.0.1" + "@typescript-eslint/parser": "npm:^7.0.1" + "@vitejs/plugin-react": "npm:^4.2.1" + "@vitest/coverage-v8": "npm:^1.6.0" + eslint: "npm:^8.56.0" + eslint-plugin-react-hooks: "npm:^4.6.0" + eslint-plugin-react-refresh: "npm:^0.4.5" + protobufjs: "npm:^7.2.6" + react: "npm:^18.2.0" + react-dom: "npm:^18.2.0" + testcontainers: "npm:^10.3.2" + ts-proto: "npm:^1.176.0" + typescript: "npm:^5.4.5" + vite: "npm:^5.1.2" + vitest: "npm:^1.6.0" + languageName: unknown + linkType: soft + +"@fishjam-example/minimal-example@workspace:examples/ts-client/minimal": + version: 0.0.0-use.local + resolution: "@fishjam-example/minimal-example@workspace:examples/ts-client/minimal" + dependencies: + "@fishjam-dev/ts-client": "npm:*" + autoprefixer: "npm:^10.4.17" + typescript: "npm:^5.4.0" + vite: "npm:^5.1.2" + vite-plugin-checker: "npm:^0.6.4" + languageName: unknown + linkType: soft + +"@fishjam-example/minimal-react-example@workspace:examples/react-client/minimal-react": + version: 0.0.0-use.local + resolution: "@fishjam-example/minimal-react-example@workspace:examples/react-client/minimal-react" + dependencies: + "@fishjam-dev/react-client": "npm:*" + "@types/react": "npm:^18.2.55" + "@types/react-dom": "npm:^18.2.19" + "@vitejs/plugin-react-swc": "npm:^3.6.0" + autoprefixer: "npm:^10.4.17" + postcss: "npm:^8.4.39" + react: "npm:^18.2.0" + react-dom: "npm:^18.2.0" + typescript: "npm:^5.4.0" + vite: "npm:^5.1.2" + vite-plugin-checker: "npm:^0.6.4" + languageName: unknown + linkType: soft + +"@fishjam-example/simple-app-example@workspace:examples/ts-client/simple-app": + version: 0.0.0-use.local + resolution: "@fishjam-example/simple-app-example@workspace:examples/ts-client/simple-app" + dependencies: + "@fishjam-dev/ts-client": "npm:*" + autoprefixer: "npm:^10.4.17" + daisyui: "npm:^4.7.2" + postcss: "npm:^8.4.39" + tailwindcss: "npm:^3.4.1" + typescript: "npm:^5.4.0" + vite: "npm:^5.1.2" + vite-plugin-checker: "npm:^0.6.4" + languageName: unknown + linkType: soft + "@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" @@ -701,6 +794,17 @@ __metadata: languageName: node linkType: hard +"@playwright/test@npm:^1.41.2": + version: 1.45.1 + resolution: "@playwright/test@npm:1.45.1" + dependencies: + playwright: "npm:1.45.1" + bin: + playwright: cli.js + checksum: 10c0/ba214addee06e846041b819b8bcc2b04dae1beb36d05cd0942bb0fc7f9742002c881e2058b75aba37a8baef9a3aaff66e818b20b8013e9020d2cc28ff0c655d7 + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -1087,6 +1191,27 @@ __metadata: languageName: node linkType: hard +"@types/docker-modem@npm:*": + version: 3.0.6 + resolution: "@types/docker-modem@npm:3.0.6" + dependencies: + "@types/node": "npm:*" + "@types/ssh2": "npm:*" + checksum: 10c0/d3ffd273148bc883ff9b1a972b1f84c1add6d9a197d2f4fc9774db4c814f39c2e51cc649385b55d781c790c16fb0bf9c1f4c62499bd0f372a4b920190919445d + languageName: node + linkType: hard + +"@types/dockerode@npm:^3.3.29": + version: 3.3.29 + resolution: "@types/dockerode@npm:3.3.29" + dependencies: + "@types/docker-modem": "npm:*" + "@types/node": "npm:*" + "@types/ssh2": "npm:*" + checksum: 10c0/1c51a9f7d9a2ab81ecdf9e56b9a8e25400a97ed5f0701c583ed030b4518dee4b3d2ecc7d927fe1ff618c06747f3b285168adac5293aa3cdafafa1914db595cc2 + languageName: node + linkType: hard + "@types/estree@npm:1.0.5, @types/estree@npm:^1.0.0": version: 1.0.5 resolution: "@types/estree@npm:1.0.5" @@ -1117,6 +1242,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:*, @types/node@npm:^20.11.18": + version: 20.14.9 + resolution: "@types/node@npm:20.14.9" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 10c0/911ffa444dc032897f4a23ed580c67903bd38ea1c5ec99b1d00fa10b83537a3adddef8e1f29710cbdd8e556a61407ed008e06537d834e48caf449ce59f87d387 + languageName: node + linkType: hard + "@types/node@npm:>=13.7.0, @types/node@npm:^20.10.3, @types/node@npm:^20.11.27": version: 20.14.5 resolution: "@types/node@npm:20.14.5" @@ -1126,6 +1260,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^18.11.18": + version: 18.19.39 + resolution: "@types/node@npm:18.19.39" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 10c0/a9eb33bc093beba6bd5d4e839de7d1d1f496cd7e741c2f6c7161318dba0f37227bb25d8306907194992488d6c59a7363a419d72298549483d33402227a2d435b + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.12 resolution: "@types/prop-types@npm:15.7.12" @@ -1152,6 +1295,34 @@ __metadata: languageName: node linkType: hard +"@types/ssh2-streams@npm:*": + version: 0.1.12 + resolution: "@types/ssh2-streams@npm:0.1.12" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/6c860066e76391c937723b9f8c3953208737be5adf33b5584d7817ec90913094f2ca578e1d47717182f1d62cb5ca8e83fdec0241d73bf064221e3a2b2d132f0e + languageName: node + linkType: hard + +"@types/ssh2@npm:*": + version: 1.15.0 + resolution: "@types/ssh2@npm:1.15.0" + dependencies: + "@types/node": "npm:^18.11.18" + checksum: 10c0/055c271845847867c365b0c002e59536608e400864aea4f54ebc72e8588b92dbc4b6572e3095092dba0d86d49898e2180a389810269d119f897972ebbddb4a7f + languageName: node + linkType: hard + +"@types/ssh2@npm:^0.5.48": + version: 0.5.52 + resolution: "@types/ssh2@npm:0.5.52" + dependencies: + "@types/node": "npm:*" + "@types/ssh2-streams": "npm:*" + checksum: 10c0/95c52fd3438dedae6a59ca87b6558cb36568db6b9144c6c8a28c168739e04c51e27c02908aae14950b7b5020e1c40fea039b1203ae2734c356a40a050fd51c84 + languageName: node + linkType: hard + "@types/uuid@npm:^9.0.8": version: 9.0.8 resolution: "@types/uuid@npm:9.0.8" @@ -1159,6 +1330,29 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:^7.0.1": + version: 7.15.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.15.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:7.15.0" + "@typescript-eslint/type-utils": "npm:7.15.0" + "@typescript-eslint/utils": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.3.1" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^1.3.0" + peerDependencies: + "@typescript-eslint/parser": ^7.0.0 + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/7ed4ef8355cb60f02ed603673ef749928a001931c534960d1f3f9f9b8092f4abd7ec1e80a33b4c38efb6e8e66c902583bd56a4c4d6ccbd870677a40680a7d1f5 + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:^7.14.1": version: 7.14.1 resolution: "@typescript-eslint/eslint-plugin@npm:7.14.1" @@ -1182,6 +1376,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:^7.0.1": + version: 7.15.0 + resolution: "@typescript-eslint/parser@npm:7.15.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:7.15.0" + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/typescript-estree": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + debug: "npm:^4.3.4" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/8dcad9b84e2cbf89afea97ee7f690f91b487eed21d01997126f98cb7dd56d3b6c98c7ecbdbeda35904af521c4ed746c47887e908f8a1e2148d47c05b491d7b9d + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:^7.8.0": version: 7.13.1 resolution: "@typescript-eslint/parser@npm:7.13.1" @@ -1220,6 +1432,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/scope-manager@npm:7.15.0" + dependencies: + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + checksum: 10c0/781ec31a07ab7f0bdfb07dd271ef6553aa98f8492f1b3a67c65d178c94d590f4fd2e0916450f2446f1da2fbe007f3454c360ccb25f4d69612f782eb499f400ab + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:7.14.1": version: 7.14.1 resolution: "@typescript-eslint/type-utils@npm:7.14.1" @@ -1237,6 +1459,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/type-utils@npm:7.15.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:7.15.0" + "@typescript-eslint/utils": "npm:7.15.0" + debug: "npm:^4.3.4" + ts-api-utils: "npm:^1.3.0" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/06189eb05d741f05977bbc029c6ac46edd566e0136f2f2c22429fd5f2be1224e2d9135b7021bc686871bfaec9c05a5c9990a321762d3abd06e457486956326ba + languageName: node + linkType: hard + "@typescript-eslint/types@npm:7.13.1": version: 7.13.1 resolution: "@typescript-eslint/types@npm:7.13.1" @@ -1251,6 +1490,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/types@npm:7.15.0" + checksum: 10c0/935387b21d9fdff65de86f6350cdda1f0614e269324f3a4f0a2ca1b0d72ef4b1d40c7de2f3a20a6f8c83edca6507bfbac3168c860625859e59fc455c80392bed + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:7.13.1": version: 7.13.1 resolution: "@typescript-eslint/typescript-estree@npm:7.13.1" @@ -1289,6 +1535,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.15.0" + dependencies: + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/visitor-keys": "npm:7.15.0" + debug: "npm:^4.3.4" + globby: "npm:^11.1.0" + is-glob: "npm:^4.0.3" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/0d6e61cb36c4612147ceea796c2bdbb65fca59170d9d768cff314146c5564253a058cbcb9e251722cd76c92a90c257e1210a69f8d4377c8002f211c574d18d24 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:7.14.1": version: 7.14.1 resolution: "@typescript-eslint/utils@npm:7.14.1" @@ -1303,6 +1568,20 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/utils@npm:7.15.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.4.0" + "@typescript-eslint/scope-manager": "npm:7.15.0" + "@typescript-eslint/types": "npm:7.15.0" + "@typescript-eslint/typescript-estree": "npm:7.15.0" + peerDependencies: + eslint: ^8.56.0 + checksum: 10c0/26aced17976cee0aa39a79201f68b384bbce1dc96e1c70d0e5f790e1e5655b1b1ddb2afd9eaf3fce9a48c0fb69daecd37a99fdbcdbf1cb58c65ae89ecac88a2c + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:7.13.1": version: 7.13.1 resolution: "@typescript-eslint/visitor-keys@npm:7.13.1" @@ -1323,6 +1602,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:7.15.0": + version: 7.15.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.15.0" + dependencies: + "@typescript-eslint/types": "npm:7.15.0" + eslint-visitor-keys: "npm:^3.4.3" + checksum: 10c0/7509f01c8cd2126a38213bc735a77aa7e976340af0d664be5b2ccd01b8211724b2ea129e33bfd32fe5feac848b7b68ca55bb533f6ccfeec1d2f26a91240489b9 + languageName: node + linkType: hard + "@ungap/structured-clone@npm:^1.2.0": version: 1.2.0 resolution: "@ungap/structured-clone@npm:1.2.0" @@ -1577,6 +1866,57 @@ __metadata: languageName: node linkType: hard +"archiver-utils@npm:^2.1.0": + version: 2.1.0 + resolution: "archiver-utils@npm:2.1.0" + dependencies: + glob: "npm:^7.1.4" + graceful-fs: "npm:^4.2.0" + lazystream: "npm:^1.0.0" + lodash.defaults: "npm:^4.2.0" + lodash.difference: "npm:^4.5.0" + lodash.flatten: "npm:^4.4.0" + lodash.isplainobject: "npm:^4.0.6" + lodash.union: "npm:^4.6.0" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^2.0.0" + checksum: 10c0/6ea5b02e440f3099aff58b18dd384f84ecfe18632e81d26c1011fe7dfdb80ade43d7a06cbf048ef0e9ee0f2c87a80cb24c0f0ac5e3a2c4d67641d6f0d6e36ece + languageName: node + linkType: hard + +"archiver-utils@npm:^3.0.4": + version: 3.0.4 + resolution: "archiver-utils@npm:3.0.4" + dependencies: + glob: "npm:^7.2.3" + graceful-fs: "npm:^4.2.0" + lazystream: "npm:^1.0.0" + lodash.defaults: "npm:^4.2.0" + lodash.difference: "npm:^4.5.0" + lodash.flatten: "npm:^4.4.0" + lodash.isplainobject: "npm:^4.0.6" + lodash.union: "npm:^4.6.0" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^3.6.0" + checksum: 10c0/9bb7e271e95ff33bdbdcd6f69f8860e0aeed3fcba352a74f51a626d1c32b404f20e3185d5214f171b24a692471d01702f43874d1a4f0d2e5f57bd0834bc54c14 + languageName: node + linkType: hard + +"archiver@npm:^5.3.2": + version: 5.3.2 + resolution: "archiver@npm:5.3.2" + dependencies: + archiver-utils: "npm:^2.1.0" + async: "npm:^3.2.4" + buffer-crc32: "npm:^0.2.1" + readable-stream: "npm:^3.6.0" + readdir-glob: "npm:^1.1.2" + tar-stream: "npm:^2.2.0" + zip-stream: "npm:^4.1.0" + checksum: 10c0/973384d749b3fa96f44ceda1603a65aaa3f24a267230d69a4df9d7b607d38d3ebc6c18c358af76eb06345b6b331ccb9eca07bd079430226b5afce95de22dfade + languageName: node + linkType: hard + "arg@npm:^5.0.2": version: 5.0.2 resolution: "arg@npm:5.0.2" @@ -1598,6 +1938,15 @@ __metadata: languageName: node linkType: hard +"asn1@npm:^0.2.6": + version: 0.2.6 + resolution: "asn1@npm:0.2.6" + dependencies: + safer-buffer: "npm:~2.1.0" + checksum: 10c0/00c8a06c37e548762306bcb1488388d2f76c74c36f70c803f0c081a01d3bdf26090fc088cd812afc5e56a6d49e33765d451a5f8a68ab9c2b087eba65d2e980e0 + languageName: node + linkType: hard + "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -1605,6 +1954,20 @@ __metadata: languageName: node linkType: hard +"async-lock@npm:^1.4.1": + version: 1.4.1 + resolution: "async-lock@npm:1.4.1" + checksum: 10c0/f696991c7d894af1dc91abc81cc4f14b3785190a35afb1646d8ab91138238d55cabd83bfdd56c42663a008d72b3dc39493ff83797e550effc577d1ccbde254af + languageName: node + linkType: hard + +"async@npm:^3.2.4": + version: 3.2.5 + resolution: "async@npm:3.2.5" + checksum: 10c0/1408287b26c6db67d45cb346e34892cee555b8b59e6c68e6f8c3e495cad5ca13b4f218180e871f3c2ca30df4ab52693b66f2f6ff43644760cab0b2198bda79c1 + languageName: node + linkType: hard + "autoprefixer@npm:^10.4.17": version: 10.4.19 resolution: "autoprefixer@npm:10.4.19" @@ -1623,6 +1986,13 @@ __metadata: languageName: node linkType: hard +"b4a@npm:^1.6.4": + version: 1.6.6 + resolution: "b4a@npm:1.6.6" + checksum: 10c0/56f30277666cb511a15829e38d369b114df7dc8cec4cedc09cc5d685bc0f27cb63c7bcfb58e09a19a1b3c4f2541069ab078b5328542e85d74a39620327709a38 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -1630,6 +2000,65 @@ __metadata: languageName: node linkType: hard +"bare-events@npm:^2.0.0, bare-events@npm:^2.2.0": + version: 2.4.2 + resolution: "bare-events@npm:2.4.2" + checksum: 10c0/09fa923061f31f815e83504e2ed4a8ba87732a01db40a7fae703dbb7eef7f05d99264b5e186074cbe9698213990d1af564c62cca07a5ff88baea8099ad9a6303 + languageName: node + linkType: hard + +"bare-fs@npm:^2.1.1": + version: 2.3.1 + resolution: "bare-fs@npm:2.3.1" + dependencies: + bare-events: "npm:^2.0.0" + bare-path: "npm:^2.0.0" + bare-stream: "npm:^2.0.0" + checksum: 10c0/820979ad3dd8693076ba08af842e41b5119fcca63f4324b8f28d96b96050cd260085dffd1169dc644f20746fadb4cf4368b317f2fa2db4e40890921ceb557581 + languageName: node + linkType: hard + +"bare-os@npm:^2.1.0": + version: 2.4.0 + resolution: "bare-os@npm:2.4.0" + checksum: 10c0/85615522fd8309d3815d3bef227623f008fac34e037459294a7e24bb2b51ea125597274b8aa7e7038f82de89c15e2148fef299eece40ec3ea33797a357c4f2bb + languageName: node + linkType: hard + +"bare-path@npm:^2.0.0, bare-path@npm:^2.1.0": + version: 2.1.3 + resolution: "bare-path@npm:2.1.3" + dependencies: + bare-os: "npm:^2.1.0" + checksum: 10c0/35587e177fc8fa5b13fb90bac8779b5ce49c99016d221ddaefe2232d02bd4295d79b941e14ae19fda75ec42a6fe5fb66c07d83ae7ec11462178e66b7be65ca74 + languageName: node + linkType: hard + +"bare-stream@npm:^2.0.0": + version: 2.1.3 + resolution: "bare-stream@npm:2.1.3" + dependencies: + streamx: "npm:^2.18.0" + checksum: 10c0/8703b1d80318496ea560483943d5f425a160ded8d3d75659571842caf5f374f52668809bc1e39b032af14df7210973995efaf273f8c35986bef697380ef4674a + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf + languageName: node + linkType: hard + +"bcrypt-pbkdf@npm:^1.0.2": + version: 1.0.2 + resolution: "bcrypt-pbkdf@npm:1.0.2" + dependencies: + tweetnacl: "npm:^0.14.3" + checksum: 10c0/ddfe85230b32df25aeebfdccfbc61d3bc493ace49c884c9c68575de1f5dcf733a5d7de9def3b0f318b786616b8d85bad50a28b1da1750c43e0012c93badcc148 + languageName: node + linkType: hard + "binary-extensions@npm:^2.0.0": version: 2.3.0 resolution: "binary-extensions@npm:2.3.0" @@ -1637,6 +2066,17 @@ __metadata: languageName: node linkType: hard +"bl@npm:^4.0.3": + version: 4.1.0 + resolution: "bl@npm:4.1.0" + dependencies: + buffer: "npm:^5.5.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.4.0" + checksum: 10c0/02847e1d2cb089c9dc6958add42e3cdeaf07d13f575973963335ac0fdece563a50ac770ac4c8fa06492d2dd276f6cc3b7f08c7cd9c7a7ad0f8d388b2a28def5f + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -1679,6 +2119,37 @@ __metadata: languageName: node linkType: hard +"buffer-crc32@npm:^0.2.1, buffer-crc32@npm:^0.2.13": + version: 0.2.13 + resolution: "buffer-crc32@npm:0.2.13" + checksum: 10c0/cb0a8ddf5cf4f766466db63279e47761eb825693eeba6a5a95ee4ec8cb8f81ede70aa7f9d8aeec083e781d47154290eb5d4d26b3f7a465ec57fb9e7d59c47150 + languageName: node + linkType: hard + +"buffer@npm:^5.5.0": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + +"buildcheck@npm:~0.0.6": + version: 0.0.6 + resolution: "buildcheck@npm:0.0.6" + checksum: 10c0/8cbdb89f41bc484b8325f4828db4135b206a0dffb641eb6cdb2b7022483c45dd0e5aac6d820c9a67bdd2caab3a02c76d7ceec7bd9ec494b5a2270d2806b01a76 + languageName: node + linkType: hard + +"byline@npm:^5.0.0": + version: 5.0.0 + resolution: "byline@npm:5.0.0" + checksum: 10c0/33fb64cd84440b3652a99a68d732c56ef18a748ded495ba38e7756a242fab0d4654b9b8ce269fd0ac14c5f97aa4e3c369613672b280a1f60b559b34223105c85 + languageName: node + linkType: hard + "cac@npm:^6.7.14": version: 6.7.14 resolution: "cac@npm:6.7.14" @@ -1805,6 +2276,13 @@ __metadata: languageName: node linkType: hard +"chownr@npm:^1.1.1": + version: 1.1.4 + resolution: "chownr@npm:1.1.4" + checksum: 10c0/ed57952a84cc0c802af900cf7136de643d3aba2eecb59d29344bc2f3f9bf703a301b9d84cdc71f82c3ffc9ccde831b0d92f5b45f91727d6c9da62f23aef9d9db + languageName: node + linkType: hard + "chownr@npm:^2.0.0": version: 2.0.0 resolution: "chownr@npm:2.0.0" @@ -1898,6 +2376,18 @@ __metadata: languageName: node linkType: hard +"compress-commons@npm:^4.1.2": + version: 4.1.2 + resolution: "compress-commons@npm:4.1.2" + dependencies: + buffer-crc32: "npm:^0.2.13" + crc32-stream: "npm:^4.0.2" + normalize-path: "npm:^3.0.0" + readable-stream: "npm:^3.6.0" + checksum: 10c0/e5fa03cb374ed89028e20226c70481e87286240392d5c6856f4e7fef40605c1892748648e20ed56597d390d76513b1b9bb4dbd658a1bbff41c9fa60107c74d3f + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -1919,6 +2409,43 @@ __metadata: languageName: node linkType: hard +"core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 10c0/90a0e40abbddfd7618f8ccd63a74d88deea94e77d0e8dbbea059fa7ebebb8fbb4e2909667fe26f3a467073de1a542ebe6ae4c73a73745ac5833786759cd906c9 + languageName: node + linkType: hard + +"cpu-features@npm:~0.0.9": + version: 0.0.10 + resolution: "cpu-features@npm:0.0.10" + dependencies: + buildcheck: "npm:~0.0.6" + nan: "npm:^2.19.0" + node-gyp: "npm:latest" + checksum: 10c0/0c4a12904657b22477ffbcfd2b4b2bdd45b174f283616b18d9e1ade495083f9f6098493feb09f4ae2d0b36b240f9ecd32cfb4afe210cf0d0f8f0cc257bd58e54 + languageName: node + linkType: hard + +"crc-32@npm:^1.2.0": + version: 1.2.2 + resolution: "crc-32@npm:1.2.2" + bin: + crc32: bin/crc32.njs + checksum: 10c0/11dcf4a2e77ee793835d49f2c028838eae58b44f50d1ff08394a610bfd817523f105d6ae4d9b5bef0aad45510f633eb23c903e9902e4409bed1ce70cb82b9bf0 + languageName: node + linkType: hard + +"crc32-stream@npm:^4.0.2": + version: 4.0.3 + resolution: "crc32-stream@npm:4.0.3" + dependencies: + crc-32: "npm:^1.2.0" + readable-stream: "npm:^3.4.0" + checksum: 10c0/127b0c66a947c54db37054fca86085722140644d3a75ebc61d4477bad19304d2936386b0461e8ee9e1c24b00e804cd7c2e205180e5bcb4632d20eccd60533bc4 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -1975,7 +2502,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:~4.3.4": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:~4.3.4": version: 4.3.5 resolution: "debug@npm:4.3.5" dependencies: @@ -2042,6 +2569,38 @@ __metadata: languageName: node linkType: hard +"docker-compose@npm:^0.24.8": + version: 0.24.8 + resolution: "docker-compose@npm:0.24.8" + dependencies: + yaml: "npm:^2.2.2" + checksum: 10c0/1494389e554fed8aabf9fef24210a641cd2442028b1462d7f68186919f5e75045f7bfb4ccaf47c94ed879dcb63e4d82885c389399f531550c4b244920740b2b3 + languageName: node + linkType: hard + +"docker-modem@npm:^3.0.0": + version: 3.0.8 + resolution: "docker-modem@npm:3.0.8" + dependencies: + debug: "npm:^4.1.1" + readable-stream: "npm:^3.5.0" + split-ca: "npm:^1.0.1" + ssh2: "npm:^1.11.0" + checksum: 10c0/5c00592297fabd78454621fe765a5ef0daea4bbb6692e239ad65b111f4da9d750178f448f8efcaf84f9f999598eb735bc14ad6bf5f0a2dcf9c2d453d5b683540 + languageName: node + linkType: hard + +"dockerode@npm:^3.3.5": + version: 3.3.5 + resolution: "dockerode@npm:3.3.5" + dependencies: + "@balena/dockerignore": "npm:^1.0.2" + docker-modem: "npm:^3.0.0" + tar-fs: "npm:~2.0.1" + checksum: 10c0/c45fa8ed3ad76f13fe7799d539a60fe466f8e34bea06b30d75be9e08bc00536cc9ff2d54e38fbb3b2a8a382bf9d4459a27741e6454ce7d0cda5cd35c51224c73 + languageName: node + linkType: hard + "doctrine@npm:^3.0.0": version: 3.0.0 resolution: "doctrine@npm:3.0.0" @@ -2104,6 +2663,15 @@ __metadata: languageName: node linkType: hard +"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: "npm:^1.4.0" + checksum: 10c0/870b423afb2d54bb8d243c63e07c170409d41e20b47eeef0727547aea5740bd6717aca45597a9f2745525667a6b804c1e7bede41f856818faee5806dd9ff3975 + languageName: node + linkType: hard + "entities@npm:^4.4.0": version: 4.5.0 resolution: "entities@npm:4.5.0" @@ -2246,7 +2814,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-refresh@npm:^0.4.6": +"eslint-plugin-react-refresh@npm:^0.4.5, eslint-plugin-react-refresh@npm:^0.4.6": version: 0.4.7 resolution: "eslint-plugin-react-refresh@npm:0.4.7" peerDependencies: @@ -2272,7 +2840,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.55.0": +"eslint@npm:^8.55.0, eslint@npm:^8.56.0": version: 8.57.0 resolution: "eslint@npm:8.57.0" dependencies: @@ -2434,6 +3002,13 @@ __metadata: languageName: node linkType: hard +"fast-fifo@npm:^1.2.0, fast-fifo@npm:^1.3.2": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: 10c0/d53f6f786875e8b0529f784b59b4b05d4b5c31c651710496440006a398389a579c8dbcd2081311478b5bf77f4b0b21de69109c5a4eabea9d8e8783d1eb864e4c + languageName: node + linkType: hard + "fast-glob@npm:^3.2.7, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" @@ -2555,6 +3130,13 @@ __metadata: languageName: node linkType: hard +"fs-constants@npm:^1.0.0": + version: 1.0.0 + resolution: "fs-constants@npm:1.0.0" + checksum: 10c0/a0cde99085f0872f4d244e83e03a46aa387b74f5a5af750896c6b05e9077fac00e9932fdf5aef84f2f16634cd473c63037d7a512576da7d5c2b9163d1909f3a8 + languageName: node + linkType: hard + "fs-extra@npm:^11.1.0": version: 11.2.0 resolution: "fs-extra@npm:11.2.0" @@ -2657,6 +3239,13 @@ __metadata: languageName: node linkType: hard +"get-port@npm:^5.1.1": + version: 5.1.1 + resolution: "get-port@npm:5.1.1" + checksum: 10c0/2873877a469b24e6d5e0be490724a17edb39fafc795d1d662e7bea951ca649713b4a50117a473f9d162312cb0e946597bd0e049ed2f866e79e576e8e213d3d1c + languageName: node + linkType: hard + "get-stream@npm:^8.0.1": version: 8.0.1 resolution: "get-stream@npm:8.0.1" @@ -2698,7 +3287,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.1.3, glob@npm:^7.1.4": +"glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.2.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -2742,7 +3331,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 @@ -2838,6 +3427,13 @@ __metadata: languageName: node linkType: hard +"ieee754@npm:^1.1.13": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb + languageName: node + linkType: hard + "ignore@npm:^5.2.0, ignore@npm:^5.3.1": version: 5.3.1 resolution: "ignore@npm:5.3.1" @@ -2879,7 +3475,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2": +"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -2981,6 +3577,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: 10c0/18b5be6669be53425f0b84098732670ed4e727e3af33bc7f948aac01782110eb9a18b3b329c5323bcdd3acdaae547ee077d3951317e7f133bff7105264b3003d + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -3164,6 +3767,15 @@ __metadata: languageName: node linkType: hard +"lazystream@npm:^1.0.0": + version: 1.0.1 + resolution: "lazystream@npm:1.0.1" + dependencies: + readable-stream: "npm:^2.0.5" + checksum: 10c0/ea4e509a5226ecfcc303ba6782cc269be8867d372b9bcbd625c88955df1987ea1a20da4643bf9270336415a398d33531ebf0d5f0d393b9283dc7c98bfcbd7b69 + languageName: node + linkType: hard + "levn@npm:^0.4.1": version: 0.4.1 resolution: "levn@npm:0.4.1" @@ -3264,6 +3876,27 @@ __metadata: languageName: node linkType: hard +"lodash.defaults@npm:^4.2.0": + version: 4.2.0 + resolution: "lodash.defaults@npm:4.2.0" + checksum: 10c0/d5b77aeb702caa69b17be1358faece33a84497bcca814897383c58b28a2f8dfc381b1d9edbec239f8b425126a3bbe4916223da2a576bb0411c2cefd67df80707 + languageName: node + linkType: hard + +"lodash.difference@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.difference@npm:4.5.0" + checksum: 10c0/5d52859218a7df427547ff1fadbc397879709fe6c788b037df7d6d92b676122c92bd35ec85d364edb596b65dfc6573132f420c9b4ee22bb6b9600cd454c90637 + languageName: node + linkType: hard + +"lodash.flatten@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.flatten@npm:4.4.0" + checksum: 10c0/97e8f0d6b61fe4723c02ad0c6e67e51784c4a2c48f56ef283483e556ad01594cf9cec9c773e177bbbdbdb5d19e99b09d2487cb6b6e5dc405c2693e93b125bd3a + languageName: node + linkType: hard + "lodash.isequal@npm:4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" @@ -3285,6 +3918,13 @@ __metadata: languageName: node linkType: hard +"lodash.union@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.union@npm:4.6.0" + checksum: 10c0/6da7f72d1facd472f6090b49eefff984c9f9179e13172039c0debca6851d21d37d83c7ad5c43af23bd220f184cd80e6897e8e3206509fae491f9068b02ae6319 + languageName: node + linkType: hard + "log-update@npm:^6.0.0": version: 6.0.0 resolution: "log-update@npm:6.0.0" @@ -3458,36 +4098,6 @@ __metadata: languageName: node linkType: hard -"minimal-example@workspace:examples/ts-client/minimal": - version: 0.0.0-use.local - resolution: "minimal-example@workspace:examples/ts-client/minimal" - dependencies: - "@fishjam-dev/ts-client": "npm:*" - autoprefixer: "npm:^10.4.17" - typescript: "npm:^5.4.0" - vite: "npm:^5.1.2" - vite-plugin-checker: "npm:^0.6.4" - languageName: unknown - linkType: soft - -"minimal-react-example@workspace:examples/react-client/minimal-react": - version: 0.0.0-use.local - resolution: "minimal-react-example@workspace:examples/react-client/minimal-react" - dependencies: - "@fishjam-dev/react-client": "npm:*" - "@types/react": "npm:^18.2.55" - "@types/react-dom": "npm:^18.2.19" - "@vitejs/plugin-react-swc": "npm:^3.6.0" - autoprefixer: "npm:^10.4.17" - postcss: "npm:^8.4.39" - react: "npm:^18.2.0" - react-dom: "npm:^18.2.0" - typescript: "npm:^5.4.0" - vite: "npm:^5.1.2" - vite-plugin-checker: "npm:^0.6.4" - languageName: unknown - linkType: soft - "minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -3497,6 +4107,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^5.1.0": + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 + languageName: node + linkType: hard + "minimatch@npm:^9.0.4": version: 9.0.4 resolution: "minimatch@npm:9.0.4" @@ -3599,7 +4218,14 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.3": +"mkdirp-classic@npm:^0.5.2": + version: 0.5.3 + resolution: "mkdirp-classic@npm:0.5.3" + checksum: 10c0/95371d831d196960ddc3833cc6907e6b8f67ac5501a6582f47dfae5eb0f092e9f8ce88e0d83afcae95d6e2b61a01741ba03714eeafb6f7a6e9dcc158ac85b168 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" bin: @@ -3638,6 +4264,15 @@ __metadata: languageName: node linkType: hard +"nan@npm:^2.18.0, nan@npm:^2.19.0": + version: 2.20.0 + resolution: "nan@npm:2.20.0" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/75775309a21ad179a55250d62ce47322c33ca03d8ddb5ad4c555bd820dd72484b3c59253dd9f41cc68dd63453ef04017407fbd081a549bc030d977079bb798b7 + languageName: node + linkType: hard + "nanoid@npm:^3.3.7": version: 3.3.7 resolution: "nanoid@npm:3.3.7" @@ -3661,6 +4296,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^2.7.0": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 + languageName: node + linkType: hard + "node-gyp@npm:latest": version: 10.1.0 resolution: "node-gyp@npm:10.1.0" @@ -3745,7 +4394,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -3961,6 +4610,15 @@ __metadata: languageName: node linkType: hard +"playwright-core@npm:1.45.1": + version: 1.45.1 + resolution: "playwright-core@npm:1.45.1" + bin: + playwright-core: cli.js + checksum: 10c0/607ad31ce1e85e2042107954eeed2cb7de5f387b42d9c8c19baa5c1ea4c2ea621bf233094ed86be45de625eeece33b280847ff641ff1bb9acaddee040e17bea1 + languageName: node + linkType: hard + "playwright@npm:1.44.1": version: 1.44.1 resolution: "playwright@npm:1.44.1" @@ -3976,6 +4634,21 @@ __metadata: languageName: node linkType: hard +"playwright@npm:1.45.1": + version: 1.45.1 + resolution: "playwright@npm:1.45.1" + dependencies: + fsevents: "npm:2.3.2" + playwright-core: "npm:1.45.1" + dependenciesMeta: + fsevents: + optional: true + bin: + playwright: cli.js + checksum: 10c0/549e8621b120258ff53e93fcf3b2994a835aa084097ea533a9f4b53ff993308f3617cf00943c6975f88b66068890a6bf9d61b4ffdd73b7d8f45a5d284b6f284b + languageName: node + linkType: hard + "postcss-import@npm:^15.1.0": version: 15.1.0 resolution: "postcss-import@npm:15.1.0" @@ -4174,6 +4847,13 @@ __metadata: languageName: node linkType: hard +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 10c0/bec089239487833d46b59d80327a1605e1c5287eaad770a291add7f45fda1bb5e28b38e0e061add0a1d0ee0984788ce74fa394d345eed1c420cacf392c554367 + languageName: node + linkType: hard + "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -4184,7 +4864,27 @@ __metadata: languageName: node linkType: hard -"protobufjs@npm:^7.2.4, protobufjs@npm:^7.3.0": +"proper-lockfile@npm:^4.1.2": + version: 4.1.2 + resolution: "proper-lockfile@npm:4.1.2" + dependencies: + graceful-fs: "npm:^4.2.4" + retry: "npm:^0.12.0" + signal-exit: "npm:^3.0.2" + checksum: 10c0/2f265dbad15897a43110a02dae55105c04d356ec4ed560723dcb9f0d34bc4fb2f13f79bb930e7561be10278e2314db5aca2527d5d3dcbbdee5e6b331d1571f6d + languageName: node + linkType: hard + +"properties-reader@npm:^2.3.0": + version: 2.3.0 + resolution: "properties-reader@npm:2.3.0" + dependencies: + mkdirp: "npm:^1.0.4" + checksum: 10c0/f665057e3a9076c643ba1198afcc71703eda227a59913252f7ff9467ece8d29c0cf8bf14bf1abcaef71570840c32a4e257e6c39b7550451bbff1a777efcf5667 + languageName: node + linkType: hard + +"protobufjs@npm:^7.2.4, protobufjs@npm:^7.2.6, protobufjs@npm:^7.3.0": version: 7.3.2 resolution: "protobufjs@npm:7.3.2" dependencies: @@ -4204,6 +4904,16 @@ __metadata: languageName: node linkType: hard +"pump@npm:^3.0.0": + version: 3.0.0 + resolution: "pump@npm:3.0.0" + dependencies: + end-of-stream: "npm:^1.1.0" + once: "npm:^1.3.1" + checksum: 10c0/bbdeda4f747cdf47db97428f3a135728669e56a0ae5f354a9ac5b74556556f5446a46f720a8f14ca2ece5be9b4d5d23c346db02b555f46739934cc6c093a5478 + languageName: node + linkType: hard + "punycode.js@npm:^2.3.1": version: 2.3.1 resolution: "punycode.js@npm:2.3.1" @@ -4225,6 +4935,13 @@ __metadata: languageName: node linkType: hard +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 10c0/0db998e2c9b15215317dbcf801e9b23e6bcde4044e115155dae34f8e7454b9a783f737c9a725528d677b7a66c775eb7a955cf144fe0b87f62b575ce5bfd515a9 + languageName: node + linkType: hard + "react-dom@npm:^18.2.0": version: 18.3.1 resolution: "react-dom@npm:18.3.1" @@ -4269,6 +4986,41 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.5": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: "npm:~1.0.0" + inherits: "npm:~2.0.3" + isarray: "npm:~1.0.0" + process-nextick-args: "npm:~2.0.0" + safe-buffer: "npm:~5.1.1" + string_decoder: "npm:~1.1.1" + util-deprecate: "npm:~1.0.1" + checksum: 10c0/7efdb01f3853bc35ac62ea25493567bf588773213f5f4a79f9c365e1ad13bab845ac0dae7bc946270dc40c3929483228415e92a3fc600cc7e4548992f41ee3fa + languageName: node + linkType: hard + +"readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + +"readdir-glob@npm:^1.1.2": + version: 1.1.3 + resolution: "readdir-glob@npm:1.1.3" + dependencies: + minimatch: "npm:^5.1.0" + checksum: 10c0/a37e0716726650845d761f1041387acd93aa91b28dd5381950733f994b6c349ddc1e21e266ec7cc1f9b92e205a7a972232f9b89d5424d07361c2c3753d5dbace + languageName: node + linkType: hard + "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -4434,7 +5186,21 @@ __metadata: languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3.0.0": +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 + languageName: node + linkType: hard + +"safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:~2.1.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 @@ -4514,21 +5280,6 @@ __metadata: languageName: node linkType: hard -"simple-app-example@workspace:examples/ts-client/simple-app": - version: 0.0.0-use.local - resolution: "simple-app-example@workspace:examples/ts-client/simple-app" - dependencies: - "@fishjam-dev/ts-client": "npm:*" - autoprefixer: "npm:^10.4.17" - daisyui: "npm:^4.7.2" - postcss: "npm:^8.4.39" - tailwindcss: "npm:^3.4.1" - typescript: "npm:^5.4.0" - vite: "npm:^5.1.2" - vite-plugin-checker: "npm:^0.6.4" - languageName: unknown - linkType: soft - "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -4591,6 +5342,13 @@ __metadata: languageName: node linkType: hard +"split-ca@npm:^1.0.1": + version: 1.0.1 + resolution: "split-ca@npm:1.0.1" + checksum: 10c0/f339170b84c6b4706fcf4c60cc84acb36574c0447566bd713301a8d9b4feff7f4627efc8c334bec24944a3e2f35bc596bd58c673c9980d6bfe3137aae1116ba7 + languageName: node + linkType: hard + "sprintf-js@npm:^1.1.3": version: 1.1.3 resolution: "sprintf-js@npm:1.1.3" @@ -4598,6 +5356,33 @@ __metadata: languageName: node linkType: hard +"ssh-remote-port-forward@npm:^1.0.4": + version: 1.0.4 + resolution: "ssh-remote-port-forward@npm:1.0.4" + dependencies: + "@types/ssh2": "npm:^0.5.48" + ssh2: "npm:^1.4.0" + checksum: 10c0/33a441af12817577ea30d089b03c19f980d2fb2370933123a35026dc6be40f2dfce067e4dfc173e23d745464537ff647aa1bb7469be5571cc21f7cdb25181c09 + languageName: node + linkType: hard + +"ssh2@npm:^1.11.0, ssh2@npm:^1.4.0": + version: 1.15.0 + resolution: "ssh2@npm:1.15.0" + dependencies: + asn1: "npm:^0.2.6" + bcrypt-pbkdf: "npm:^1.0.2" + cpu-features: "npm:~0.0.9" + nan: "npm:^2.18.0" + dependenciesMeta: + cpu-features: + optional: true + nan: + optional: true + checksum: 10c0/7c76888fbfa1c15660cf51086a6e5699b3c1caad516e29adb1d2a00fc1ef6b48946ca7ec811b4bb50456984967c4346115c7ddd3dbf981a1193bd1f40fa4529a + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.6 resolution: "ssri@npm:10.0.6" @@ -4621,6 +5406,21 @@ __metadata: languageName: node linkType: hard +"streamx@npm:^2.15.0, streamx@npm:^2.18.0": + version: 2.18.0 + resolution: "streamx@npm:2.18.0" + dependencies: + bare-events: "npm:^2.2.0" + fast-fifo: "npm:^1.3.2" + queue-tick: "npm:^1.0.1" + text-decoder: "npm:^1.1.0" + dependenciesMeta: + bare-events: + optional: true + checksum: 10c0/ef50f419252a73dd35abcde72329eafbf5ad9cd2e27f0cc3abebeff6e0dbea124ac6d3e16acbdf081cce41b4125393ac22f9848fcfa19e640830734883e622ba + languageName: node + linkType: hard + "string-argv@npm:~0.3.2": version: 0.3.2 resolution: "string-argv@npm:0.3.2" @@ -4661,6 +5461,24 @@ __metadata: languageName: node linkType: hard +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: "npm:~5.2.0" + checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d + languageName: node + linkType: hard + +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: "npm:~5.1.0" + checksum: 10c0/b4f89f3a92fd101b5653ca3c99550e07bdf9e13b35037e9e2a1c7b47cec4e55e06ff3fc468e314a0b5e80bfbaf65c1ca5a84978764884ae9413bec1fc6ca924e + languageName: node + linkType: hard + "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" @@ -4778,6 +5596,59 @@ __metadata: languageName: node linkType: hard +"tar-fs@npm:^3.0.6": + version: 3.0.6 + resolution: "tar-fs@npm:3.0.6" + dependencies: + bare-fs: "npm:^2.1.1" + bare-path: "npm:^2.1.0" + pump: "npm:^3.0.0" + tar-stream: "npm:^3.1.5" + dependenciesMeta: + bare-fs: + optional: true + bare-path: + optional: true + checksum: 10c0/207b7c0f193495668bd9dbad09a0108ce4ffcfec5bce2133f90988cdda5c81fad83c99f963d01e47b565196594f7a17dbd063ae55b97b36268fcc843975278ee + languageName: node + linkType: hard + +"tar-fs@npm:~2.0.1": + version: 2.0.1 + resolution: "tar-fs@npm:2.0.1" + dependencies: + chownr: "npm:^1.1.1" + mkdirp-classic: "npm:^0.5.2" + pump: "npm:^3.0.0" + tar-stream: "npm:^2.0.0" + checksum: 10c0/0128e888b61c7c4e8e7997d66ceccc3c79d73c01e87cfcc3d9f6b8555b0c88b8d67d91ff167f00b067f726dde497b2d1fb2bba0cfcb3ccb95ae413cb86c715bc + languageName: node + linkType: hard + +"tar-stream@npm:^2.0.0, tar-stream@npm:^2.2.0": + version: 2.2.0 + resolution: "tar-stream@npm:2.2.0" + dependencies: + bl: "npm:^4.0.3" + end-of-stream: "npm:^1.4.1" + fs-constants: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^3.1.1" + checksum: 10c0/2f4c910b3ee7196502e1ff015a7ba321ec6ea837667220d7bcb8d0852d51cb04b87f7ae471008a6fb8f5b1a1b5078f62f3a82d30c706f20ada1238ac797e7692 + languageName: node + linkType: hard + +"tar-stream@npm:^3.1.5": + version: 3.1.7 + resolution: "tar-stream@npm:3.1.7" + dependencies: + b4a: "npm:^1.6.4" + fast-fifo: "npm:^1.2.0" + streamx: "npm:^2.15.0" + checksum: 10c0/a09199d21f8714bd729993ac49b6c8efcb808b544b89f23378ad6ffff6d1cb540878614ba9d4cfec11a64ef39e1a6f009a5398371491eb1fda606ffc7f70f718 + languageName: node + linkType: hard + "tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.2.1 resolution: "tar@npm:6.2.1" @@ -4803,6 +5674,38 @@ __metadata: languageName: node linkType: hard +"testcontainers@npm:^10.3.2": + version: 10.10.0 + resolution: "testcontainers@npm:10.10.0" + dependencies: + "@balena/dockerignore": "npm:^1.0.2" + "@types/dockerode": "npm:^3.3.29" + archiver: "npm:^5.3.2" + async-lock: "npm:^1.4.1" + byline: "npm:^5.0.0" + debug: "npm:^4.3.5" + docker-compose: "npm:^0.24.8" + dockerode: "npm:^3.3.5" + get-port: "npm:^5.1.1" + node-fetch: "npm:^2.7.0" + proper-lockfile: "npm:^4.1.2" + properties-reader: "npm:^2.3.0" + ssh-remote-port-forward: "npm:^1.0.4" + tar-fs: "npm:^3.0.6" + tmp: "npm:^0.2.3" + checksum: 10c0/5cf4ae3001430cd5e8ad0a81bf00956274efe3be987e970ebe47403c31dec8daea2b292f889a5d0778297d56a70d807a8cd50504e9f06778ffe0ab2ed9c6eea1 + languageName: node + linkType: hard + +"text-decoder@npm:^1.1.0": + version: 1.1.0 + resolution: "text-decoder@npm:1.1.0" + dependencies: + b4a: "npm:^1.6.4" + checksum: 10c0/623a6cfb5ee86c250fea31f369a0d40e4ef5c2c32ce8db43492648b51193858213e61bf47a6078f285053715dcc6342806ce6ea9a49d7847ffca282ca88ad7e8 + languageName: node + linkType: hard + "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -4856,6 +5759,13 @@ __metadata: languageName: node linkType: hard +"tmp@npm:^0.2.3": + version: 0.2.3 + resolution: "tmp@npm:0.2.3" + checksum: 10c0/3e809d9c2f46817475b452725c2aaa5d11985cf18d32a7a970ff25b568438e2c076c2e8609224feef3b7923fa9749b74428e3e634f6b8e520c534eef2fd24125 + languageName: node + linkType: hard + "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -4872,6 +5782,13 @@ __metadata: languageName: node linkType: hard +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 + languageName: node + linkType: hard + "ts-api-utils@npm:^1.3.0": version: 1.3.0 resolution: "ts-api-utils@npm:1.3.0" @@ -4928,6 +5845,13 @@ __metadata: languageName: node linkType: hard +"tweetnacl@npm:^0.14.3": + version: 0.14.5 + resolution: "tweetnacl@npm:0.14.5" + checksum: 10c0/4612772653512c7bc19e61923fbf42903f5e0389ec76a4a1f17195859d114671ea4aa3b734c2029ce7e1fa7e5cc8b80580f67b071ecf0b46b5636d030a0102a2 + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -5016,6 +5940,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.4.5": + version: 5.5.3 + resolution: "typescript@npm:5.5.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/f52c71ccbc7080b034b9d3b72051d563601a4815bf3e39ded188e6ce60813f75dbedf11ad15dd4d32a12996a9ed8c7155b46c93a9b9c9bad1049766fe614bbdd + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A^5.4.0#optional!builtin": version: 5.4.5 resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c" @@ -5026,6 +5960,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.4.5#optional!builtin": + version: 5.5.3 + resolution: "typescript@patch:typescript@npm%3A5.5.3#optional!builtin::version=5.5.3&hash=b45daf" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/5a437c416251334deeaf29897157032311f3f126547cfdc4b133768b606cb0e62bcee733bb97cf74c42fe7268801aea1392d8e40988cdef112e9546eba4c03c5 + languageName: node + linkType: hard + "uc.micro@npm:^2.0.0, uc.micro@npm:^2.1.0": version: 2.1.0 resolution: "uc.micro@npm:2.1.0" @@ -5117,7 +6061,7 @@ __metadata: languageName: unknown linkType: soft -"util-deprecate@npm:^1.0.2": +"util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 @@ -5348,6 +6292,23 @@ __metadata: languageName: node linkType: hard +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: "npm:~0.0.3" + webidl-conversions: "npm:^3.0.0" + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -5443,7 +6404,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.3.4, yaml@npm:^2.4.5, yaml@npm:~2.4.2": +"yaml@npm:^2.2.2, yaml@npm:^2.3.4, yaml@npm:^2.4.5, yaml@npm:~2.4.2": version: 2.4.5 resolution: "yaml@npm:2.4.5" bin: @@ -5466,6 +6427,17 @@ __metadata: languageName: node linkType: hard +"zip-stream@npm:^4.1.0": + version: 4.1.1 + resolution: "zip-stream@npm:4.1.1" + dependencies: + archiver-utils: "npm:^3.0.4" + compress-commons: "npm:^4.1.2" + readable-stream: "npm:^3.6.0" + checksum: 10c0/38f91ca116a38561cf184c29e035e9453b12c30eaf574e0993107a4a5331882b58c9a7f7b97f63910664028089fbde3296d0b3682d1ccb2ad96929e68f1b2b89 + languageName: node + linkType: hard + "zod@npm:^3.22.4, zod@npm:^3.23.6": version: 3.23.8 resolution: "zod@npm:3.23.8" From b89cf0f3640465562ab6bbf8560790ba602418b9 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 4 Jul 2024 15:49:39 +0200 Subject: [PATCH 4/9] Refactor --- packages/ts-client/src/webrtc/transceivers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ts-client/src/webrtc/transceivers.ts b/packages/ts-client/src/webrtc/transceivers.ts index 55c24b4a..adf53c0a 100644 --- a/packages/ts-client/src/webrtc/transceivers.ts +++ b/packages/ts-client/src/webrtc/transceivers.ts @@ -15,13 +15,13 @@ export const getMidToTrackId = ( // - negotiated unmuted tracks: tracks added in previous negotiation, data is being transmitted // - not yet negotiated tracks: tracks added in this negotiation, data will be transmitted after successful negotiation - const transceiver = getTransceiverMapping(connection, localTrackIdToTrack) + const mappingFromTransceivers = getTransceiverMapping(connection, localTrackIdToTrack) // - negotiated unmuted tracks: tracks added in previous negotiation, data is being transmitted // - negotiated muted tracks: tracks added in previous negotiation, data is not being transmitted but can be transmitted in the future - const allNegotiated = getAllNegotiatedLocalTracksMapping(midToTrackId, localEndpoint) + const mappingFromLocalNegotiatedTracks = getAllNegotiatedLocalTracksMapping(midToTrackId, localEndpoint) - return { ...transceiver, ...allNegotiated }; + return { ...mappingFromTransceivers, ...mappingFromLocalNegotiatedTracks }; }; const getTrackContext = (localTrackIdToTrack: Map>, localTrackId: string) => Array.from(localTrackIdToTrack.values()).find( From 8d71dbf9542881a26a5922986dd32d0d872386d6 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 4 Jul 2024 15:59:21 +0200 Subject: [PATCH 5/9] Fix ts-simple-example --- examples/ts-client/simple-app/src/main.ts | 39 +++++++++++++---------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/examples/ts-client/simple-app/src/main.ts b/examples/ts-client/simple-app/src/main.ts index 13cbae04..16edc39e 100644 --- a/examples/ts-client/simple-app/src/main.ts +++ b/examples/ts-client/simple-app/src/main.ts @@ -3,11 +3,15 @@ import "./style.css"; import { createStream } from "./createMockStream"; import type { TrackEncoding, Peer } from "@fishjam-dev/ts-client"; import { FishjamClient } from "@fishjam-dev/ts-client"; -import { - enumerateDevices, - getUserMedia, - SCREEN_SHARING_MEDIA_CONSTRAINTS, -} from "@fishjam-dev/browser-media-utils"; + +const SCREEN_SHARING_MEDIA_CONSTRAINTS = { + video: { + frameRate: { ideal: 20, max: 25 }, + width: { max: 1920, ideal: 1920 }, + height: { max: 1080, ideal: 1080 }, + }, +}; + /* eslint-disable no-console */ @@ -205,7 +209,8 @@ client.on("peerJoined", (peer: Peer) => { toastInfo(`New peer joined`); }); -client.on("peerUpdated", (_peer) => {}); +client.on("peerUpdated", (_peer) => { +}); client.on("peerLeft", (peer) => { const peerComponent = document.querySelector( @@ -334,7 +339,8 @@ client.on("trackAdded", (ctx) => { )!; activeEncodingElement.innerHTML = ctx.encoding ?? ""; }); - ctx.on("voiceActivityChanged", () => {}); + ctx.on("voiceActivityChanged", () => { + }); }); client.on("trackRemoved", (ctx) => { @@ -344,11 +350,14 @@ client.on("trackRemoved", (ctx) => { tracksContainer?.remove(); }); -client.on("trackUpdated", (_ctx) => {}); +client.on("trackUpdated", (_ctx) => { +}); -client.on("bandwidthEstimationChanged", (_estimation) => {}); +client.on("bandwidthEstimationChanged", (_estimation) => { +}); -client.on("tracksPriorityChanged", (_enabledTracks, _disabledTracks) => {}); +client.on("tracksPriorityChanged", (_enabledTracks, _disabledTracks) => { +}); connectButton.addEventListener("click", () => { console.log("Connect"); @@ -411,16 +420,14 @@ removeTrackButton.addEventListener("click", () => { localVideo.classList.remove(...borderActiveClasses); }); -enumerateDevicesButton.addEventListener("click", () => { - enumerateDevices(true, false).then((result) => { +enumerateDevicesButton.addEventListener("click", async () => { + navigator.mediaDevices.enumerateDevices().then((result) => { console.log(result); - if (result.video.type !== "OK") return; - const videoPlayers = document.querySelector("#video-players")!; videoPlayers.innerHTML = ""; // Video devices views - result.video.devices.forEach((device) => { + result.forEach((device) => { const clone = // @ts-ignore templateVideoPlayer.content.firstElementChild.cloneNode(true); @@ -433,7 +440,7 @@ enumerateDevicesButton.addEventListener("click", () => { .querySelector(".start-template-btn") .addEventListener("click", () => { console.log("Start"); - getUserMedia(device.deviceId, "video").then((stream) => { + navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => { console.log("Connecting stream"); videoPlayer.srcObject = stream; videoPlayer.play(); From 810935bec86002c2ad417ee3b5ae876d7df46122 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 4 Jul 2024 16:13:40 +0200 Subject: [PATCH 6/9] Fix eslint --- e2e-tests/ts-client/app/package.json | 5 ++- e2e-tests/ts-client/app/src/App.tsx | 37 ++++++++++--------- e2e-tests/ts-client/app/src/MockComponent.tsx | 11 +++++- e2e-tests/ts-client/app/src/MuteTrackTest.tsx | 6 +-- .../app/src/VideoPlayerWithDetector.tsx | 17 +++++---- packages/react-client/src/DeviceManager.ts | 2 +- packages/ts-client/src/webrtc/transceivers.ts | 4 +- 7 files changed, 48 insertions(+), 34 deletions(-) diff --git a/e2e-tests/ts-client/app/package.json b/e2e-tests/ts-client/app/package.json index 8934da96..b8e50294 100644 --- a/e2e-tests/ts-client/app/package.json +++ b/e2e-tests/ts-client/app/package.json @@ -7,7 +7,10 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "format": "prettier --write . --ignore-path ./.eslintignore", + "format:check": "prettier --check . --ignore-path ./.eslintignore", + "lint": "eslint . --ext .ts,.tsx --fix", + "lint:check": "eslint . --ext .ts,.tsx", "e2e": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test", "e2e:ui": "NODE_OPTIONS=--dns-result-order=ipv4first playwright test --ui", "preview": "vite preview" diff --git a/e2e-tests/ts-client/app/src/App.tsx b/e2e-tests/ts-client/app/src/App.tsx index ec3f48d4..ce111b00 100644 --- a/e2e-tests/ts-client/app/src/App.tsx +++ b/e2e-tests/ts-client/app/src/App.tsx @@ -1,13 +1,15 @@ -import { +import type { Endpoint, SerializedMediaEvent, TrackContext, TrackEncoding, - WebRTCEndpoint, WebRTCEndpointEvents, TrackContextEvents, BandwidthLimit, - SimulcastConfig, + SimulcastConfig +} from '@fishjam-dev/ts-client'; +import { + WebRTCEndpoint } from '@fishjam-dev/ts-client'; import { PeerMessage } from '@fishjam-dev/ts-client/protos'; import { useEffect, useState, useSyncExternalStore } from 'react'; @@ -24,7 +26,7 @@ export type TrackMetadata = { goodTrack: string; }; -function endpointMetadataParser(a: any): EndpointMetadata { +function endpointMetadataParser(a: unknown): EndpointMetadata { if ( typeof a !== 'object' || a === null || @@ -35,7 +37,7 @@ function endpointMetadataParser(a: any): EndpointMetadata { return { goodStuff: a.goodStuff }; } -function trackMetadataParser(a: any): TrackMetadata { +function trackMetadataParser(a: unknown): TrackMetadata { if ( typeof a !== 'object' || a === null || @@ -58,7 +60,8 @@ class RemoteStore { constructor( private webrtc: WebRTCEndpoint, - ) {} + ) { + } subscribe(callback: () => void) { const cb = () => { @@ -154,7 +157,7 @@ function connect(token: string, metadata: EndpointMetadata) { websocket.send(message); }); - const messageHandler = (event: MessageEvent) => { + const messageHandler = (event: MessageEvent) => { /* eslint-disable-line @typescript-eslint/no-explicit-any */ const uint8Array = new Uint8Array(event.data); try { const data = PeerMessage.decode(uint8Array); @@ -186,19 +189,19 @@ function connect(token: string, metadata: EndpointMetadata) { websocket.addEventListener('message', messageHandler); - const closeHandler = (event: any) => { + const closeHandler = (event: unknown) => { console.log({ name: 'Close handler!', event }); }; websocket.addEventListener('close', closeHandler); - const errorHandler = (event: any) => { + const errorHandler = (event: unknown) => { console.log({ name: 'Error handler!', event }); }; websocket.addEventListener('error', errorHandler); - const trackReady = (event: any) => { + const trackReady = (event: unknown) => { console.log({ name: 'trackReady', event }); }; @@ -289,13 +292,13 @@ export function App() {
{Object.values(remoteTracks).map( ({ - stream, - trackId, - endpoint, - metadata, - rawMetadata, - metadataParsingError, - }) => ( + stream, + trackId, + endpoint, + metadata, + rawMetadata, + metadataParsingError, + }) => (
{ const getTrackIdentifierToInboundRtp = ( stats: RTCStatsReport, -): Record => { - const result: Record = {}; +): Record => { /* eslint-disable-line @typescript-eslint/no-explicit-any */ + const result: Record = {}; stats.forEach((report) => { if (report.type === 'inbound-rtp') { @@ -43,7 +44,7 @@ export const VideoPlayerWithDetector = ({ stream, id, webrtc }: Props) => { videoElementRef.current.srcObject = stream || null; }, [stream]); - const getDecodedFrames = async () => { + const getDecodedFrames = useCallback(async () => { const connection = webrtc['connection']; if (!connection) return 0; @@ -52,7 +53,7 @@ export const VideoPlayerWithDetector = ({ stream, id, webrtc }: Props) => { const trackId = stream?.getVideoTracks()?.[0]?.id ?? ''; return inbound[trackId]?.framesDecoded ?? 0; - }; + }, [stream, webrtc]); useEffect(() => { const id = setInterval(async () => { @@ -62,7 +63,7 @@ export const VideoPlayerWithDetector = ({ stream, id, webrtc }: Props) => { return () => { clearInterval(id); }; - }, [stream]); + }, [getDecodedFrames, stream]); useEffect(() => { const id = setInterval(() => { diff --git a/packages/react-client/src/DeviceManager.ts b/packages/react-client/src/DeviceManager.ts index d5df1522..bd6785ba 100644 --- a/packages/react-client/src/DeviceManager.ts +++ b/packages/react-client/src/DeviceManager.ts @@ -24,7 +24,7 @@ import { import EventEmitter from "events"; import type TypedEmitter from "typed-emitter"; import type { TrackType } from "./ScreenShareManager"; -import { TrackKind } from "@fishjam-dev/ts-client"; +import type { TrackKind } from "@fishjam-dev/ts-client"; const removeExact = ( trackConstraints: boolean | MediaTrackConstraints | undefined, diff --git a/packages/ts-client/src/webrtc/transceivers.ts b/packages/ts-client/src/webrtc/transceivers.ts index adf53c0a..abdcdb80 100644 --- a/packages/ts-client/src/webrtc/transceivers.ts +++ b/packages/ts-client/src/webrtc/transceivers.ts @@ -1,5 +1,5 @@ -import { EndpointWithTrackContext, TrackContextImpl } from "./internal"; -import { RemoteTrackId } from "./types"; +import type { EndpointWithTrackContext, TrackContextImpl } from "./internal"; +import type { RemoteTrackId } from "./types"; type Mid = string type TrackId = string; From 56e8fb4b9da2e7d769cc27851083519d69817740 Mon Sep 17 00:00:00 2001 From: Kamil Stasiak Date: Thu, 4 Jul 2024 16:15:17 +0200 Subject: [PATCH 7/9] Fix format --- e2e-tests/ts-client/app/playwright.config.ts | 36 ++-- e2e-tests/ts-client/app/src/App.tsx | 176 +++++++++--------- e2e-tests/ts-client/app/src/MockComponent.tsx | 36 ++-- e2e-tests/ts-client/app/src/MuteTrackTest.tsx | 59 +++--- e2e-tests/ts-client/app/src/VideoPlayer.tsx | 4 +- .../app/src/VideoPlayerWithDetector.tsx | 39 ++-- e2e-tests/ts-client/app/src/main.tsx | 8 +- e2e-tests/ts-client/app/src/mocks.ts | 10 +- e2e-tests/ts-client/app/tsconfig.json | 10 +- e2e-tests/ts-client/app/vite.config.ts | 4 +- examples/ts-client/simple-app/src/main.ts | 28 ++- packages/ts-client/src/webrtc/bitrate.ts | 7 +- packages/ts-client/src/webrtc/index.ts | 2 +- packages/ts-client/src/webrtc/transceivers.ts | 74 +++++--- .../ts-client/src/webrtc/webRTCEndpoint.ts | 20 +- 15 files changed, 276 insertions(+), 237 deletions(-) diff --git a/e2e-tests/ts-client/app/playwright.config.ts b/e2e-tests/ts-client/app/playwright.config.ts index ba6defc6..70533a27 100644 --- a/e2e-tests/ts-client/app/playwright.config.ts +++ b/e2e-tests/ts-client/app/playwright.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; /** * Read environment variables from file. @@ -10,7 +10,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: '../.', + testDir: "../.", /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ @@ -21,32 +21,38 @@ export default defineConfig({ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: [ - ['list'], - ['html', { outputFolder: '../../../playwright-report/ts-client-e2e', open: "never" }] + ["list"], + [ + "html", + { + outputFolder: "../../../playwright-report/ts-client-e2e", + open: "never", + }, + ], ], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://localhost:5173', + baseURL: "http://localhost:5173", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', + trace: "on-first-retry", extraHTTPHeaders: { - Authorization: 'Bearer development', + Authorization: "Bearer development", }, }, /* Configure projects for major browsers */ projects: [ { - name: 'chromium', + name: "chromium", use: { - ...devices['Desktop Chrome'], + ...devices["Desktop Chrome"], launchOptions: { args: [ - '--use-fake-ui-for-media-stream', - '--use-fake-device-for-media-stream', + "--use-fake-ui-for-media-stream", + "--use-fake-device-for-media-stream", ], // default Google Chrome path on MacOS // executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", @@ -57,11 +63,11 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: { - command: 'yarn run dev', - url: 'http://localhost:5173', + command: "yarn run dev", + url: "http://localhost:5173", reuseExistingServer: !process.env.CI, }, - globalSetup: '../setup/setupFishjam', - globalTeardown: '../setup/teardownFishjam', + globalSetup: "../setup/setupFishjam", + globalTeardown: "../setup/teardownFishjam", }); diff --git a/e2e-tests/ts-client/app/src/App.tsx b/e2e-tests/ts-client/app/src/App.tsx index ce111b00..1fec1c7c 100644 --- a/e2e-tests/ts-client/app/src/App.tsx +++ b/e2e-tests/ts-client/app/src/App.tsx @@ -6,15 +6,13 @@ import type { WebRTCEndpointEvents, TrackContextEvents, BandwidthLimit, - SimulcastConfig -} from '@fishjam-dev/ts-client'; -import { - WebRTCEndpoint -} from '@fishjam-dev/ts-client'; -import { PeerMessage } from '@fishjam-dev/ts-client/protos'; -import { useEffect, useState, useSyncExternalStore } from 'react'; -import { MockComponent } from './MockComponent'; -import { VideoPlayerWithDetector } from './VideoPlayerWithDetector'; + SimulcastConfig, +} from "@fishjam-dev/ts-client"; +import { WebRTCEndpoint } from "@fishjam-dev/ts-client"; +import { PeerMessage } from "@fishjam-dev/ts-client/protos"; +import { useEffect, useState, useSyncExternalStore } from "react"; +import { MockComponent } from "./MockComponent"; +import { VideoPlayerWithDetector } from "./VideoPlayerWithDetector"; /* eslint-disable no-console */ @@ -28,23 +26,23 @@ export type TrackMetadata = { function endpointMetadataParser(a: unknown): EndpointMetadata { if ( - typeof a !== 'object' || + typeof a !== "object" || a === null || - !('goodStuff' in a) || - typeof a.goodStuff !== 'string' + !("goodStuff" in a) || + typeof a.goodStuff !== "string" ) - throw 'Invalid metadata!!!'; + throw "Invalid metadata!!!"; return { goodStuff: a.goodStuff }; } function trackMetadataParser(a: unknown): TrackMetadata { if ( - typeof a !== 'object' || + typeof a !== "object" || a === null || - !('goodTrack' in a) || - typeof a.goodTrack !== 'string' + !("goodTrack" in a) || + typeof a.goodTrack !== "string" ) - throw 'Invalid track metadata!!!'; + throw "Invalid track metadata!!!"; return { goodTrack: a.goodTrack }; } @@ -60,8 +58,7 @@ class RemoteStore { constructor( private webrtc: WebRTCEndpoint, - ) { - } + ) {} subscribe(callback: () => void) { const cb = () => { @@ -72,14 +69,14 @@ class RemoteStore { const trackCb: TrackContextEvents< EndpointMetadata, TrackMetadata - >['encodingChanged'] = () => cb(); + >["encodingChanged"] = () => cb(); const trackAddedCb: WebRTCEndpointEvents< EndpointMetadata, TrackMetadata - >['trackAdded'] = (context) => { - context.on('encodingChanged', () => trackCb); - context.on('voiceActivityChanged', () => trackCb); + >["trackAdded"] = (context) => { + context.on("encodingChanged", () => trackCb); + context.on("voiceActivityChanged", () => trackCb); callback(); }; @@ -87,29 +84,29 @@ class RemoteStore { const removeCb: WebRTCEndpointEvents< EndpointMetadata, TrackMetadata - >['trackRemoved'] = (context) => { - context.removeListener('encodingChanged', () => trackCb); - context.removeListener('voiceActivityChanged', () => trackCb); + >["trackRemoved"] = (context) => { + context.removeListener("encodingChanged", () => trackCb); + context.removeListener("voiceActivityChanged", () => trackCb); callback(); }; - this.webrtc.on('trackAdded', trackAddedCb); - this.webrtc.on('trackReady', cb); - this.webrtc.on('trackUpdated', cb); - this.webrtc.on('trackRemoved', removeCb); - this.webrtc.on('endpointAdded', cb); - this.webrtc.on('endpointRemoved', cb); - this.webrtc.on('endpointUpdated', cb); + this.webrtc.on("trackAdded", trackAddedCb); + this.webrtc.on("trackReady", cb); + this.webrtc.on("trackUpdated", cb); + this.webrtc.on("trackRemoved", removeCb); + this.webrtc.on("endpointAdded", cb); + this.webrtc.on("endpointRemoved", cb); + this.webrtc.on("endpointUpdated", cb); return () => { - this.webrtc.removeListener('trackAdded', trackAddedCb); - this.webrtc.removeListener('trackReady', cb); - this.webrtc.removeListener('trackUpdated', cb); - this.webrtc.removeListener('trackRemoved', removeCb); - this.webrtc.removeListener('endpointAdded', cb); - this.webrtc.removeListener('endpointRemoved', cb); - this.webrtc.removeListener('endpointUpdated', cb); + this.webrtc.removeListener("trackAdded", trackAddedCb); + this.webrtc.removeListener("trackReady", cb); + this.webrtc.removeListener("trackUpdated", cb); + this.webrtc.removeListener("trackRemoved", removeCb); + this.webrtc.removeListener("endpointAdded", cb); + this.webrtc.removeListener("endpointRemoved", cb); + this.webrtc.removeListener("endpointUpdated", cb); }; } @@ -117,8 +114,8 @@ class RemoteStore { const newTracks = webrtc.getRemoteTracks(); const newEndpoints = webrtc.getRemoteEndpoints(); const ids = - Object.keys(newTracks).sort().join(':') + - Object.keys(newEndpoints).sort().join(':'); + Object.keys(newTracks).sort().join(":") + + Object.keys(newEndpoints).sort().join(":"); if (!(ids in this.cache) || this.invalidateCache) { this.cache[ids] = [newEndpoints, newTracks]; this.invalidateCache = false; @@ -138,26 +135,27 @@ const webrtc = new WebRTCEndpoint({ const remoteTracksStore = new RemoteStore(webrtc); function connect(token: string, metadata: EndpointMetadata) { - const websocketUrl = 'ws://localhost:5002/socket/peer/websocket'; + const websocketUrl = "ws://localhost:5002/socket/peer/websocket"; const websocket = new WebSocket(websocketUrl); - websocket.binaryType = 'arraybuffer'; + websocket.binaryType = "arraybuffer"; function socketOpenHandler(_event: Event) { const message = PeerMessage.encode({ authRequest: { token } }).finish(); websocket.send(message); } - websocket.addEventListener('open', socketOpenHandler); + websocket.addEventListener("open", socketOpenHandler); - webrtc.on('sendMediaEvent', (mediaEvent: SerializedMediaEvent) => { - console.log(`%c(${clientId}) - Send: ${mediaEvent}`, 'color:blue'); + webrtc.on("sendMediaEvent", (mediaEvent: SerializedMediaEvent) => { + console.log(`%c(${clientId}) - Send: ${mediaEvent}`, "color:blue"); const message = PeerMessage.encode({ mediaEvent: { data: mediaEvent }, }).finish(); websocket.send(message); }); - const messageHandler = (event: MessageEvent) => { /* eslint-disable-line @typescript-eslint/no-explicit-any */ + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + const messageHandler = (event: MessageEvent) => { const uint8Array = new Uint8Array(event.data); try { const data = PeerMessage.decode(uint8Array); @@ -166,19 +164,19 @@ function connect(token: string, metadata: EndpointMetadata) { const mediaEvent = JSON.parse(data?.mediaEvent?.data); console.log( `%c(${clientId}) - Received: ${JSON.stringify(mediaEvent)}`, - 'color:green', + "color:green", ); } else { console.log( `%c(${clientId}) - Received: ${JSON.stringify(data)}`, - 'color:green', + "color:green", ); } if (data.authenticated !== undefined) { webrtc.connect(metadata); } else if (data.authRequest !== undefined) { - console.warn('Received unexpected control message: authRequest'); + console.warn("Received unexpected control message: authRequest"); } else if (data.mediaEvent !== undefined) { webrtc.receiveMediaEvent(data.mediaEvent.data); } @@ -187,32 +185,32 @@ function connect(token: string, metadata: EndpointMetadata) { } }; - websocket.addEventListener('message', messageHandler); + websocket.addEventListener("message", messageHandler); const closeHandler = (event: unknown) => { - console.log({ name: 'Close handler!', event }); + console.log({ name: "Close handler!", event }); }; - websocket.addEventListener('close', closeHandler); + websocket.addEventListener("close", closeHandler); const errorHandler = (event: unknown) => { - console.log({ name: 'Error handler!', event }); + console.log({ name: "Error handler!", event }); }; - websocket.addEventListener('error', errorHandler); + websocket.addEventListener("error", errorHandler); const trackReady = (event: unknown) => { - console.log({ name: 'trackReady', event }); + console.log({ name: "trackReady", event }); }; - websocket.addEventListener('trackReady', trackReady); + websocket.addEventListener("trackReady", trackReady); } async function addScreenshareTrack(): Promise { const stream = await window.navigator.mediaDevices.getDisplayMedia(); const track = stream.getVideoTracks()[0]; - const trackMetadata: TrackMetadata = { goodTrack: 'screenshare' }; + const trackMetadata: TrackMetadata = { goodTrack: "screenshare" }; const simulcastConfig: SimulcastConfig = { enabled: false, activeEncodings: [], @@ -225,21 +223,21 @@ async function addScreenshareTrack(): Promise { export function App() { const [tokenInput, setTokenInput] = useState( - localStorage.getItem('token') ?? '', + localStorage.getItem("token") ?? "", ); const [endpointMetadataInput, setEndpointMetadataInput] = useState( - JSON.stringify({ goodStuff: 'ye' }), + JSON.stringify({ goodStuff: "ye" }), ); const [connected, setConnected] = useState(false); useEffect(() => { - localStorage.setItem('token', tokenInput); + localStorage.setItem("token", tokenInput); }, [tokenInput]); const handleConnect = () => connect( tokenInput, - endpointMetadataInput !== '' + endpointMetadataInput !== "" ? JSON.parse(endpointMetadataInput) : undefined, ); @@ -259,15 +257,15 @@ export function App() { useEffect(() => { const callback = () => setConnected(true); - webrtc.on('connected', callback); + webrtc.on("connected", callback); return () => { - webrtc.removeListener('connected', callback); + webrtc.removeListener("connected", callback); }; }, []); return ( -
+
-
{connected ? 'true' : 'false'}
+
{connected ? "true" : "false"}

-
+
{Object.values(remoteTracks).map( ({ - stream, - trackId, - endpoint, - metadata, - rawMetadata, - metadataParsingError, - }) => ( + stream, + trackId, + endpoint, + metadata, + rawMetadata, + metadataParsingError, + }) => (
+ data-stream-id={stream?.id} + >
Endpoint id: {endpoint.id}
- Metadata:{' '} + Metadata:{" "} {JSON.stringify(metadata)}
- Raw:{' '} + Raw:{" "} {JSON.stringify(rawMetadata)}
- Error:{' '} + Error:{" "} {metadataParsingError} -
+
{stream?.id}
- - - + + +
), )}
-
+
Our metadata: setEndpointMetadataInput(e.target.value)}> + onChange={(e) => setEndpointMetadataInput(e.target.value)} + >
Endpoints: @@ -346,15 +346,15 @@ export function App() { ({ id, metadata, rawMetadata, metadataParsingError }) => (
{id} - metadata:{' '} + metadata:{" "} {JSON.stringify(metadata)}
- raw metadata:{' '} + raw metadata:{" "} {JSON.stringify(rawMetadata)}
- metadata parsing error:{' '} + metadata parsing error:{" "} {metadataParsingError?.toString?.() ?? metadataParsingError} diff --git a/e2e-tests/ts-client/app/src/MockComponent.tsx b/e2e-tests/ts-client/app/src/MockComponent.tsx index 2e973faf..045913c5 100644 --- a/e2e-tests/ts-client/app/src/MockComponent.tsx +++ b/e2e-tests/ts-client/app/src/MockComponent.tsx @@ -1,25 +1,25 @@ -import { createStream } from './mocks'; -import { VideoPlayer } from './VideoPlayer'; -import { useRef, useState } from 'react'; -import type { EndpointMetadata, TrackMetadata } from './App'; +import { createStream } from "./mocks"; +import { VideoPlayer } from "./VideoPlayer"; +import { useRef, useState } from "react"; +import type { EndpointMetadata, TrackMetadata } from "./App"; import type { BandwidthLimit, SimulcastConfig, WebRTCEndpoint, -} from '@fishjam-dev/ts-client'; -import { MuteTrackTest } from './MuteTrackTest'; +} from "@fishjam-dev/ts-client"; +import { MuteTrackTest } from "./MuteTrackTest"; // eslint-disable-next-line react-refresh/only-export-components -export const brainMock = createStream('๐Ÿง ', 'white', 'low', 24); +export const brainMock = createStream("๐Ÿง ", "white", "low", 24); // eslint-disable-next-line react-refresh/only-export-components -export const brain2Mock = createStream('๐Ÿคฏ', '#00ff00', 'low', 24); +export const brain2Mock = createStream("๐Ÿคฏ", "#00ff00", "low", 24); // eslint-disable-next-line react-refresh/only-export-components -export const heartMock = createStream('๐Ÿซ€', 'white', 'low', 24); +export const heartMock = createStream("๐Ÿซ€", "white", "low", 24); // eslint-disable-next-line react-refresh/only-export-components -export const heart2Mock = createStream('๐Ÿ’', '#FF0000', 'low', 24); +export const heart2Mock = createStream("๐Ÿ’", "#FF0000", "low", 24); type Props = { webrtc: WebRTCEndpoint; @@ -29,10 +29,10 @@ export const MockComponent = ({ webrtc }: Props) => { const heartId = useRef | null>(null); const brainId = useRef | null>(null); const [replaceStatus, setReplaceStatus] = useState< - 'unknown' | 'success' | 'failure' - >('unknown'); + "unknown" | "success" | "failure" + >("unknown"); const [trackMetadataInput, setTrackMetadataInput] = useState( - JSON.stringify({ goodTrack: 'ye' }), + JSON.stringify({ goodTrack: "ye" }), ); const addHeart = async () => { @@ -43,19 +43,19 @@ export const MockComponent = ({ webrtc }: Props) => { }; const removeHeart = async () => { - if (!heartId.current) throw Error('Heart id is undefined'); + if (!heartId.current) throw Error("Heart id is undefined"); webrtc.removeTrack(await heartId.current); }; const removeBrain = async () => { - if (!brainId.current) throw Error('Brain id is undefined'); + if (!brainId.current) throw Error("Brain id is undefined"); webrtc.removeTrack(await brainId.current); }; const replaceHeart = async () => { - if (!heartId.current) throw Error('Track Id is not set'); + if (!heartId.current) throw Error("Track Id is not set"); const stream = heart2Mock.stream; const track = stream.getVideoTracks()[0]; @@ -65,11 +65,11 @@ export const MockComponent = ({ webrtc }: Props) => { track, JSON.parse(trackMetadataInput), ); - setReplaceStatus('success'); + setReplaceStatus("success"); }; const replaceBrain = async () => { - if (!brainId.current) throw Error('Track Id is not set'); + if (!brainId.current) throw Error("Track Id is not set"); const stream = brain2Mock.stream; const track = stream.getVideoTracks()[0]; diff --git a/e2e-tests/ts-client/app/src/MuteTrackTest.tsx b/e2e-tests/ts-client/app/src/MuteTrackTest.tsx index d65c54ce..54f5c2d6 100644 --- a/e2e-tests/ts-client/app/src/MuteTrackTest.tsx +++ b/e2e-tests/ts-client/app/src/MuteTrackTest.tsx @@ -1,9 +1,9 @@ -import type { WebRTCEndpoint } from '@fishjam-dev/ts-client'; -import { brain2Mock, heart2Mock } from './MockComponent'; -import { useEffect, useState } from 'react'; -import { VideoPlayer } from './VideoPlayer'; -import type { WebRTCEndpointEvents } from '@fishjam-dev/ts-client/webrtc'; -import type { EndpointMetadata, TrackMetadata } from './App'; +import type { WebRTCEndpoint } from "@fishjam-dev/ts-client"; +import { brain2Mock, heart2Mock } from "./MockComponent"; +import { useEffect, useState } from "react"; +import { VideoPlayer } from "./VideoPlayer"; +import type { WebRTCEndpointEvents } from "@fishjam-dev/ts-client/webrtc"; +import type { EndpointMetadata, TrackMetadata } from "./App"; type Props = { webrtc: WebRTCEndpoint; @@ -18,7 +18,7 @@ export const MuteTrackTest = ({ webrtc }: Props) => { const localTrackAdded: WebRTCEndpointEvents< EndpointMetadata, TrackMetadata - >['localTrackAdded'] = (event) => { + >["localTrackAdded"] = (event) => { setCurrentStream(event.stream); setCurrentTrack(event.track); setTrackId(event.trackId); @@ -27,16 +27,16 @@ export const MuteTrackTest = ({ webrtc }: Props) => { const localTrackReplaced: WebRTCEndpointEvents< EndpointMetadata, TrackMetadata - >['localTrackReplaced'] = (event) => { + >["localTrackReplaced"] = (event) => { setCurrentTrack(event.track); }; - webrtc.on('localTrackAdded', localTrackAdded); - webrtc.on('localTrackReplaced', localTrackReplaced); + webrtc.on("localTrackAdded", localTrackAdded); + webrtc.on("localTrackReplaced", localTrackReplaced); return () => { - webrtc.removeListener('localTrackAdded', localTrackAdded); - webrtc.removeListener('localTrackReplaced', localTrackReplaced); + webrtc.removeListener("localTrackAdded", localTrackAdded); + webrtc.removeListener("localTrackReplaced", localTrackReplaced); }; }, [webrtc]); @@ -47,10 +47,10 @@ export const MuteTrackTest = ({ webrtc }: Props) => { await webrtc.addTrack( track, - { goodTrack: 'camera' }, + { goodTrack: "camera" }, { enabled: true, - activeEncodings: ['l', 'm', 'h'], + activeEncodings: ["l", "m", "h"], disabledEncodings: [], }, ); @@ -61,7 +61,7 @@ export const MuteTrackTest = ({ webrtc }: Props) => { stream: MediaStream | null, track: MediaStreamTrack | null, ) => { - if (!trackId) throw Error('Track id is null'); + if (!trackId) throw Error("Track id is null"); await webrtc.replaceTrack(trackId, track); }; @@ -69,25 +69,28 @@ export const MuteTrackTest = ({ webrtc }: Props) => { return (
+ display: "flex", + flexDirection: "column", + padding: "8px", + borderStyle: "dotted", + borderWidth: "1px", + borderColor: "black", + }} + >
- track: {currentTrack?.id ?? 'null'} + track: {currentTrack?.id ?? "null"}