diff --git a/package.json b/package.json
index 02f20fa3..c28d7884 100644
--- a/package.json
+++ b/package.json
@@ -32,8 +32,7 @@
"@types/ws": "^8",
"prettier": "^2.7.1",
"replayio": "workspace:^",
- "typescript": "^5.4.5",
- "ws": "^8.17.0"
+ "typescript": "^5.4.5"
},
"dependencies": {
"node-fetch": "^3.3.1"
diff --git a/packages/playwright/jest.config.js b/packages/playwright/jest.config.js
new file mode 100644
index 00000000..2abe8413
--- /dev/null
+++ b/packages/playwright/jest.config.js
@@ -0,0 +1,8 @@
+/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
+module.exports = {
+ testTimeout: 20000,
+ preset: "ts-jest",
+ testEnvironment: "node",
+ testMatch: ["**/(*.)+(spec|test).[jt]s?(x)", "!**/fixtures-app/**"],
+ // TODO: implement dependencyExtractor: the whole src directory and the whole fixture app should be added here
+};
diff --git a/packages/playwright/package.json b/packages/playwright/package.json
index fe0abcb1..261cebca 100644
--- a/packages/playwright/package.json
+++ b/packages/playwright/package.json
@@ -17,8 +17,9 @@
"scripts": {
"prepare": "yarn run build",
"build": "rm -rf dist/ tsconfig.tsbuildinfo && tsc",
- "test": "echo \"Error: no test specified\"",
- "typecheck": "tsc --noEmit"
+ "test": "jest",
+ "typecheck": "tsc --noEmit",
+ "fixtures-app": "next dev tests/fixtures-app"
},
"devDependencies": {
"@playwright/test": "^1.40.1",
@@ -28,6 +29,12 @@
"@types/stack-utils": "^2.0.3",
"@types/uuid": "^8.3.4",
"@types/ws": "^8.5.10",
+ "jest": "^28.1.3",
+ "msw": "2.3.0-ws.rc-6",
+ "next": "^14.2.4",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "ts-jest": "^28.0.6",
"typescript": "^5.4.5"
},
"repository": {
@@ -45,6 +52,7 @@
"@replayio/test-utils": "workspace:^",
"debug": "^4.3.4",
"stack-utils": "^2.0.6",
+ "undici": "^5.28.4",
"uuid": "^8.3.2",
"ws": "^8.13.0"
},
diff --git a/packages/playwright/tests/fixtures-app/.gitignore b/packages/playwright/tests/fixtures-app/.gitignore
new file mode 100644
index 00000000..fd3dbb57
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/packages/playwright/tests/fixtures-app/app/_pw-utils/network-mock-global-setup.ts b/packages/playwright/tests/fixtures-app/app/_pw-utils/network-mock-global-setup.ts
new file mode 100644
index 00000000..e21a277d
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/_pw-utils/network-mock-global-setup.ts
@@ -0,0 +1,121 @@
+import type { FullConfig } from "@playwright/test";
+import type {
+ addOriginalSourceResult,
+ addSourceMapResult,
+ beginRecordingUploadParameters,
+ beginRecordingUploadResult,
+ endRecordingUploadResult,
+ existsResult,
+ setAccessTokenResult,
+ setRecordingMetadataResult,
+} from "@replayio/protocol";
+import { WebSocket } from "undici";
+
+async function globalSetup(_config: FullConfig) {
+ (globalThis as any).WebSocket = WebSocket;
+
+ const { http, ws, HttpResponse } = await import("msw");
+ const { setupServer } = await import("msw/node");
+
+ const server = setupServer(
+ http.get("*", async ({ request }) => {
+ switch (request.url) {
+ case "https://dispatch.replay.io/": {
+ return new HttpResponse("", {
+ status: 200,
+ });
+ }
+ default:
+ throw new Error(`Unexpected GET to: ${request.url}`);
+ }
+ }),
+ http.post("*", async ({ request }) => {
+ switch (request.url) {
+ case "https://api.replay.io/v1/graphql": {
+ const body = JSON.parse(await request.text());
+
+ switch (body.name) {
+ case "AddTestsToShard":
+ // TODO: we are interested in the data that we sent out here
+ return new HttpResponse(JSON.stringify({}));
+ case "CompleteTestRunShard":
+ return new HttpResponse(JSON.stringify({}));
+ case "CreateTestRunShard":
+ return new HttpResponse(
+ JSON.stringify({
+ data: {
+ startTestRunShard: {
+ testRunShardId: "test-run-shard-id",
+ },
+ },
+ })
+ );
+ default:
+ throw new Error(`Unexpected graphql operation name: ${body.name}`);
+ }
+ }
+ case "https://webhooks.replay.io/api/metrics":
+ return new HttpResponse(JSON.stringify({}));
+ default:
+ throw new Error(`Unexpected POST to: ${request.url}`);
+ }
+ }),
+ http.put("*", async ({ request }) => {
+ if (request.url.startsWith("https://app.replay.io/recording/")) {
+ return new HttpResponse(JSON.stringify({}));
+ }
+ throw new Error(`Unexpected PUT to: ${request.url}`);
+ })
+ );
+
+ const wsHandler = ws.link("wss://dispatch.replay.io").on("connection", ({ client, server }) => {
+ server.connect();
+
+ client.addEventListener("message", event => {
+ event.preventDefault();
+ const data = JSON.parse(String(event.data));
+ switch (data.method) {
+ case "Authentication.setAccessToken":
+ case "Internal.endRecordingUpload":
+ case "Internal.setRecordingMetadata":
+ case "Recording.addOriginalSource":
+ case "Recording.addSourceMap":
+ case "Resource.exists":
+ client.send(
+ JSON.stringify({
+ id: data.id,
+ result: {} satisfies
+ | addOriginalSourceResult
+ | addSourceMapResult
+ | endRecordingUploadResult
+ | existsResult
+ | setAccessTokenResult
+ | setRecordingMetadataResult,
+ })
+ );
+ return;
+ case "Internal.beginRecordingUpload": {
+ const params: beginRecordingUploadParameters = data.params;
+ client.send(
+ JSON.stringify({
+ id: data.id,
+ result: {
+ recordingId: params.recordingId!,
+ uploadLink: `https://app.replay.io/recording/${params.recordingId}`,
+ } satisfies beginRecordingUploadResult,
+ })
+ );
+ return;
+ }
+ default:
+ throw new Error(`Unexpected protocol method: ${data.method}`);
+ }
+ });
+ });
+
+ server.use(wsHandler);
+
+ server.listen();
+}
+
+export default globalSetup;
diff --git a/packages/playwright/tests/fixtures-app/app/basic/page.module.css b/packages/playwright/tests/fixtures-app/app/basic/page.module.css
new file mode 100644
index 00000000..5c4b1e6a
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/basic/page.module.css
@@ -0,0 +1,230 @@
+.main {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6rem;
+ min-height: 100vh;
+}
+
+.description {
+ display: inherit;
+ justify-content: inherit;
+ align-items: inherit;
+ font-size: 0.85rem;
+ max-width: var(--max-width);
+ width: 100%;
+ z-index: 2;
+ font-family: var(--font-mono);
+}
+
+.description a {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.description p {
+ position: relative;
+ margin: 0;
+ padding: 1rem;
+ background-color: rgba(var(--callout-rgb), 0.5);
+ border: 1px solid rgba(var(--callout-border-rgb), 0.3);
+ border-radius: var(--border-radius);
+}
+
+.code {
+ font-weight: 700;
+ font-family: var(--font-mono);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(25%, auto));
+ max-width: 100%;
+ width: var(--max-width);
+}
+
+.card {
+ padding: 1rem 1.2rem;
+ border-radius: var(--border-radius);
+ background: rgba(var(--card-rgb), 0);
+ border: 1px solid rgba(var(--card-border-rgb), 0);
+ transition: background 200ms, border 200ms;
+}
+
+.card span {
+ display: inline-block;
+ transition: transform 200ms;
+}
+
+.card h2 {
+ font-weight: 600;
+ margin-bottom: 0.7rem;
+}
+
+.card p {
+ margin: 0;
+ opacity: 0.6;
+ font-size: 0.9rem;
+ line-height: 1.5;
+ max-width: 30ch;
+ text-wrap: balance;
+}
+
+.center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ padding: 4rem 0;
+}
+
+.center::before {
+ background: var(--secondary-glow);
+ border-radius: 50%;
+ width: 480px;
+ height: 360px;
+ margin-left: -400px;
+}
+
+.center::after {
+ background: var(--primary-glow);
+ width: 240px;
+ height: 180px;
+ z-index: -1;
+}
+
+.center::before,
+.center::after {
+ content: "";
+ left: 50%;
+ position: absolute;
+ filter: blur(45px);
+ transform: translateZ(0);
+}
+
+.logo {
+ position: relative;
+}
+/* Enable hover only on non-touch devices */
+@media (hover: hover) and (pointer: fine) {
+ .card:hover {
+ background: rgba(var(--card-rgb), 0.1);
+ border: 1px solid rgba(var(--card-border-rgb), 0.15);
+ }
+
+ .card:hover span {
+ transform: translateX(4px);
+ }
+}
+
+@media (prefers-reduced-motion) {
+ .card:hover span {
+ transform: none;
+ }
+}
+
+/* Mobile */
+@media (max-width: 700px) {
+ .content {
+ padding: 4rem;
+ }
+
+ .grid {
+ grid-template-columns: 1fr;
+ margin-bottom: 120px;
+ max-width: 320px;
+ text-align: center;
+ }
+
+ .card {
+ padding: 1rem 2.5rem;
+ }
+
+ .card h2 {
+ margin-bottom: 0.5rem;
+ }
+
+ .center {
+ padding: 8rem 0 6rem;
+ }
+
+ .center::before {
+ transform: none;
+ height: 300px;
+ }
+
+ .description {
+ font-size: 0.8rem;
+ }
+
+ .description a {
+ padding: 1rem;
+ }
+
+ .description p,
+ .description div {
+ display: flex;
+ justify-content: center;
+ position: fixed;
+ width: 100%;
+ }
+
+ .description p {
+ align-items: center;
+ inset: 0 0 auto;
+ padding: 2rem 1rem 1.4rem;
+ border-radius: 0;
+ border: none;
+ border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
+ background: linear-gradient(
+ to bottom,
+ rgba(var(--background-start-rgb), 1),
+ rgba(var(--callout-rgb), 0.5)
+ );
+ background-clip: padding-box;
+ backdrop-filter: blur(24px);
+ }
+
+ .description div {
+ align-items: flex-end;
+ pointer-events: none;
+ inset: auto 0 0;
+ padding: 2rem;
+ height: 200px;
+ background: linear-gradient(
+ to bottom,
+ transparent 0%,
+ rgb(var(--background-end-rgb)) 40%
+ );
+ z-index: 1;
+ }
+}
+
+/* Tablet and Smaller Desktop */
+@media (min-width: 701px) and (max-width: 1120px) {
+ .grid {
+ grid-template-columns: repeat(2, 50%);
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ .vercelLogo {
+ filter: invert(1);
+ }
+
+ .logo {
+ filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
+ }
+}
+
+@keyframes rotate {
+ from {
+ transform: rotate(360deg);
+ }
+ to {
+ transform: rotate(0deg);
+ }
+}
diff --git a/packages/playwright/tests/fixtures-app/app/basic/page.tsx b/packages/playwright/tests/fixtures-app/app/basic/page.tsx
new file mode 100644
index 00000000..0d945a2e
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/basic/page.tsx
@@ -0,0 +1,94 @@
+import Image from "next/image";
+import styles from "./page.module.css";
+
+export default function Home() {
+ return (
+
+
+
+ Get started by editing
+ app/page.tsx
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/playwright/tests/fixtures-app/app/basic/playwright.config.mts b/packages/playwright/tests/fixtures-app/app/basic/playwright.config.mts
new file mode 100644
index 00000000..147d61dc
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/basic/playwright.config.mts
@@ -0,0 +1,19 @@
+import { defineConfig } from "@playwright/test";
+import { devices as replayDevices, replayReporter } from "@replayio/playwright";
+
+export default defineConfig({
+ globalSetup: "../_pw-utils/network-mock-global-setup.ts",
+ reporter: [
+ ["line"],
+ replayReporter({
+ upload: true,
+ apiKey: "MOCKED_API_KEY",
+ }),
+ ],
+ projects: [
+ {
+ name: "replay-chromium",
+ use: { ...replayDevices["Replay Chromium"] },
+ },
+ ],
+});
diff --git a/packages/playwright/tests/fixtures-app/app/basic/tests/pw.spec.ts b/packages/playwright/tests/fixtures-app/app/basic/tests/pw.spec.ts
new file mode 100644
index 00000000..5fba6af7
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/basic/tests/pw.spec.ts
@@ -0,0 +1,9 @@
+import { test, expect } from "@playwright/test";
+
+const testName = __dirname.split("/").slice(-2)[0];
+
+test("smoke", async ({ page }) => {
+ await page.goto(`http://localhost:3000/${testName}`);
+ const title = page.locator("#docs-card p");
+ await expect(title).toHaveText("Find in-depth information about Next.js features and API.");
+});
diff --git a/packages/playwright/tests/fixtures-app/app/favicon.ico b/packages/playwright/tests/fixtures-app/app/favicon.ico
new file mode 100644
index 00000000..718d6fea
Binary files /dev/null and b/packages/playwright/tests/fixtures-app/app/favicon.ico differ
diff --git a/packages/playwright/tests/fixtures-app/app/globals.css b/packages/playwright/tests/fixtures-app/app/globals.css
new file mode 100644
index 00000000..f4bd77c0
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/globals.css
@@ -0,0 +1,107 @@
+:root {
+ --max-width: 1100px;
+ --border-radius: 12px;
+ --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
+ "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
+ "Fira Mono", "Droid Sans Mono", "Courier New", monospace;
+
+ --foreground-rgb: 0, 0, 0;
+ --background-start-rgb: 214, 219, 220;
+ --background-end-rgb: 255, 255, 255;
+
+ --primary-glow: conic-gradient(
+ from 180deg at 50% 50%,
+ #16abff33 0deg,
+ #0885ff33 55deg,
+ #54d6ff33 120deg,
+ #0071ff33 160deg,
+ transparent 360deg
+ );
+ --secondary-glow: radial-gradient(
+ rgba(255, 255, 255, 1),
+ rgba(255, 255, 255, 0)
+ );
+
+ --tile-start-rgb: 239, 245, 249;
+ --tile-end-rgb: 228, 232, 233;
+ --tile-border: conic-gradient(
+ #00000080,
+ #00000040,
+ #00000030,
+ #00000020,
+ #00000010,
+ #00000010,
+ #00000080
+ );
+
+ --callout-rgb: 238, 240, 241;
+ --callout-border-rgb: 172, 175, 176;
+ --card-rgb: 180, 185, 188;
+ --card-border-rgb: 131, 134, 135;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --foreground-rgb: 255, 255, 255;
+ --background-start-rgb: 0, 0, 0;
+ --background-end-rgb: 0, 0, 0;
+
+ --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
+ --secondary-glow: linear-gradient(
+ to bottom right,
+ rgba(1, 65, 255, 0),
+ rgba(1, 65, 255, 0),
+ rgba(1, 65, 255, 0.3)
+ );
+
+ --tile-start-rgb: 2, 13, 46;
+ --tile-end-rgb: 2, 5, 19;
+ --tile-border: conic-gradient(
+ #ffffff80,
+ #ffffff40,
+ #ffffff30,
+ #ffffff20,
+ #ffffff10,
+ #ffffff10,
+ #ffffff80
+ );
+
+ --callout-rgb: 20, 20, 20;
+ --callout-border-rgb: 108, 108, 108;
+ --card-rgb: 100, 100, 100;
+ --card-border-rgb: 200, 200, 200;
+ }
+}
+
+* {
+ box-sizing: border-box;
+ padding: 0;
+ margin: 0;
+}
+
+html,
+body {
+ max-width: 100vw;
+ overflow-x: hidden;
+}
+
+body {
+ color: rgb(var(--foreground-rgb));
+ background: linear-gradient(
+ to bottom,
+ transparent,
+ rgb(var(--background-end-rgb))
+ )
+ rgb(var(--background-start-rgb));
+}
+
+a {
+ color: inherit;
+ text-decoration: none;
+}
+
+@media (prefers-color-scheme: dark) {
+ html {
+ color-scheme: dark;
+ }
+}
diff --git a/packages/playwright/tests/fixtures-app/app/layout.tsx b/packages/playwright/tests/fixtures-app/app/layout.tsx
new file mode 100644
index 00000000..3314e478
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/layout.tsx
@@ -0,0 +1,22 @@
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import "./globals.css";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "Create Next App",
+ description: "Generated by create next app",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) {
+ return (
+
+
{children}
+
+ );
+}
diff --git a/packages/playwright/tests/fixtures-app/app/page.module.css b/packages/playwright/tests/fixtures-app/app/page.module.css
new file mode 100644
index 00000000..5c4b1e6a
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/page.module.css
@@ -0,0 +1,230 @@
+.main {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6rem;
+ min-height: 100vh;
+}
+
+.description {
+ display: inherit;
+ justify-content: inherit;
+ align-items: inherit;
+ font-size: 0.85rem;
+ max-width: var(--max-width);
+ width: 100%;
+ z-index: 2;
+ font-family: var(--font-mono);
+}
+
+.description a {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.description p {
+ position: relative;
+ margin: 0;
+ padding: 1rem;
+ background-color: rgba(var(--callout-rgb), 0.5);
+ border: 1px solid rgba(var(--callout-border-rgb), 0.3);
+ border-radius: var(--border-radius);
+}
+
+.code {
+ font-weight: 700;
+ font-family: var(--font-mono);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(25%, auto));
+ max-width: 100%;
+ width: var(--max-width);
+}
+
+.card {
+ padding: 1rem 1.2rem;
+ border-radius: var(--border-radius);
+ background: rgba(var(--card-rgb), 0);
+ border: 1px solid rgba(var(--card-border-rgb), 0);
+ transition: background 200ms, border 200ms;
+}
+
+.card span {
+ display: inline-block;
+ transition: transform 200ms;
+}
+
+.card h2 {
+ font-weight: 600;
+ margin-bottom: 0.7rem;
+}
+
+.card p {
+ margin: 0;
+ opacity: 0.6;
+ font-size: 0.9rem;
+ line-height: 1.5;
+ max-width: 30ch;
+ text-wrap: balance;
+}
+
+.center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ padding: 4rem 0;
+}
+
+.center::before {
+ background: var(--secondary-glow);
+ border-radius: 50%;
+ width: 480px;
+ height: 360px;
+ margin-left: -400px;
+}
+
+.center::after {
+ background: var(--primary-glow);
+ width: 240px;
+ height: 180px;
+ z-index: -1;
+}
+
+.center::before,
+.center::after {
+ content: "";
+ left: 50%;
+ position: absolute;
+ filter: blur(45px);
+ transform: translateZ(0);
+}
+
+.logo {
+ position: relative;
+}
+/* Enable hover only on non-touch devices */
+@media (hover: hover) and (pointer: fine) {
+ .card:hover {
+ background: rgba(var(--card-rgb), 0.1);
+ border: 1px solid rgba(var(--card-border-rgb), 0.15);
+ }
+
+ .card:hover span {
+ transform: translateX(4px);
+ }
+}
+
+@media (prefers-reduced-motion) {
+ .card:hover span {
+ transform: none;
+ }
+}
+
+/* Mobile */
+@media (max-width: 700px) {
+ .content {
+ padding: 4rem;
+ }
+
+ .grid {
+ grid-template-columns: 1fr;
+ margin-bottom: 120px;
+ max-width: 320px;
+ text-align: center;
+ }
+
+ .card {
+ padding: 1rem 2.5rem;
+ }
+
+ .card h2 {
+ margin-bottom: 0.5rem;
+ }
+
+ .center {
+ padding: 8rem 0 6rem;
+ }
+
+ .center::before {
+ transform: none;
+ height: 300px;
+ }
+
+ .description {
+ font-size: 0.8rem;
+ }
+
+ .description a {
+ padding: 1rem;
+ }
+
+ .description p,
+ .description div {
+ display: flex;
+ justify-content: center;
+ position: fixed;
+ width: 100%;
+ }
+
+ .description p {
+ align-items: center;
+ inset: 0 0 auto;
+ padding: 2rem 1rem 1.4rem;
+ border-radius: 0;
+ border: none;
+ border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
+ background: linear-gradient(
+ to bottom,
+ rgba(var(--background-start-rgb), 1),
+ rgba(var(--callout-rgb), 0.5)
+ );
+ background-clip: padding-box;
+ backdrop-filter: blur(24px);
+ }
+
+ .description div {
+ align-items: flex-end;
+ pointer-events: none;
+ inset: auto 0 0;
+ padding: 2rem;
+ height: 200px;
+ background: linear-gradient(
+ to bottom,
+ transparent 0%,
+ rgb(var(--background-end-rgb)) 40%
+ );
+ z-index: 1;
+ }
+}
+
+/* Tablet and Smaller Desktop */
+@media (min-width: 701px) and (max-width: 1120px) {
+ .grid {
+ grid-template-columns: repeat(2, 50%);
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ .vercelLogo {
+ filter: invert(1);
+ }
+
+ .logo {
+ filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
+ }
+}
+
+@keyframes rotate {
+ from {
+ transform: rotate(360deg);
+ }
+ to {
+ transform: rotate(0deg);
+ }
+}
diff --git a/packages/playwright/tests/fixtures-app/app/page.tsx b/packages/playwright/tests/fixtures-app/app/page.tsx
new file mode 100644
index 00000000..81070906
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/app/page.tsx
@@ -0,0 +1,95 @@
+import Image from "next/image";
+import styles from "./page.module.css";
+
+export default function Home() {
+ return (
+
+
+
+ Get started by editing
+ app/page.tsx
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/playwright/tests/fixtures-app/next.config.mjs b/packages/playwright/tests/fixtures-app/next.config.mjs
new file mode 100644
index 00000000..4678774e
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/packages/playwright/tests/fixtures-app/public/next.svg b/packages/playwright/tests/fixtures-app/public/next.svg
new file mode 100644
index 00000000..5174b28c
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/playwright/tests/fixtures-app/public/vercel.svg b/packages/playwright/tests/fixtures-app/public/vercel.svg
new file mode 100644
index 00000000..d2f84222
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/playwright/tests/fixtures-app/tsconfig.json b/packages/playwright/tests/fixtures-app/tsconfig.json
new file mode 100644
index 00000000..bb5584ed
--- /dev/null
+++ b/packages/playwright/tests/fixtures-app/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/packages/playwright/tests/index.test.ts b/packages/playwright/tests/index.test.ts
new file mode 100644
index 00000000..71ddcfb4
--- /dev/null
+++ b/packages/playwright/tests/index.test.ts
@@ -0,0 +1,38 @@
+import cp from "child_process";
+import path from "path";
+import fs from "fs";
+
+const fixturesPages = path.join(__dirname, "fixtures-app", "app");
+const playwrightPath = cp.spawnSync("yarn", ["bin", "playwright"]).stdout.toString().trim();
+
+fs.readdirSync(fixturesPages).forEach(name => {
+ if (name.startsWith("_") || !fs.statSync(path.join(fixturesPages, name)).isDirectory()) {
+ return;
+ }
+ it(name, async () => {
+ await new Promise((resolve, reject) => {
+ const child = cp.spawn("node", [playwrightPath, "test", "--project", "replay-chromium"], {
+ cwd: path.join(fixturesPages, name),
+ stdio: "inherit",
+ env: {
+ ...process.env,
+ // so Playwirhgt doesn't think the test was run by Jest. If it sees this env variable it throws an error
+ JEST_WORKER_ID: undefined,
+ },
+ });
+
+ child.on("error", reject);
+
+ child.on("exit", (code, signal) => {
+ if (code || signal) {
+ if (signal === "SIGTERM") {
+ return;
+ }
+ reject(new Error(`Process failed (${code ? `code: ${code}` : `signal: ${signal}`})`));
+ } else {
+ resolve();
+ }
+ });
+ });
+ });
+});
diff --git a/packages/replay/package.json b/packages/replay/package.json
index e13ac1a3..ba8a7dbf 100644
--- a/packages/replay/package.json
+++ b/packages/replay/package.json
@@ -48,7 +48,7 @@
"semver": "^7.5.4",
"superstruct": "^0.15.4",
"text-table": "^0.2.0",
- "ws": "^7.5.0"
+ "undici": "^5.28.4"
},
"devDependencies": {
"@replay-cli/tsconfig": "workspace:^",
diff --git a/packages/replay/src/client.ts b/packages/replay/src/client.ts
index 337107d3..b80f2510 100644
--- a/packages/replay/src/client.ts
+++ b/packages/replay/src/client.ts
@@ -1,7 +1,6 @@
import dbg from "./debug";
-import WebSocket from "ws";
+import { WebSocket } from "undici";
import { defer } from "./utils";
-import { Agent } from "http";
const debug = dbg("replay:protocol");
@@ -45,17 +44,15 @@ class ProtocolClient {
eventListeners = new Map();
nextMessageId = 1;
- constructor(address: string, callbacks: Callbacks, agent?: Agent) {
- debug("Creating WebSocket for %s with %o", address, { agent });
- this.socket = new WebSocket(address, {
- agent: agent,
- });
+ constructor(address: string, callbacks: Callbacks) {
+ debug("Creating WebSocket for %s", address);
+ this.socket = new ((globalThis as any).WebSocket || WebSocket)(address);
this.callbacks = callbacks;
- this.socket.on("open", callbacks.onOpen);
- this.socket.on("close", callbacks.onClose);
- this.socket.on("error", callbacks.onError);
- this.socket.on("message", message => this.onMessage(message));
+ this.socket.addEventListener("open", () => callbacks.onOpen(this.socket));
+ this.socket.addEventListener("close", () => callbacks.onClose(this.socket));
+ this.socket.addEventListener("error", () => callbacks.onError(this.socket));
+ this.socket.addEventListener("message", message => this.onMessage(message.data));
}
close() {
@@ -79,31 +76,24 @@ class ProtocolClient {
async sendCommand>(
method: string,
params: P,
- data?: any,
- sessionId?: string,
- callback?: (err?: Error) => void
+ sessionId?: string
) {
const id = this.nextMessageId++;
debug("Sending command %s: %o", method, { id, params, sessionId });
- this.socket.send(
- JSON.stringify({
- id,
- method,
- params,
- binary: data ? true : undefined,
- sessionId,
- }),
- err => {
- if (!err && data) {
- this.socket.send(data, callback);
- } else {
- if (err) {
- debug("Received socket error: %s", err);
- }
- callback?.(err);
- }
- }
- );
+ try {
+ this.socket.send(
+ JSON.stringify({
+ id,
+ method,
+ params,
+ sessionId,
+ })
+ );
+ } catch (err) {
+ debug("Received socket error: %s", err);
+ throw err;
+ }
+
const waiter = defer();
this.pendingMessages.set(id, waiter);
return waiter.promise;
@@ -113,7 +103,7 @@ class ProtocolClient {
this.eventListeners.set(method, callback);
}
- onMessage(contents: WebSocket.RawData) {
+ onMessage(contents: any) {
const msg = JSON.parse(String(contents));
debug("Received message %o", msg);
if (msg.id) {
diff --git a/packages/replay/src/main.ts b/packages/replay/src/main.ts
index aea1a9ba..0540034f 100644
--- a/packages/replay/src/main.ts
+++ b/packages/replay/src/main.ts
@@ -4,7 +4,7 @@ import { getPackument } from "query-registry";
import { compare } from "semver";
import dbg from "./debug";
import { query } from "./graphql";
-import { getCurrentVersion, getHttpAgent } from "./utils";
+import { getCurrentVersion } from "./utils";
// requiring v4 explicitly because it's the last version with commonjs support.
// Should be upgraded to the latest when converting this code to es modules.
@@ -145,12 +145,11 @@ async function doUploadCrash(
server: string,
recording: RecordingEntry,
verbose?: boolean,
- apiKey?: string,
- agent?: Agent
+ apiKey?: string
) {
const client = new ReplayClient();
maybeLog(verbose, `Starting crash data upload for ${recording.id}...`);
- if (!(await client.initConnection(server, apiKey, verbose, agent))) {
+ if (!(await client.initConnection(server, apiKey, verbose))) {
maybeLog(verbose, `Crash data upload failed: can't connect to server ${server}`);
return null;
}
@@ -327,11 +326,9 @@ async function doUploadRecording(
apiKey = await readToken({ directory: dir });
}
- const agent = getHttpAgent(server, agentOptions);
-
if (recording.status == "crashed") {
debug("Uploading crash %o", recording);
- await doUploadCrash(dir, server, recording, verbose, apiKey, agent);
+ await doUploadCrash(dir, server, recording, verbose, apiKey);
maybeLog(verbose, `Crash report uploaded for ${recording.id}`);
if (removeAssets) {
removeRecordingAssets(recording, { directory: dir });
@@ -343,7 +340,7 @@ async function doUploadRecording(
debug("Uploading recording %o", recording);
const client = new ReplayClient();
- if (!(await client.initConnection(server, apiKey, verbose, agent))) {
+ if (!(await client.initConnection(server, apiKey, verbose))) {
handleUploadingError(`Cannot connect to server ${server}`, strict, verbose);
return null;
}
@@ -468,7 +465,6 @@ async function uploadRecording(id: string, opts: UploadOptions = {}) {
async function processUploadedRecording(recordingId: string, opts: Options) {
const server = getServer(opts);
- const agent = getHttpAgent(server, opts.agentOptions);
const { verbose } = opts;
let apiKey = opts.apiKey;
@@ -479,7 +475,7 @@ async function processUploadedRecording(recordingId: string, opts: Options) {
}
const client = new ReplayClient();
- if (!(await client.initConnection(server, apiKey, verbose, agent))) {
+ if (!(await client.initConnection(server, apiKey, verbose))) {
maybeLog(verbose, `Processing failed: can't connect to server ${server}`);
return false;
}
diff --git a/packages/replay/src/upload.ts b/packages/replay/src/upload.ts
index 5b02f59f..bf4ce35c 100644
--- a/packages/replay/src/upload.ts
+++ b/packages/replay/src/upload.ts
@@ -21,31 +21,27 @@ class ReplayClient {
client: ProtocolClient | undefined;
clientReady = defer();
- async initConnection(server: string, accessToken?: string, verbose?: boolean, agent?: Agent) {
+ async initConnection(server: string, accessToken?: string, verbose?: boolean) {
if (!this.client) {
let { resolve } = this.clientReady;
- this.client = new ProtocolClient(
- server,
- {
- onOpen: async () => {
- try {
- await this.client!.setAccessToken(accessToken);
- resolve(true);
- } catch (err) {
- maybeLog(verbose, `Error authenticating with server: ${err}`);
- resolve(false);
- }
- },
- onClose() {
- resolve(false);
- },
- onError(e) {
- maybeLog(verbose, `Error connecting to server: ${e}`);
+ this.client = new ProtocolClient(server, {
+ onOpen: async () => {
+ try {
+ await this.client!.setAccessToken(accessToken);
+ resolve(true);
+ } catch (err) {
+ maybeLog(verbose, `Error authenticating with server: ${err}`);
resolve(false);
- },
+ }
},
- agent
- );
+ onClose() {
+ resolve(false);
+ },
+ onError(e) {
+ maybeLog(verbose, `Error connecting to server: ${e}`);
+ resolve(false);
+ },
+ });
}
return this.clientReady.promise;
@@ -151,7 +147,7 @@ class ReplayClient {
this.client.setEventListener("Session.unprocessedRegions", () => {});
this.client
- .sendCommand("Session.ensureProcessed", { level: "basic" }, null, sessionId)
+ .sendCommand("Session.ensureProcessed", { level: "basic" }, sessionId)
.then(() => waiter.resolve(null));
const error = await waiter.promise;
diff --git a/packages/replayio/package.json b/packages/replayio/package.json
index b55e21d6..88b2784a 100644
--- a/packages/replayio/package.json
+++ b/packages/replayio/package.json
@@ -55,8 +55,7 @@
"strip-ansi": "^6.0.1",
"superstruct": "^0.15.4",
"table": "^6.8.2",
- "undici": "^5.28.4",
- "ws": "^7.5.0"
+ "undici": "^5.28.4"
},
"devDependencies": {
"@replay-cli/tsconfig": "workspace:^",
diff --git a/packages/replayio/src/utils/protocol/ProtocolClient.ts b/packages/replayio/src/utils/protocol/ProtocolClient.ts
index 64f00053..aea2c7fc 100644
--- a/packages/replayio/src/utils/protocol/ProtocolClient.ts
+++ b/packages/replayio/src/utils/protocol/ProtocolClient.ts
@@ -1,6 +1,6 @@
import { SessionId, sessionError } from "@replayio/protocol";
import assert from "assert";
-import WebSocket from "ws";
+import { WebSocket } from "undici";
import { replayWsServer } from "../../config";
import { getAccessToken } from "../authentication/getAccessToken";
import { Deferred, STATUS_PENDING, createDeferred } from "../async/createDeferred";
@@ -28,10 +28,10 @@ export default class ProtocolClient {
this.socket = new WebSocket(replayWsServer);
- this.socket.on("close", this.onSocketClose);
- this.socket.on("error", this.onSocketError);
- this.socket.on("open", this.onSocketOpen);
- this.socket.on("message", this.onSocketMessage);
+ this.socket.addEventListener("close", this.onSocketClose);
+ this.socket.addEventListener("error", this.onSocketError);
+ this.socket.addEventListener("open", this.onSocketOpen);
+ this.socket.addEventListener("message", event => this.onSocketMessage(event.data));
this.listenForMessage("Recording.sessionError", (error: sessionError) => {
if (error.sessionId) {
@@ -91,11 +91,12 @@ export default class ProtocolClient {
sessionId,
};
- this.socket.send(JSON.stringify(command), error => {
- if (error) {
- debug("Received socket error: %s", error);
- }
- });
+ try {
+ this.socket.send(JSON.stringify(command));
+ } catch (error) {
+ debug("Socket error when sending: %s", error);
+ throw error;
+ }
const deferred = createDeferred({ sessionId, command });
@@ -122,7 +123,7 @@ export default class ProtocolClient {
}
};
- private onSocketMessage = (contents: WebSocket.RawData) => {
+ private onSocketMessage = (contents: any) => {
const { error, id, method, params, result } = JSON.parse(String(contents));
if (id) {
diff --git a/packages/replayio/src/utils/protocol/types.ts b/packages/replayio/src/utils/protocol/types.ts
deleted file mode 100644
index 173f8f15..00000000
--- a/packages/replayio/src/utils/protocol/types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { WebSocket } from "ws";
-
-export type Callbacks = {
- onOpen: (socket: WebSocket) => void;
- onClose: (socket: WebSocket) => void;
- onError: (socket: WebSocket) => void;
-};
diff --git a/yarn.lock b/yarn.lock
index a3e635ea..ff8fe5c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1789,6 +1789,24 @@ __metadata:
languageName: node
linkType: hard
+"@bundled-es-modules/cookie@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "@bundled-es-modules/cookie@npm:2.0.0"
+ dependencies:
+ cookie: "npm:^0.5.0"
+ checksum: 10c0/0655dd331b35d7b5b6dd2301c3bcfb7233018c0e3235a40ced1d53f00463ab92dc01f0091f153812867bc0ef0f8e0a157a30acb16e8d7ef149702bf8db9fe7a6
+ languageName: node
+ linkType: hard
+
+"@bundled-es-modules/statuses@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "@bundled-es-modules/statuses@npm:1.0.1"
+ dependencies:
+ statuses: "npm:^2.0.1"
+ checksum: 10c0/c1a8ede3efa8da61ccda4b98e773582a9733edfbeeee569d4630785f8e018766202edb190a754a3ec7a7f6bd738e857829affc2fdb676b6dab4db1bb44e62785
+ languageName: node
+ linkType: hard
+
"@changesets/apply-release-plan@npm:^7.0.3":
version: 7.0.3
resolution: "@changesets/apply-release-plan@npm:7.0.3"
@@ -2402,6 +2420,51 @@ __metadata:
languageName: node
linkType: hard
+"@inquirer/confirm@npm:^3.0.0":
+ version: 3.1.10
+ resolution: "@inquirer/confirm@npm:3.1.10"
+ dependencies:
+ "@inquirer/core": "npm:^8.2.3"
+ "@inquirer/type": "npm:^1.3.3"
+ checksum: 10c0/a69bc0d21807b8cecb6ab1a9e0653abd255d1dde34083f536ee59df1bf01b1614fd6824b25735d2ddd8e5d81192a67e1da8944dc1713dbaeb75c7c182a4d6b88
+ languageName: node
+ linkType: hard
+
+"@inquirer/core@npm:^8.2.3":
+ version: 8.2.3
+ resolution: "@inquirer/core@npm:8.2.3"
+ dependencies:
+ "@inquirer/figures": "npm:^1.0.3"
+ "@inquirer/type": "npm:^1.3.3"
+ "@types/mute-stream": "npm:^0.0.4"
+ "@types/node": "npm:^20.14.6"
+ "@types/wrap-ansi": "npm:^3.0.0"
+ ansi-escapes: "npm:^4.3.2"
+ chalk: "npm:^4.1.2"
+ cli-spinners: "npm:^2.9.2"
+ cli-width: "npm:^4.1.0"
+ mute-stream: "npm:^1.0.0"
+ signal-exit: "npm:^4.1.0"
+ strip-ansi: "npm:^6.0.1"
+ wrap-ansi: "npm:^6.2.0"
+ checksum: 10c0/5e618df6bac115e29ba2da01f5b142da53f2502679ebebccc9aa185e04261cae279c856e07bdecd69d3ad9eeec87729b7c212c59242374b982bdaa45ceb69ae4
+ languageName: node
+ linkType: hard
+
+"@inquirer/figures@npm:^1.0.3":
+ version: 1.0.3
+ resolution: "@inquirer/figures@npm:1.0.3"
+ checksum: 10c0/099e062f000baafb4010014ece443d0cd211f562194854dc52a128bfe514611f8cc3da4cdb5092d75440956aff201dcd8e893b8a71feb104f97b0b00c6a696cf
+ languageName: node
+ linkType: hard
+
+"@inquirer/type@npm:^1.3.3":
+ version: 1.3.3
+ resolution: "@inquirer/type@npm:1.3.3"
+ checksum: 10c0/84048694410bb5b2c55dc4e48da6369ce942b9e8f8016d15ef63ab3f9873832a56cc12a50582b5b2b626821bfe29973dfcc19edc90f58490b51df1f4d9d0a074
+ languageName: node
+ linkType: hard
+
"@isaacs/cliui@npm:^8.0.2":
version: 8.0.2
resolution: "@isaacs/cliui@npm:8.0.2"
@@ -2939,6 +3002,27 @@ __metadata:
languageName: node
linkType: hard
+"@mswjs/cookies@npm:^1.1.0":
+ version: 1.1.1
+ resolution: "@mswjs/cookies@npm:1.1.1"
+ checksum: 10c0/75d3fdb0b5941ff473776b25869e4e7d1aeae872107c8cd12f1ebd89e1a9fb39473c9fbd1278aec91f40c991cd9fe98533863ef3a3906ca060532ce49acf86a5
+ languageName: node
+ linkType: hard
+
+"@mswjs/interceptors@npm:^0.27.1":
+ version: 0.27.2
+ resolution: "@mswjs/interceptors@npm:0.27.2"
+ dependencies:
+ "@open-draft/deferred-promise": "npm:^2.2.0"
+ "@open-draft/logger": "npm:^0.3.0"
+ "@open-draft/until": "npm:^2.0.0"
+ is-node-process: "npm:^1.2.0"
+ outvariant: "npm:^1.2.1"
+ strict-event-emitter: "npm:^0.5.1"
+ checksum: 10c0/7498cf89059eed1f42433bbee31ab6a88955bd377379f2f9cb34623eb00c48002975abff9bdf90489ce5832684f09b3b61a8801b161ec3f86c8015ee4e5b18f5
+ languageName: node
+ linkType: hard
+
"@napi-rs/snappy-android-arm-eabi@npm:7.2.2":
version: 7.2.2
resolution: "@napi-rs/snappy-android-arm-eabi@npm:7.2.2"
@@ -3030,6 +3114,76 @@ __metadata:
languageName: node
linkType: hard
+"@next/env@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/env@npm:14.2.4"
+ checksum: 10c0/cc284e3dd0666df04d8321645d8409c10cb8e325884c226abbb2e7bea20f0a4232f988216aa506a9d0457b46f28b594a61179d1e978c0ca22497cd8cab8196c7
+ languageName: node
+ linkType: hard
+
+"@next/swc-darwin-arm64@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-darwin-arm64@npm:14.2.4"
+ conditions: os=darwin & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@next/swc-darwin-x64@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-darwin-x64@npm:14.2.4"
+ conditions: os=darwin & cpu=x64
+ languageName: node
+ linkType: hard
+
+"@next/swc-linux-arm64-gnu@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-linux-arm64-gnu@npm:14.2.4"
+ conditions: os=linux & cpu=arm64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@next/swc-linux-arm64-musl@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-linux-arm64-musl@npm:14.2.4"
+ conditions: os=linux & cpu=arm64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@next/swc-linux-x64-gnu@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-linux-x64-gnu@npm:14.2.4"
+ conditions: os=linux & cpu=x64 & libc=glibc
+ languageName: node
+ linkType: hard
+
+"@next/swc-linux-x64-musl@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-linux-x64-musl@npm:14.2.4"
+ conditions: os=linux & cpu=x64 & libc=musl
+ languageName: node
+ linkType: hard
+
+"@next/swc-win32-arm64-msvc@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-win32-arm64-msvc@npm:14.2.4"
+ conditions: os=win32 & cpu=arm64
+ languageName: node
+ linkType: hard
+
+"@next/swc-win32-ia32-msvc@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-win32-ia32-msvc@npm:14.2.4"
+ conditions: os=win32 & cpu=ia32
+ languageName: node
+ linkType: hard
+
+"@next/swc-win32-x64-msvc@npm:14.2.4":
+ version: 14.2.4
+ resolution: "@next/swc-win32-x64-msvc@npm:14.2.4"
+ conditions: os=win32 & cpu=x64
+ languageName: node
+ linkType: hard
+
"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1":
version: 5.1.1-v1
resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1"
@@ -3088,6 +3242,30 @@ __metadata:
languageName: node
linkType: hard
+"@open-draft/deferred-promise@npm:^2.2.0":
+ version: 2.2.0
+ resolution: "@open-draft/deferred-promise@npm:2.2.0"
+ checksum: 10c0/eafc1b1d0fc8edb5e1c753c5e0f3293410b40dde2f92688211a54806d4136887051f39b98c1950370be258483deac9dfd17cf8b96557553765198ef2547e4549
+ languageName: node
+ linkType: hard
+
+"@open-draft/logger@npm:^0.3.0":
+ version: 0.3.0
+ resolution: "@open-draft/logger@npm:0.3.0"
+ dependencies:
+ is-node-process: "npm:^1.2.0"
+ outvariant: "npm:^1.4.0"
+ checksum: 10c0/90010647b22e9693c16258f4f9adb034824d1771d3baa313057b9a37797f571181005bc50415a934eaf7c891d90ff71dcd7a9d5048b0b6bb438f31bef2c7c5c1
+ languageName: node
+ linkType: hard
+
+"@open-draft/until@npm:^2.0.0, @open-draft/until@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "@open-draft/until@npm:2.1.0"
+ checksum: 10c0/61d3f99718dd86bb393fee2d7a785f961dcaf12f2055f0c693b27f4d0cd5f7a03d498a6d9289773b117590d794a43cd129366fd8e99222e4832f67b1653d54cf
+ languageName: node
+ linkType: hard
+
"@pkgjs/parseargs@npm:^0.11.0":
version: 0.11.0
resolution: "@pkgjs/parseargs@npm:0.11.0"
@@ -3319,8 +3497,15 @@ __metadata:
"@types/uuid": "npm:^8.3.4"
"@types/ws": "npm:^8.5.10"
debug: "npm:^4.3.4"
+ jest: "npm:^28.1.3"
+ msw: "npm:2.3.0-ws.rc-6"
+ next: "npm:^14.2.4"
+ react: "npm:^18.3.1"
+ react-dom: "npm:^18.3.1"
stack-utils: "npm:^2.0.6"
+ ts-jest: "npm:^28.0.6"
typescript: "npm:^5.4.5"
+ undici: "npm:^5.28.4"
uuid: "npm:^8.3.2"
ws: "npm:^8.13.0"
peerDependencies:
@@ -3382,7 +3567,7 @@ __metadata:
text-table: "npm:^0.2.0"
ts-jest: "npm:^28.0.6"
typescript: "npm:^5.4.5"
- ws: "npm:^7.5.0"
+ undici: "npm:^5.28.4"
bin:
replay: ./bin.js
languageName: unknown
@@ -3695,6 +3880,23 @@ __metadata:
languageName: node
linkType: hard
+"@swc/counter@npm:^0.1.3":
+ version: 0.1.3
+ resolution: "@swc/counter@npm:0.1.3"
+ checksum: 10c0/8424f60f6bf8694cfd2a9bca45845bce29f26105cda8cf19cdb9fd3e78dc6338699e4db77a89ae449260bafa1cc6bec307e81e7fb96dbf7dcfce0eea55151356
+ languageName: node
+ linkType: hard
+
+"@swc/helpers@npm:0.5.5":
+ version: 0.5.5
+ resolution: "@swc/helpers@npm:0.5.5"
+ dependencies:
+ "@swc/counter": "npm:^0.1.3"
+ tslib: "npm:^2.4.0"
+ checksum: 10c0/21a9b9cfe7e00865f9c9f3eb4c1cc5b397143464f7abee76a2c5366e591e06b0155b5aac93fe8269ef8d548df253f6fd931e9ddfc0fd12efd405f90f45506e7d
+ languageName: node
+ linkType: hard
+
"@testing-library/dom@npm:^8.0.0":
version: 8.20.1
resolution: "@testing-library/dom@npm:8.20.1"
@@ -3853,6 +4055,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/cookie@npm:^0.6.0":
+ version: 0.6.0
+ resolution: "@types/cookie@npm:0.6.0"
+ checksum: 10c0/5b326bd0188120fb32c0be086b141b1481fec9941b76ad537f9110e10d61ee2636beac145463319c71e4be67a17e85b81ca9e13ceb6e3bb63b93d16824d6c149
+ languageName: node
+ linkType: hard
+
"@types/debug@npm:^4.1.5, @types/debug@npm:^4.1.7, @types/debug@npm:^4.1.8":
version: 4.1.12
resolution: "@types/debug@npm:4.1.12"
@@ -4085,6 +4294,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/mute-stream@npm:^0.0.4":
+ version: 0.0.4
+ resolution: "@types/mute-stream@npm:0.0.4"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 10c0/944730fd7b398c5078de3c3d4d0afeec8584283bc694da1803fdfca14149ea385e18b1b774326f1601baf53898ce6d121a952c51eb62d188ef6fcc41f725c0dc
+ languageName: node
+ linkType: hard
+
"@types/node-fetch@npm:^2.5.10, @types/node-fetch@npm:^2.6.2, @types/node-fetch@npm:^2.6.3":
version: 2.6.11
resolution: "@types/node-fetch@npm:2.6.11"
@@ -4292,6 +4510,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/statuses@npm:^2.0.4":
+ version: 2.0.5
+ resolution: "@types/statuses@npm:2.0.5"
+ checksum: 10c0/4dacec0b29483a44be902a022a11a22b339de7a6e7b2059daa4f7add10cb6dbcc28d02d2a416fe9687e48d335906bf983065391836d4e7c847e55ddef4de8fad
+ languageName: node
+ linkType: hard
+
"@types/string.prototype.matchall@npm:^4.0.0":
version: 4.0.4
resolution: "@types/string.prototype.matchall@npm:4.0.4"
@@ -4361,6 +4586,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/wrap-ansi@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@types/wrap-ansi@npm:3.0.0"
+ checksum: 10c0/8d8f53363f360f38135301a06b596c295433ad01debd082078c33c6ed98b05a5c8fe8853a88265432126096084f4a135ec1564e3daad631b83296905509f90b3
+ languageName: node
+ linkType: hard
+
"@types/ws@npm:^8, @types/ws@npm:^8.5.10, @types/ws@npm:^8.5.5":
version: 8.5.10
resolution: "@types/ws@npm:8.5.10"
@@ -4986,7 +5218,7 @@ __metadata:
languageName: node
linkType: hard
-"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.1":
+"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0, ansi-escapes@npm:^4.3.1, ansi-escapes@npm:^4.3.2":
version: 4.3.2
resolution: "ansi-escapes@npm:4.3.2"
dependencies:
@@ -5876,6 +6108,15 @@ __metadata:
languageName: node
linkType: hard
+"busboy@npm:1.6.0":
+ version: 1.6.0
+ resolution: "busboy@npm:1.6.0"
+ dependencies:
+ streamsearch: "npm:^1.1.0"
+ checksum: 10c0/fa7e836a2b82699b6e074393428b91ae579d4f9e21f5ac468e1b459a244341d722d2d22d10920cdd849743dbece6dca11d72de939fb75a7448825cf2babfba1f
+ languageName: node
+ linkType: hard
+
"bvaughn-enquirer@npm:2.4.2":
version: 2.4.2
resolution: "bvaughn-enquirer@npm:2.4.2"
@@ -6009,6 +6250,13 @@ __metadata:
languageName: node
linkType: hard
+"caniuse-lite@npm:^1.0.30001579":
+ version: 1.0.30001636
+ resolution: "caniuse-lite@npm:1.0.30001636"
+ checksum: 10c0/e5f965b4da7bae1531fd9f93477d015729ff9e3fa12670ead39a9e6cdc4c43e62c272d47857c5cc332e7b02d697cb3f2f965a1030870ac7476da60c2fc81ee94
+ languageName: node
+ linkType: hard
+
"caniuse-lite@npm:^1.0.30001587":
version: 1.0.30001597
resolution: "caniuse-lite@npm:1.0.30001597"
@@ -6205,6 +6453,20 @@ __metadata:
languageName: node
linkType: hard
+"cli-width@npm:^4.1.0":
+ version: 4.1.0
+ resolution: "cli-width@npm:4.1.0"
+ checksum: 10c0/1fbd56413578f6117abcaf858903ba1f4ad78370a4032f916745fa2c7e390183a9d9029cf837df320b0fdce8137668e522f60a30a5f3d6529ff3872d265a955f
+ languageName: node
+ linkType: hard
+
+"client-only@npm:0.0.1":
+ version: 0.0.1
+ resolution: "client-only@npm:0.0.1"
+ checksum: 10c0/9d6cfd0c19e1c96a434605added99dff48482152af791ec4172fb912a71cff9027ff174efd8cdb2160cc7f377543e0537ffc462d4f279bc4701de3f2a3c4b358
+ languageName: node
+ linkType: hard
+
"cliui@npm:^6.0.0":
version: 6.0.0
resolution: "cliui@npm:6.0.0"
@@ -6514,6 +6776,13 @@ __metadata:
languageName: node
linkType: hard
+"cookie@npm:^0.5.0":
+ version: 0.5.0
+ resolution: "cookie@npm:0.5.0"
+ checksum: 10c0/c01ca3ef8d7b8187bae434434582288681273b5a9ed27521d4d7f9f7928fe0c920df0decd9f9d3bbd2d14ac432b8c8cf42b98b3bdd5bfe0e6edddeebebe8b61d
+ languageName: node
+ linkType: hard
+
"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1":
version: 3.36.1
resolution: "core-js-compat@npm:3.36.1"
@@ -9440,6 +9709,13 @@ __metadata:
languageName: node
linkType: hard
+"graphql@npm:^16.8.1":
+ version: 16.8.2
+ resolution: "graphql@npm:16.8.2"
+ checksum: 10c0/921a6321c4efe2540fd5a752093c1542f96cd10b3907b1a8044819f054e6e8a6bca78d93a8eada065a07dfd4e53d89eef99ebdced2c372453e05480e12d8652e
+ languageName: node
+ linkType: hard
+
"gzip-size@npm:^6.0.0":
version: 6.0.0
resolution: "gzip-size@npm:6.0.0"
@@ -9541,6 +9817,13 @@ __metadata:
languageName: node
linkType: hard
+"headers-polyfill@npm:^4.0.2":
+ version: 4.0.3
+ resolution: "headers-polyfill@npm:4.0.3"
+ checksum: 10c0/53e85b2c6385f8d411945fb890c5369f1469ce8aa32a6e8d28196df38568148de640c81cf88cbc7c67767103dd9acba48f4f891982da63178fc6e34560022afe
+ languageName: node
+ linkType: hard
+
"hoopy@npm:^0.1.4":
version: 0.1.4
resolution: "hoopy@npm:0.1.4"
@@ -10229,6 +10512,13 @@ __metadata:
languageName: node
linkType: hard
+"is-node-process@npm:^1.2.0":
+ version: 1.2.0
+ resolution: "is-node-process@npm:1.2.0"
+ checksum: 10c0/5b24fda6776d00e42431d7bcd86bce81cb0b6cabeb944142fe7b077a54ada2e155066ad06dbe790abdb397884bdc3151e04a9707b8cd185099efbc79780573ed
+ languageName: node
+ linkType: hard
+
"is-number-object@npm:^1.0.4":
version: 1.0.7
resolution: "is-number-object@npm:1.0.7"
@@ -12585,6 +12875,38 @@ __metadata:
languageName: node
linkType: hard
+"msw@npm:2.3.0-ws.rc-6":
+ version: 2.3.0-ws.rc-6
+ resolution: "msw@npm:2.3.0-ws.rc-6"
+ dependencies:
+ "@bundled-es-modules/cookie": "npm:^2.0.0"
+ "@bundled-es-modules/statuses": "npm:^1.0.1"
+ "@inquirer/confirm": "npm:^3.0.0"
+ "@mswjs/cookies": "npm:^1.1.0"
+ "@mswjs/interceptors": "npm:^0.27.1"
+ "@open-draft/until": "npm:^2.1.0"
+ "@types/cookie": "npm:^0.6.0"
+ "@types/statuses": "npm:^2.0.4"
+ chalk: "npm:^4.1.2"
+ graphql: "npm:^16.8.1"
+ headers-polyfill: "npm:^4.0.2"
+ is-node-process: "npm:^1.2.0"
+ outvariant: "npm:^1.4.2"
+ path-to-regexp: "npm:^6.2.0"
+ strict-event-emitter: "npm:^0.5.1"
+ type-fest: "npm:^4.9.0"
+ yargs: "npm:^17.7.2"
+ peerDependencies:
+ typescript: ">= 4.7.x"
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ bin:
+ msw: cli/index.js
+ checksum: 10c0/1ac620e5bce3a193507c14d3cb213f03f0cc6ec11eca849ae3c61c420ae2768d23617569d222bef156ab857afd53012a20208909828e414fe5d39d7b57ca241a
+ languageName: node
+ linkType: hard
+
"multicast-dns@npm:^7.2.5":
version: 7.2.5
resolution: "multicast-dns@npm:7.2.5"
@@ -12604,6 +12926,13 @@ __metadata:
languageName: node
linkType: hard
+"mute-stream@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "mute-stream@npm:1.0.0"
+ checksum: 10c0/dce2a9ccda171ec979a3b4f869a102b1343dee35e920146776780de182f16eae459644d187e38d59a3d37adf85685e1c17c38cf7bfda7e39a9880f7a1d10a74c
+ languageName: node
+ linkType: hard
+
"mz@npm:^2.7.0":
version: 2.7.0
resolution: "mz@npm:2.7.0"
@@ -12615,7 +12944,7 @@ __metadata:
languageName: node
linkType: hard
-"nanoid@npm:^3.3.7":
+"nanoid@npm:^3.3.6, nanoid@npm:^3.3.7":
version: 3.3.7
resolution: "nanoid@npm:3.3.7"
bin:
@@ -12652,6 +12981,64 @@ __metadata:
languageName: node
linkType: hard
+"next@npm:^14.2.4":
+ version: 14.2.4
+ resolution: "next@npm:14.2.4"
+ dependencies:
+ "@next/env": "npm:14.2.4"
+ "@next/swc-darwin-arm64": "npm:14.2.4"
+ "@next/swc-darwin-x64": "npm:14.2.4"
+ "@next/swc-linux-arm64-gnu": "npm:14.2.4"
+ "@next/swc-linux-arm64-musl": "npm:14.2.4"
+ "@next/swc-linux-x64-gnu": "npm:14.2.4"
+ "@next/swc-linux-x64-musl": "npm:14.2.4"
+ "@next/swc-win32-arm64-msvc": "npm:14.2.4"
+ "@next/swc-win32-ia32-msvc": "npm:14.2.4"
+ "@next/swc-win32-x64-msvc": "npm:14.2.4"
+ "@swc/helpers": "npm:0.5.5"
+ busboy: "npm:1.6.0"
+ caniuse-lite: "npm:^1.0.30001579"
+ graceful-fs: "npm:^4.2.11"
+ postcss: "npm:8.4.31"
+ styled-jsx: "npm:5.1.1"
+ peerDependencies:
+ "@opentelemetry/api": ^1.1.0
+ "@playwright/test": ^1.41.2
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ sass: ^1.3.0
+ dependenciesMeta:
+ "@next/swc-darwin-arm64":
+ optional: true
+ "@next/swc-darwin-x64":
+ optional: true
+ "@next/swc-linux-arm64-gnu":
+ optional: true
+ "@next/swc-linux-arm64-musl":
+ optional: true
+ "@next/swc-linux-x64-gnu":
+ optional: true
+ "@next/swc-linux-x64-musl":
+ optional: true
+ "@next/swc-win32-arm64-msvc":
+ optional: true
+ "@next/swc-win32-ia32-msvc":
+ optional: true
+ "@next/swc-win32-x64-msvc":
+ optional: true
+ peerDependenciesMeta:
+ "@opentelemetry/api":
+ optional: true
+ "@playwright/test":
+ optional: true
+ sass:
+ optional: true
+ bin:
+ next: dist/bin/next
+ checksum: 10c0/630c2a197b57c1f29caf4672a0f8fb74dbb048e77e4513f567279467332212f3eebcb68279885f1d525d7aaebbb452f522b02c0b5cd3ca66f385341e4b4eac67
+ languageName: node
+ linkType: hard
+
"no-case@npm:^3.0.4":
version: 3.0.4
resolution: "no-case@npm:3.0.4"
@@ -13069,6 +13456,13 @@ __metadata:
languageName: node
linkType: hard
+"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0, outvariant@npm:^1.4.2":
+ version: 1.4.2
+ resolution: "outvariant@npm:1.4.2"
+ checksum: 10c0/48041425a4cb725ff8871b7d9889bfc2eaded867b9b35b6c2450a36fb3632543173098654990caa6c9e9f67d902b2a01f4402c301835e9ecaf4b4695d3161853
+ languageName: node
+ linkType: hard
+
"p-filter@npm:^2.1.0":
version: 2.1.0
resolution: "p-filter@npm:2.1.0"
@@ -13270,6 +13664,13 @@ __metadata:
languageName: node
linkType: hard
+"path-to-regexp@npm:^6.2.0":
+ version: 6.2.2
+ resolution: "path-to-regexp@npm:6.2.2"
+ checksum: 10c0/4b60852d3501fd05ca9dd08c70033d73844e5eca14e41f499f069afa8364f780f15c5098002f93bd42af8b3514de62ac6e82a53b5662de881d2b08c9ef21ea6b
+ languageName: node
+ linkType: hard
+
"path-type@npm:^4.0.0":
version: 4.0.0
resolution: "path-type@npm:4.0.0"
@@ -14211,6 +14612,17 @@ __metadata:
languageName: node
linkType: hard
+"postcss@npm:8.4.31":
+ version: 8.4.31
+ resolution: "postcss@npm:8.4.31"
+ dependencies:
+ nanoid: "npm:^3.3.6"
+ picocolors: "npm:^1.0.0"
+ source-map-js: "npm:^1.0.2"
+ checksum: 10c0/748b82e6e5fc34034dcf2ae88ea3d11fd09f69b6c50ecdd3b4a875cfc7cdca435c958b211e2cb52355422ab6fccb7d8f2f2923161d7a1b281029e4a913d59acf
+ languageName: node
+ linkType: hard
+
"postcss@npm:^7.0.35":
version: 7.0.39
resolution: "postcss@npm:7.0.39"
@@ -14648,6 +15060,18 @@ __metadata:
languageName: node
linkType: hard
+"react-dom@npm:^18.3.1":
+ version: 18.3.1
+ resolution: "react-dom@npm:18.3.1"
+ dependencies:
+ loose-envify: "npm:^1.1.0"
+ scheduler: "npm:^0.23.2"
+ peerDependencies:
+ react: ^18.3.1
+ checksum: 10c0/a752496c1941f958f2e8ac56239172296fcddce1365ce45222d04a1947e0cc5547df3e8447f855a81d6d39f008d7c32eab43db3712077f09e3f67c4874973e85
+ languageName: node
+ linkType: hard
+
"react-error-overlay@npm:^6.0.11":
version: 6.0.11
resolution: "react-error-overlay@npm:6.0.11"
@@ -14836,6 +15260,15 @@ __metadata:
languageName: node
linkType: hard
+"react@npm:^18.3.1":
+ version: 18.3.1
+ resolution: "react@npm:18.3.1"
+ dependencies:
+ loose-envify: "npm:^1.1.0"
+ checksum: 10c0/283e8c5efcf37802c9d1ce767f302dd569dd97a70d9bb8c7be79a789b9902451e0d16334b05d73299b20f048cbc3c7d288bbbde10b701fa194e2089c237dbea3
+ languageName: node
+ linkType: hard
+
"read-cache@npm:^1.0.0":
version: 1.0.0
resolution: "read-cache@npm:1.0.0"
@@ -15072,7 +15505,6 @@ __metadata:
prettier: "npm:^2.7.1"
replayio: "workspace:^"
typescript: "npm:^5.4.5"
- ws: "npm:^8.17.0"
languageName: unknown
linkType: soft
@@ -15116,7 +15548,6 @@ __metadata:
ts-jest: "npm:^28.0.6"
typescript: "npm:^5.4.5"
undici: "npm:^5.28.4"
- ws: "npm:^7.5.0"
bin:
replayio: ./replayio.js
languageName: unknown
@@ -15482,6 +15913,15 @@ __metadata:
languageName: node
linkType: hard
+"scheduler@npm:^0.23.2":
+ version: 0.23.2
+ resolution: "scheduler@npm:0.23.2"
+ dependencies:
+ loose-envify: "npm:^1.1.0"
+ checksum: 10c0/26383305e249651d4c58e6705d5f8425f153211aef95f15161c151f7b8de885f24751b377e4a0b3dd42cce09aad3f87a61dab7636859c0d89b7daf1a1e2a5c78
+ languageName: node
+ linkType: hard
+
"schema-utils@npm:2.7.0":
version: 2.7.0
resolution: "schema-utils@npm:2.7.0"
@@ -15751,7 +16191,7 @@ __metadata:
languageName: node
linkType: hard
-"signal-exit@npm:^4.0.1":
+"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0":
version: 4.1.0
resolution: "signal-exit@npm:4.1.0"
checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83
@@ -15927,7 +16367,7 @@ __metadata:
languageName: node
linkType: hard
-"source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.0":
+"source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0":
version: 1.2.0
resolution: "source-map-js@npm:1.2.0"
checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4
@@ -16160,7 +16600,7 @@ __metadata:
languageName: node
linkType: hard
-"statuses@npm:2.0.1":
+"statuses@npm:2.0.1, statuses@npm:^2.0.1":
version: 2.0.1
resolution: "statuses@npm:2.0.1"
checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0
@@ -16201,6 +16641,20 @@ __metadata:
languageName: node
linkType: hard
+"streamsearch@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "streamsearch@npm:1.1.0"
+ checksum: 10c0/fbd9aecc2621364384d157f7e59426f4bfd385e8b424b5aaa79c83a6f5a1c8fd2e4e3289e95de1eb3511cb96bb333d6281a9919fafce760e4edb35b2cd2facab
+ languageName: node
+ linkType: hard
+
+"strict-event-emitter@npm:^0.5.1":
+ version: 0.5.1
+ resolution: "strict-event-emitter@npm:0.5.1"
+ checksum: 10c0/f5228a6e6b6393c57f52f62e673cfe3be3294b35d6f7842fc24b172ae0a6e6c209fa83241d0e433fc267c503bc2f4ffdbe41a9990ff8ffd5ac425ec0489417f7
+ languageName: node
+ linkType: hard
+
"string-length@npm:^4.0.1":
version: 4.0.2
resolution: "string-length@npm:4.0.2"
@@ -16443,6 +16897,22 @@ __metadata:
languageName: node
linkType: hard
+"styled-jsx@npm:5.1.1":
+ version: 5.1.1
+ resolution: "styled-jsx@npm:5.1.1"
+ dependencies:
+ client-only: "npm:0.0.1"
+ peerDependencies:
+ react: ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ peerDependenciesMeta:
+ "@babel/core":
+ optional: true
+ babel-plugin-macros:
+ optional: true
+ checksum: 10c0/42655cdadfa5388f8a48bb282d6b450df7d7b8cf066ac37038bd0499d3c9f084815ebd9ff9dfa12a218fd4441338851db79603498d7557207009c1cf4d609835
+ languageName: node
+ linkType: hard
+
"stylehacks@npm:^5.1.1":
version: 5.1.1
resolution: "stylehacks@npm:5.1.1"
@@ -17004,6 +17474,13 @@ __metadata:
languageName: node
linkType: hard
+"tslib@npm:^2.4.0":
+ version: 2.6.3
+ resolution: "tslib@npm:2.6.3"
+ checksum: 10c0/2598aef53d9dbe711af75522464b2104724d6467b26a60f2bdac8297d2b5f1f6b86a71f61717384aa8fd897240467aaa7bcc36a0700a0faf751293d1331db39a
+ languageName: node
+ linkType: hard
+
"tsutils@npm:^3.21.0":
version: 3.21.0
resolution: "tsutils@npm:3.21.0"
@@ -17124,6 +17601,13 @@ __metadata:
languageName: node
linkType: hard
+"type-fest@npm:^4.9.0":
+ version: 4.20.1
+ resolution: "type-fest@npm:4.20.1"
+ checksum: 10c0/c31da16fe170a74c5b7e102e70e764ba8ec6ade128e782a56f842aefa07307df5a6353e6b5601d3b30ff2d856d8b955f89813df639e4758fedcf8e426b2d854e
+ languageName: node
+ linkType: hard
+
"type-is@npm:~1.6.18":
version: 1.6.18
resolution: "type-is@npm:1.6.18"
@@ -18324,7 +18808,7 @@ __metadata:
languageName: node
linkType: hard
-"ws@npm:^7.4.6, ws@npm:^7.5.0":
+"ws@npm:^7.4.6":
version: 7.5.9
resolution: "ws@npm:7.5.9"
peerDependencies:
@@ -18354,21 +18838,6 @@ __metadata:
languageName: node
linkType: hard
-"ws@npm:^8.17.0":
- version: 8.17.0
- resolution: "ws@npm:8.17.0"
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: ">=5.0.2"
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
- checksum: 10c0/55241ec93a66fdfc4bf4f8bc66c8eb038fda2c7a4ee8f6f157f2ca7dc7aa76aea0c0da0bf3adb2af390074a70a0e45456a2eaf80e581e630b75df10a64b0a990
- languageName: node
- linkType: hard
-
"xml-name-validator@npm:^3.0.0":
version: 3.0.0
resolution: "xml-name-validator@npm:3.0.0"
@@ -18492,7 +18961,7 @@ __metadata:
languageName: node
linkType: hard
-"yargs@npm:^17.3.1, yargs@npm:^17.7.1":
+"yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2":
version: 17.7.2
resolution: "yargs@npm:17.7.2"
dependencies: