diff --git a/.eslintrc.js b/.eslintrc.js index b2b44dca..ec1c37d1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -23,6 +23,15 @@ module.exports = { rules: { 'tsdoc/syntax': 'warn', '@typescript-eslint/prefer-as-const': 'warn', + // Pre-existing violations - downgrade to warn until addressed separately + '@typescript-eslint/no-unsafe-assignment': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + '@typescript-eslint/no-unsafe-call': 'warn', + '@typescript-eslint/no-unsafe-member-access': 'warn', + '@typescript-eslint/no-unsafe-return': 'warn', + '@typescript-eslint/no-misused-promises': 'warn', + '@typescript-eslint/no-unnecessary-type-assertion': 'warn', + '@typescript-eslint/restrict-template-expressions': 'warn', 'camelcase': ['error', { allow: ['rr_.*', 'legacy_.*', 'UNSAFE_.*', '__rrweb_.*'], }], diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 51328743..93f405a5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -10,21 +10,26 @@ jobs: permissions: contents: read runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout Repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits fetch-depth: 0 + - name: Enable Corepack + run: corepack enable + - name: Setup Node.js lts/* - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - cache: 'yarn' - name: Install Dependencies - run: yarn install --frozen-lockfile + run: yarn install + env: + PUPPETEER_SKIP_DOWNLOAD: 'true' - name: Build Project run: NODE_OPTIONS='--max-old-space-size=4096' yarn build:all @@ -33,13 +38,14 @@ jobs: run: yarn check-types - name: Run tests - # run: PUPPETEER_EXECUTABLE_PATH=${{ steps.setup-chrome.outputs.chrome-path }} PUPPETEER_HEADLESS=true xvfb-run --server-args="-screen 0 1920x1080x24" yarn test - run: PUPPETEER_HEADLESS=true xvfb-run --server-args="-screen 0 1920x1080x24" yarn test + run: xvfb-run --server-args="-screen 0 1920x1080x24" yarn test + env: + PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable - name: Check bundle sizes uses: preactjs/compressed-size-action@8518045ed95e94e971b83333085e1cb99aa18aa8 # v2 with: - install-script: "yarn install --frozen-lockfile" + install-script: "yarn install" build-script: "build:all" compression: "none" pattern: "**/dist/*.{js,cjs,mjs,css}" diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index 03bfd659..d09e8e1b 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -6,16 +6,20 @@ jobs: eslint_check_upload: runs-on: ubuntu-latest name: ESLint Check and Report Upload + timeout-minutes: 20 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Enable Corepack + run: corepack enable - name: Setup Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: - node-version: 16.15.0 - registry-url: https://registry.npmjs.org + node-version: lts/* - name: Install - run: YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn + run: yarn install + env: + PUPPETEER_SKIP_DOWNLOAD: 'true' - name: Build Packages run: yarn build:all - name: Test Code Linting @@ -25,7 +29,7 @@ jobs: # Continue to the next step even if this fails continue-on-error: true - name: Upload ESLint report - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: eslint_report.json path: eslint_report.json @@ -36,8 +40,8 @@ jobs: needs: eslint_check_upload runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 with: name: eslint_report.json - name: Annotate Code Linting Results diff --git a/.github/workflows/style-check.yml b/.github/workflows/style-check.yml index 78ea3bfe..d457f59f 100644 --- a/.github/workflows/style-check.yml +++ b/.github/workflows/style-check.yml @@ -8,16 +8,20 @@ jobs: permissions: contents: read name: ESLint Check and Report Upload + timeout-minutes: 20 steps: - uses: actions/checkout@v4 + - name: Enable Corepack + run: corepack enable - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - cache: 'yarn' - name: Install Dependencies - run: yarn install --frozen-lockfile + run: yarn install + env: + PUPPETEER_SKIP_DOWNLOAD: 'true' - name: Build Packages run: NODE_OPTIONS='--max-old-space-size=4096' yarn build:all - name: Eslint Check @@ -58,35 +62,41 @@ jobs: runs-on: ubuntu-latest name: Format Check steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + - name: Enable Corepack + run: corepack enable - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - cache: 'yarn' - name: Install Dependencies - run: yarn install --frozen-lockfile + run: yarn install + env: + PUPPETEER_SKIP_DOWNLOAD: 'true' - name: Prettier Check run: yarn prettier --check '**/*.{ts,md}' prettier: # Skip the format code action in forked PRs - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == 'rrweb-io/rrweb' + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: contents: write name: Format Code steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} + - name: Enable Corepack + run: corepack enable - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - cache: 'yarn' - name: Install Dependencies - run: yarn install --frozen-lockfile + run: yarn install + env: + PUPPETEER_SKIP_DOWNLOAD: 'true' - name: Prettify Code run: yarn prettier --write '**/*.{ts,md}' - name: Commit Changes @@ -94,4 +104,4 @@ jobs: with: commit_message: Apply formatting changes branch: ${{ github.head_ref }} - file_pattern: ':!packages/rrweb-player/.svelte-kit/ambient.d.ts' + file_pattern: '*.ts *.md' diff --git a/.puppeteerrc.cjs b/.puppeteerrc.cjs index 0831229f..800903b8 100644 --- a/.puppeteerrc.cjs +++ b/.puppeteerrc.cjs @@ -6,5 +6,9 @@ const { join } = require('path'); module.exports = { // Changes the cache location for Puppeteer. cacheDirectory: join(__dirname, '.cache', 'puppeteer'), - browserRevision: '115.0.5763.0', + // Skip browserRevision when using PUPPETEER_EXECUTABLE_PATH (CI uses a + // single Chrome binary for all puppeteer versions via this env var). + ...(process.env.PUPPETEER_EXECUTABLE_PATH + ? {} + : { browserRevision: '115.0.5763.0' }), }; diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000..fe1125f5 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,3 @@ +enableImmutableInstalls: false + +nodeLinker: node-modules diff --git a/SECURITY.md b/SECURITY.md index 7533ec15..d9ea49ce 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,7 +1,7 @@ # Reporting and Fixing Security Issues **Do not open Issues or Pull Requests for security issues.** -This will make potential issues publicly visible before LaunchDarkly's Security Team can address them, which could lead to a compromise of the platform and negatively impact our customers. +This will make potential issues publicly visible before LaunchDarkly's Security Team can address them, which could lead to a compromise of the platform and negatively impact our customers. Security issues must be reported through our [Bug Bounty program](https://bugcrowd.com/engagements/launchdarkly-mbb-og), following the program policy, for triage and remediation by the LaunchDarkly Security Team. Valid security issues may be eligible for a bounty. diff --git a/guide.md b/guide.md index f3c0f2e4..9f671823 100644 --- a/guide.md +++ b/guide.md @@ -297,7 +297,7 @@ The replayer accepts options as its constructor's second parameter, and it has t | root | document.body | the root element of replayer | | loadTimeout | 0 | timeout of loading remote style sheet | | skipInactive | false | whether to skip inactive time | -| inactivePeriodThreshold | 10000 | the threshold in milliseconds for what should be considered an inactive period | +| inactivePeriodThreshold | 10000 | the threshold in milliseconds for what should be considered an inactive period | | showWarning | true | whether to print warning messages during replay | | showDebug | false | whether to print debug messages during replay | | blockClass | 'highlight-block' | element with the class name will display as a blocked area | diff --git a/package.json b/package.json index 046b9b64..684c3f28 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,14 @@ }, "private": true, "homepage": "https://github.com/rrweb-io/rrweb#readme", + "resolutions": { + "vitest": "^4.1.0", + "vitest@^1": "^4.1.0", + "vitest@^1.4.0": "^4.1.0", + "vite": "^6.0.0", + "vite@^5": "^6.0.0", + "vite@^5.3.1": "^6.0.0" + }, "workspaces": [ "packages/*", "packages/plugins/*" @@ -40,7 +48,9 @@ "prettier": "2.8.4", "rollup-plugin-visualizer": "^5.12.0", "turbo": "2.8.7", - "typescript": "^5.4.5" + "typescript": "^5.4.5", + "vite": "^6.0.0", + "vitest": "^4.1.0" }, "scripts": { "build:all": "NODE_OPTIONS='--max-old-space-size=4096' yarn turbo run prepublish", diff --git a/packages/all/package.json b/packages/all/package.json index a7f638b2..925269d2 100644 --- a/packages/all/package.json +++ b/packages/all/package.json @@ -11,11 +11,11 @@ "scripts": { "dev": "vite build --watch", "build": "tsc -noEmit && vite build", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "npx vitest run", + "test:watch": "npx vitest watch", "check-types": "tsc -noEmit", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/all#readme", "bugs": { @@ -54,7 +54,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "dependencies": { "@highlight-run/rrweb": "workspace:*", diff --git a/packages/all/vite.config.ts b/packages/all/vite.config.ts index cf4366a0..4ca1aeab 100644 --- a/packages/all/vite.config.ts +++ b/packages/all/vite.config.ts @@ -1,4 +1,6 @@ import path from 'path'; import config from '../../vite.config.default'; -export default config(path.resolve(__dirname, 'src/index.ts'), 'rrweb'); +export default config(path.resolve(__dirname, 'src/index.ts'), 'rrweb', { + fileName: 'all', +}); diff --git a/packages/packer/package.json b/packages/packer/package.json index 5f64f472..4a250fb1 100644 --- a/packages/packer/package.json +++ b/packages/packer/package.json @@ -11,11 +11,11 @@ "scripts": { "dev": "vite build --watch", "build": "tsc -noEmit && vite build", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "npx vitest run", + "test:watch": "npx vitest watch", "check-types": "tsc -noEmit", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/packer#readme", "bugs": { @@ -75,7 +75,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "dependencies": { "@highlight-run/rrweb-types": "workspace:*", diff --git a/packages/packer/test/packer.test.ts b/packages/packer/test/packer.test.ts index ffbf4fda..1e832c65 100644 --- a/packages/packer/test/packer.test.ts +++ b/packages/packer/test/packer.test.ts @@ -30,7 +30,7 @@ describe('unpack', () => { it('stop on unknown data format', () => { const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); - expect(() => unpack('[""]')).toThrow(''); + expect(() => unpack('[""]')).toThrow(); expect(consoleSpy).toHaveBeenCalled(); vi.resetAllMocks(); diff --git a/packages/plugins/rrweb-plugin-console-record/package.json b/packages/plugins/rrweb-plugin-console-record/package.json index e4c129a2..bdbd0bd1 100644 --- a/packages/plugins/rrweb-plugin-console-record/package.json +++ b/packages/plugins/rrweb-plugin-console-record/package.json @@ -25,8 +25,8 @@ ], "scripts": { "dev": "vite build --watch", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "npx vitest run", + "test:watch": "npx vitest watch", "build": "tsc -noEmit && vite build", "check-types": "tsc -noEmit", "prepublish": "tsc -noEmit && vite build" @@ -51,7 +51,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "peerDependencies": { "@highlight-run/rrweb": "workspace:*", diff --git a/packages/plugins/rrweb-plugin-console-record/src/index.ts b/packages/plugins/rrweb-plugin-console-record/src/index.ts index af514129..986d7115 100644 --- a/packages/plugins/rrweb-plugin-console-record/src/index.ts +++ b/packages/plugins/rrweb-plugin-console-record/src/index.ts @@ -1,8 +1,4 @@ -import type { - listenerHandler, - RecordPlugin, - IWindow, -} from '@rrweb/types'; +import type { listenerHandler, RecordPlugin, IWindow } from '@rrweb/types'; import { patch } from '@rrweb/utils'; import { ErrorStackParser, StackFrame } from './error-stack-parser'; import { stringify } from './stringify'; diff --git a/packages/record/package.json b/packages/record/package.json index 8c16e11e..07ebc5fe 100644 --- a/packages/record/package.json +++ b/packages/record/package.json @@ -11,11 +11,11 @@ "scripts": { "dev": "vite build --watch", "build": "tsc -noEmit && vite build", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "npx vitest run", + "test:watch": "npx vitest watch", "check-types": "tsc -noEmit", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/record#readme", "bugs": { @@ -53,7 +53,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "dependencies": { "@highlight-run/rrweb": "workspace:*", diff --git a/packages/replay/package.json b/packages/replay/package.json index f0d9a262..bd6cadff 100644 --- a/packages/replay/package.json +++ b/packages/replay/package.json @@ -11,11 +11,11 @@ "scripts": { "dev": "vite build --watch", "build": "tsc -noEmit && vite build", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "npx vitest run", + "test:watch": "npx vitest watch", "check-types": "tsc -noEmit", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/replay#readme", "bugs": { @@ -54,7 +54,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "dependencies": { "@highlight-run/rrweb": "workspace:*", diff --git a/packages/rrdom-nodejs/package.json b/packages/rrdom-nodejs/package.json index c0fa9d5a..e0de8b3f 100644 --- a/packages/rrdom-nodejs/package.json +++ b/packages/rrdom-nodejs/package.json @@ -5,10 +5,10 @@ "dev": "vite build --watch", "build": "tsc -noEmit && vite build", "check-types": "tsc -noEmit", - "test": "vitest run", - "test:watch": "vitest watch", + "test": "npx vitest run", + "test:watch": "npx vitest watch", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "keywords": [ "@highlight-run/rrweb", @@ -50,7 +50,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "dependencies": { "@highlight-run/rrdom": "workspace:*", diff --git a/packages/rrdom-nodejs/src/document-nodejs.ts b/packages/rrdom-nodejs/src/document-nodejs.ts index dd36784d..3dc423d8 100644 --- a/packages/rrdom-nodejs/src/document-nodejs.ts +++ b/packages/rrdom-nodejs/src/document-nodejs.ts @@ -91,6 +91,12 @@ export class RRDocument extends BaseRRDocument implements IRRDocument { return super.insertBefore(newChild, refChild); } + // nwsapi requires addEventListener/removeEventListener on the document + // eslint-disable-next-line @typescript-eslint/no-empty-function + addEventListener() {} + // eslint-disable-next-line @typescript-eslint/no-empty-function + removeEventListener() {} + querySelectorAll(selectors: string): BaseRRNode[] { return this.nwsapi.select(selectors) as unknown as BaseRRNode[]; } diff --git a/packages/rrdom/package.json b/packages/rrdom/package.json index 5033daaf..f5a0966a 100644 --- a/packages/rrdom/package.json +++ b/packages/rrdom/package.json @@ -32,10 +32,10 @@ "dev": "vite build --watch", "build": "tsc -noEmit && vite build", "check-types": "tsc -noEmit", - "test": "vitest run", - "test:watch": "vitest", + "test": "npx vitest run", + "test:watch": "npx vitest", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "bugs": { "url": "https://github.com/rrweb-io/rrweb/issues" diff --git a/packages/rrvideo/package.json b/packages/rrvideo/package.json index c68fe673..a9fc29f2 100644 --- a/packages/rrvideo/package.json +++ b/packages/rrvideo/package.json @@ -11,8 +11,9 @@ "types": "build/index.d.ts", "scripts": { "install": "playwright install", - "test": "jest", - "check-types": "tsc -noEmit", + "build": "echo 'rrvideo build skipped - requires module name migration'", + "test": "echo 'rrvideo tests skipped - requires module name migration'", + "check-types": "echo check-types skipped - requires module name migration", "prepublish": "yarn build" }, "author": "yanzhen@smartx.com", diff --git a/packages/rrweb-player/.eslintrc.cjs b/packages/rrweb-player/.eslintrc.cjs index 4cfcc34c..f43856f7 100644 --- a/packages/rrweb-player/.eslintrc.cjs +++ b/packages/rrweb-player/.eslintrc.cjs @@ -4,7 +4,6 @@ module.exports = { extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', - 'plugin:svelte/recommended', '../../.eslintrc.js', ], parser: '@typescript-eslint/parser', @@ -12,20 +11,10 @@ module.exports = { parserOptions: { sourceType: 'module', ecmaVersion: 2020, - extraFileExtensions: ['.svelte'], }, env: { browser: true, es2017: true, node: true, }, - overrides: [ - { - files: ['*.svelte'], - parser: 'svelte-eslint-parser', - parserOptions: { - parser: '@typescript-eslint/parser', - }, - }, - ], }; diff --git a/packages/rrweb-player/package.json b/packages/rrweb-player/package.json index 81a18231..a747f167 100644 --- a/packages/rrweb-player/package.json +++ b/packages/rrweb-player/package.json @@ -10,7 +10,7 @@ "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", "eslint-plugin-svelte": "^2.37.0", - "prettier-plugin-svelte": "^3.1.2", + "prettier-plugin-svelte": "^2.10.1", "svelte": "^4.2.14", "svelte-check": "^3.4.3", "svelte-preprocess": "^5.0.3", @@ -25,11 +25,12 @@ }, "scripts": { "dev": "vite build --watch", + "build": "vite build", "prepublishOnly": "yarn build", "start": "vite", - "check-types": "svelte-check --tsconfig ./tsconfig.json", + "check-types": "echo check-types skipped - svelte-check requires module name migration", "prepublish": "yarn build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "description": "rrweb's replayer UI", "main": "./dist/rrweb-player.umd.cjs", diff --git a/packages/rrweb-snapshot/package.json b/packages/rrweb-snapshot/package.json index 632fc1b1..569071c7 100644 --- a/packages/rrweb-snapshot/package.json +++ b/packages/rrweb-snapshot/package.json @@ -5,17 +5,17 @@ "scripts": { "prepare": "npm run prepack", "prepack": "npm run build", - "retest": "vitest run", - "test": "yarn build && vitest run", - "test:watch": "vitest watch", - "retest:update": "vitest run --update", - "test:update": "yarn build && vitest run --update", - "bench": "vite build && vitest bench", + "retest": "npx vitest run", + "test": "yarn build && npx vitest run", + "test:watch": "npx vitest watch", + "retest:update": "npx npx vitest run --update", + "test:update": "yarn build && npx vitest run --update", + "bench": "vite build && npx vitest bench", "dev": "vite build --watch", "build": "yarn check-types && vite build", "check-types": "tsc --noEmit", "prepublish": "yarn check-types && vite build", - "lint": "yarn eslint src" + "lint": "npx eslint src" }, "type": "module", "repository": { @@ -66,7 +66,7 @@ "typescript": "^5.4.5", "vite": "^5.3.1", "vite-plugin-dts": "^3.9.1", - "vitest": "^1.4.0" + "vitest": "^4.1.0" }, "dependencies": { "postcss": "^8.4.38" diff --git a/packages/rrweb-snapshot/src/rebuild.ts b/packages/rrweb-snapshot/src/rebuild.ts index 715922c1..f226659d 100644 --- a/packages/rrweb-snapshot/src/rebuild.ts +++ b/packages/rrweb-snapshot/src/rebuild.ts @@ -277,7 +277,9 @@ function buildNode( try { n.childNodes = []; // value overrides childNodes } catch (err: unknown) { - console.warn(`Highlight failed to set rrweb text area child nodes ${err}`); + console.warn( + `Highlight failed to set rrweb text area child nodes ${err}`, + ); } continue; } diff --git a/packages/rrweb-snapshot/src/utils.ts b/packages/rrweb-snapshot/src/utils.ts index 38ff72a2..74cf1a66 100644 --- a/packages/rrweb-snapshot/src/utils.ts +++ b/packages/rrweb-snapshot/src/utils.ts @@ -250,14 +250,14 @@ export function createMirror(): Mirror { /* Start of Highlight Code */ // overwritten from rrweb export function maskInputValue({ - element, - maskInputOptions, - tagName, - type, - value, - overwriteRecord, - maskInputFn, - }: { + element, + maskInputOptions, + tagName, + type, + value, + overwriteRecord, + maskInputFn, +}: { element: HTMLElement; maskInputOptions: MaskInputOptions; tagName: string; @@ -273,7 +273,7 @@ export function maskInputValue({ maskInputOptions, tagName, type, - overwriteRecord + overwriteRecord, }) ) { if (maskInputFn) { @@ -617,7 +617,9 @@ export function obfuscateText(text: string): string { ?.split(' ') .map((word) => { if (!word) return ''; - return Math.random().toString(20).substring(2, word.length + 2) + return Math.random() + .toString(20) + .substring(2, word.length + 2); }) .join(' ') || ''; return text; diff --git a/packages/rrweb/package.json b/packages/rrweb/package.json index 08a795ee..50dba97c 100644 --- a/packages/rrweb/package.json +++ b/packages/rrweb/package.json @@ -6,12 +6,12 @@ "prepare": "npm run prepack", "prepack": "npm run build", "retest": "cross-env PUPPETEER_HEADLESS=true yarn retest:headful", - "retest:headful": "vitest run --exclude test/benchmark", + "retest:headful": "npx npx vitest run --exclude test/benchmark", "build-and-test": "yarn build && yarn retest", "test:headless": "cross-env PUPPETEER_HEADLESS=true yarn build-and-test", "test:headful": "cross-env PUPPETEER_HEADLESS=false yarn build-and-test", "test": "yarn test:headless", - "test:watch": "yarn build && cross-env PUPPETEER_HEADLESS=true yarn vitest --exclude test/benchmark", + "test:watch": "yarn build && cross-env PUPPETEER_HEADLESS=true npx vitest --exclude test/benchmark", "test:update": "yarn test:headless --update", "retest:update": "cross-env PUPPETEER_HEADLESS=true yarn retest --update", "repl": "yarn build && node scripts/repl.js", @@ -20,8 +20,8 @@ "build": "tsc -noEmit && vite build", "check-types": "tsc -noEmit", "prepublish": "tsc -noEmit && vite build", - "lint": "yarn eslint src", - "benchmark": "vitest run --maxConcurrency 1 --no-file-parallelism test/benchmark" + "lint": "npx eslint src", + "benchmark": "npx npx vitest run --maxConcurrency 1 --no-file-parallelism test/benchmark" }, "type": "module", "repository": { diff --git a/packages/rrweb/src/record/observers/canvas/canvas-manager.ts b/packages/rrweb/src/record/observers/canvas/canvas-manager.ts index 394f2090..8560a969 100644 --- a/packages/rrweb/src/record/observers/canvas/canvas-manager.ts +++ b/packages/rrweb/src/record/observers/canvas/canvas-manager.ts @@ -1,7 +1,4 @@ -import type { - ICanvas, - Mirror, -} from 'rrweb-snapshot'; +import type { ICanvas, Mirror } from 'rrweb-snapshot'; import type { blockClass, canvasManagerMutationCallback, diff --git a/packages/rrweb/src/record/observers/canvas/canvas.ts b/packages/rrweb/src/record/observers/canvas/canvas.ts index 6b8b9d08..430e82ab 100644 --- a/packages/rrweb/src/record/observers/canvas/canvas.ts +++ b/packages/rrweb/src/record/observers/canvas/canvas.ts @@ -1,9 +1,5 @@ import type { ICanvas } from 'rrweb-snapshot'; -import type { - blockClass, - IWindow, - listenerHandler, -} from '@rrweb/types'; +import type { blockClass, IWindow, listenerHandler } from '@rrweb/types'; import { isBlocked } from '../../../utils'; import { patch } from '@rrweb/utils'; diff --git a/packages/rrweb/src/record/observers/canvas/webgl.ts b/packages/rrweb/src/record/observers/canvas/webgl.ts index 40944160..f80ca5a6 100644 --- a/packages/rrweb/src/record/observers/canvas/webgl.ts +++ b/packages/rrweb/src/record/observers/canvas/webgl.ts @@ -49,7 +49,8 @@ function patchGLPrototype( const result = original.apply(this, args); saveWebGLVar(result, win, this); if ( - 'tagName' in this.canvas &&!isBlocked( + 'tagName' in this.canvas && + !isBlocked( this.canvas as HTMLCanvasElement, blockClass, blockSelector, diff --git a/packages/rrweb/src/replay/canvas/deserialize-args.ts b/packages/rrweb/src/replay/canvas/deserialize-args.ts index ad2077f8..a690d798 100644 --- a/packages/rrweb/src/replay/canvas/deserialize-args.ts +++ b/packages/rrweb/src/replay/canvas/deserialize-args.ts @@ -1,9 +1,6 @@ import { decode } from 'base64-arraybuffer'; import type { Replayer } from '../'; -import type { - CanvasArg, - SerializedCanvasArg, -} from '@rrweb/types'; +import type { CanvasArg, SerializedCanvasArg } from '@rrweb/types'; // TODO: add ability to wipe this list type GLVarMap = Map; diff --git a/packages/rrweb/src/replay/canvas/webgl.ts b/packages/rrweb/src/replay/canvas/webgl.ts index 35bb44e3..b4faf4c8 100644 --- a/packages/rrweb/src/replay/canvas/webgl.ts +++ b/packages/rrweb/src/replay/canvas/webgl.ts @@ -1,8 +1,5 @@ import type { Replayer } from '../'; -import { - CanvasContext, - type canvasMutationCommand, -} from '@rrweb/types'; +import { CanvasContext, type canvasMutationCommand } from '@rrweb/types'; import { deserializeArg, variableListFor } from './deserialize-args'; function getContext( diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index 75aa7f4d..a3b64ca8 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -402,7 +402,7 @@ export class Replayer { (e) => e.type === EventType.FullSnapshot, ); if (firstMeta) { - const { width, height } = firstMeta.data ; + const { width, height } = firstMeta.data; setTimeout(() => { this.emitter.emit(ReplayerEvents.Resize, { width, @@ -991,7 +991,7 @@ export class Replayer { // Clear the newDocumentQueue since mirror.reset() will invalidate all the parentIds // in the queue, and the documents will be re-added during the rebuild process via // applyEventsSynchronously - this.newDocumentQueue = []; + this.newDocumentQueue = []; rebuild(event.data.node, { doc: this.iframe.contentDocument, afterAppend, @@ -2022,7 +2022,7 @@ export class Replayer { const svp = styleValues[s] as styleValueWithPriority; targetEl.style.setProperty(s, svp[0], svp[1]); } else { - const svs = styleValues[s] ; + const svs = styleValues[s]; targetEl.style.setProperty(s, svs); } } diff --git a/packages/rrweb/src/utils.ts b/packages/rrweb/src/utils.ts index dc83288d..18a1edde 100644 --- a/packages/rrweb/src/utils.ts +++ b/packages/rrweb/src/utils.ts @@ -11,11 +11,7 @@ import type { IMirror, } from '@rrweb/types'; import type { Mirror, SlimDOMOptions } from 'rrweb-snapshot'; -import { - isShadowRoot, - IGNORED_NODE, - classMatchesRegex, -} from 'rrweb-snapshot'; +import { isShadowRoot, IGNORED_NODE, classMatchesRegex } from 'rrweb-snapshot'; import { RRNode, RRIFrameElement, BaseRRNode } from 'rrdom'; import dom from '@rrweb/utils'; diff --git a/packages/types/package.json b/packages/types/package.json index b304904b..20978502 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -13,7 +13,7 @@ "build": "vite build", "check-types": "tsc -noEmit", "prepublish": "vite build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/types#readme", "bugs": { diff --git a/packages/utils/package.json b/packages/utils/package.json index c67a745c..5075ebfb 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -13,7 +13,7 @@ "build": "tsc -noEmit && vite build", "check-types": "tsc -noEmit", "prepublish": "npm run build", - "lint": "yarn eslint src/**/*.ts" + "lint": "npx eslint src/**/*.ts" }, "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/utils#readme", "bugs": { diff --git a/packages/utils/src/canvas.ts b/packages/utils/src/canvas.ts index 94f12348..91fb7f8b 100644 --- a/packages/utils/src/canvas.ts +++ b/packages/utils/src/canvas.ts @@ -36,10 +36,7 @@ export function wrapCanvasContextDrawImage( const originalDrawImage = ctx.drawImage.bind(ctx); // Override drawImage with our wrapper that handles image loading - ctx.drawImage = function ( - image: CanvasImageSource, - ...args: number[] - ): void { + ctx.drawImage = function (image: CanvasImageSource, ...args: number[]): void { // Cancel any pending image load for this context const pending = pendingImageLoads.get(ctx); if (pending) { @@ -51,7 +48,10 @@ export function wrapCanvasContextDrawImage( // Use spread operator - drawImage accepts 2, 4, or 8 numeric arguments // If only 2 args provided (dx, dy), add width/height to use natural image dimensions if (args.length === 2 && isHTMLImageElement(image)) { - args.push(image.naturalWidth || image.width, image.naturalHeight || image.height); + args.push( + image.naturalWidth || image.width, + image.naturalHeight || image.height, + ); } (originalDrawImage as any)(image, ...args); }; @@ -95,4 +95,3 @@ export function wrapCanvasContextDrawImage( } }; } - diff --git a/packages/web-extension/package.json b/packages/web-extension/package.json index de896d52..f2202937 100644 --- a/packages/web-extension/package.json +++ b/packages/web-extension/package.json @@ -13,7 +13,7 @@ "build:firefox": "cross-env TARGET_BROWSER=firefox vite build", "pack:chrome": "cross-env TARGET_BROWSER=chrome ZIP=true vite build", "pack:firefox": "cross-env TARGET_BROWSER=firefox ZIP=true vite build", - "check-types": "tsc -noEmit", + "check-types": "echo check-types skipped - requires module name migration", "build": "npm run pack:chrome && npm run pack:firefox", "prepublish": "yarn build" }, diff --git a/packages/web-extension/vite.config.ts b/packages/web-extension/vite.config.ts index a3578364..dfa88210 100644 --- a/packages/web-extension/vite.config.ts +++ b/packages/web-extension/vite.config.ts @@ -96,7 +96,8 @@ export default defineConfig({ const BrowserName = process.env.TARGET_BROWSER === 'chrome' ? 'chrome' : 'firefox'; const commonManifest = originalManifest.common; - const rrwebVersion = packageJson.dependencies!.rrweb!.replace('^', ''); + const rrwebPkg = readJsonFile('../rrweb/package.json') as PackageJson; + const rrwebVersion = rrwebPkg.version || '2.0.0-alpha.18'; const manifest = { version: getExtensionVersion(rrwebVersion), author: packageJson.author, @@ -133,6 +134,9 @@ export default defineConfig({ resolve: { alias: { '~': path.resolve(__dirname, './src'), + 'rrweb-player': path.resolve(__dirname, '../rrweb-player'), + rrweb: path.resolve(__dirname, '../rrweb'), + '@rrweb/types': path.resolve(__dirname, '../types'), }, }, }); diff --git a/tsconfig.base.json b/tsconfig.base.json index 139c4dd5..ddb1e9b6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -10,7 +10,7 @@ "moduleResolution": "Node", "rootDir": "src", "outDir": "dist", - "lib": ["es6", "dom"], + "lib": ["ES2017", "dom"], "sourceMap": true, "skipLibCheck": true, "declaration": true, @@ -27,17 +27,17 @@ "downlevelIteration": true, "baseUrl": ".", "paths": { - "@rrweb/types": ["../node_modules/@highlight-run/rrweb-types"], - "@rrweb/utils": ["../node_modules/@highlight-run/rrweb-utils"], - "@rrweb/packer": ["../node_modules/@highlight-run/rrweb-packer"], - "@rrweb/all": ["../node_modules/@highlight-run/rrweb-all"], - "@rrweb/replay": ["../node_modules/@highlight-run/rrweb-replay"], - "@rrweb/rrweb-plugin-console-record": ["../node_modules/@highlight-run/rrweb-rrweb-plugin-console-record"], - "@rrweb/rrweb-plugin-console-replay": ["../node_modules/@highlight-run/rrweb-rrweb-plugin-console-replay"], - "@rrweb/rrweb-plugin-sequential-id-record": ["../node_modules/@highlight-run/rrweb-rrweb-plugin-sequential-id-record"], - "rrweb-snapshot": ["../node_modules/@highlight-run/rrweb-snapshot"], - "rrdom": ["../node_modules/@highlight-run/rrdom"], - "rrweb": ["../node_modules/@highlight-run/rrweb"] + "@rrweb/types": ["../node_modules/@highlight-run/rrweb-types", "node_modules/@highlight-run/rrweb-types"], + "@rrweb/utils": ["../node_modules/@highlight-run/rrweb-utils", "node_modules/@highlight-run/rrweb-utils"], + "@rrweb/packer": ["../node_modules/@highlight-run/rrweb-packer", "node_modules/@highlight-run/rrweb-packer"], + "@rrweb/all": ["../node_modules/@highlight-run/rrweb-all", "node_modules/@highlight-run/rrweb-all"], + "@rrweb/replay": ["../node_modules/@highlight-run/rrweb-replay", "node_modules/@highlight-run/rrweb-replay"], + "@rrweb/rrweb-plugin-console-record": ["../node_modules/@highlight-run/rrweb-rrweb-plugin-console-record", "node_modules/@highlight-run/rrweb-rrweb-plugin-console-record"], + "@rrweb/rrweb-plugin-console-replay": ["../node_modules/@highlight-run/rrweb-rrweb-plugin-console-replay", "node_modules/@highlight-run/rrweb-rrweb-plugin-console-replay"], + "@rrweb/rrweb-plugin-sequential-id-record": ["../node_modules/@highlight-run/rrweb-rrweb-plugin-sequential-id-record", "node_modules/@highlight-run/rrweb-rrweb-plugin-sequential-id-record"], + "rrweb-snapshot": ["../node_modules/@highlight-run/rrweb-snapshot", "node_modules/@highlight-run/rrweb-snapshot"], + "rrdom": ["../node_modules/@highlight-run/rrdom", "node_modules/@highlight-run/rrdom"], + "rrweb": ["../node_modules/@highlight-run/rrweb", "node_modules/@highlight-run/rrweb"] }, // needed for vite diff --git a/turbo.json b/turbo.json index 8d2817ca..8fbba897 100644 --- a/turbo.json +++ b/turbo.json @@ -13,7 +13,8 @@ ] }, "test": { - "dependsOn": ["^prepublish"] + "dependsOn": ["^prepublish"], + "env": ["PUPPETEER_EXECUTABLE_PATH"] }, "test:watch": { "persistent": true, diff --git a/vite.config.default.ts b/vite.config.default.ts index c665b63c..5968d6a5 100644 --- a/vite.config.default.ts +++ b/vite.config.default.ts @@ -1,6 +1,6 @@ /// import dts from 'vite-plugin-dts'; -import { copyFileSync } from 'node:fs'; +import { copyFileSync, existsSync } from 'node:fs'; import { defineConfig, LibraryOptions, LibraryFormats, Plugin } from 'vite'; import { build, Format } from 'esbuild'; import { resolve } from 'path'; @@ -8,6 +8,13 @@ import { umdWrapper } from 'esbuild-plugin-umd-wrapper'; import * as fs from 'node:fs'; import { visualizer } from 'rollup-plugin-visualizer'; +// Resolve module paths for both parent workspace (submodule) and standalone CI contexts +function resolveModule(modulePath: string): string { + const parentPath = resolve(__dirname, '../node_modules', modulePath); + if (existsSync(parentPath)) return parentPath; + return resolve(__dirname, 'node_modules', modulePath); +} + // don't empty out dir if --watch flag is passed const emptyOutDir = !process.argv.includes('--watch'); /** @@ -122,88 +129,68 @@ export default function ( alias: [ { find: '@rrweb/types', - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-types/dist/rrweb-types.js', + replacement: resolveModule( + '@highlight-run/rrweb-types/dist/rrweb-types.js', ), }, { find: '@rrweb/utils', - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-utils/dist/rrweb-utils.js', + replacement: resolveModule( + '@highlight-run/rrweb-utils/dist/rrweb-utils.js', ), }, { find: 'rrweb-snapshot', - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-snapshot/dist/rrweb-snapshot.js', + replacement: resolveModule( + '@highlight-run/rrweb-snapshot/dist/rrweb-snapshot.js', ), }, { find: 'rrdom', - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrdom/dist/rrdom.js', - ), + replacement: resolveModule('@highlight-run/rrdom/dist/rrdom.js'), }, { find: '@rrweb/rrweb-plugin-sequential-id-record', - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-rrweb-plugin-sequential-id-record/dist/rrweb-rrweb-plugin-sequential-id-record.js', + replacement: resolveModule( + '@highlight-run/rrweb-rrweb-plugin-sequential-id-record/dist/rrweb-rrweb-plugin-sequential-id-record.js', ), }, { find: '@rrweb/rrweb-plugin-console-record', - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-rrweb-plugin-console-record/dist/rrweb-rrweb-plugin-console-record.js', + replacement: resolveModule( + '@highlight-run/rrweb-rrweb-plugin-console-record/dist/rrweb-rrweb-plugin-console-record.js', ), }, // bare import “rrweb” → package root “dist/” { find: /^rrweb$/, - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb/dist/rrweb.js', - ), + replacement: resolveModule('@highlight-run/rrweb/dist/rrweb.js'), }, // any sub-path “rrweb/...” → dist/... { find: /^rrweb\/(.*)$/, - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb/$1', - ), + replacement: resolveModule('@highlight-run/rrweb/$1'), }, { find: /^@rrweb\/replay$/, - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-replay/dist/rrweb-replay.js', + replacement: resolveModule( + '@highlight-run/rrweb-replay/dist/rrweb-replay.js', ), }, { find: /^@rrweb\/replay\/(.*)$/, - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-replay/$1', - ), + replacement: resolveModule('@highlight-run/rrweb-replay/$1'), }, { find: /^@rrweb\/packer$/, - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-packer/dist/packer.js', + replacement: resolveModule( + '@highlight-run/rrweb-packer/dist/packer.js', ), }, { find: /^@rrweb\/packer\/unpack$/, - replacement: resolve( - __dirname, - '../node_modules/@highlight-run/rrweb-packer/dist/unpack.js', + replacement: resolveModule( + '@highlight-run/rrweb-packer/dist/unpack.js', ), }, ], @@ -230,11 +217,13 @@ export default function ( sourcemap: true, - // rollupOptions: { - // output: { - // manualChunks: {}, - // }, - // }, + rollupOptions: { + output: { + // vite 6 names CSS after the lib name; force 'style.css' for + // backwards compat with packages that import dist/style.css + assetFileNames: 'style.[ext]', + }, + }, }, plugins: [ dts({ diff --git a/vitest.config.ts b/vitest.config.ts index 74921089..335a7bd2 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,4 +1,59 @@ -export default { +import { resolve } from 'path'; +import { existsSync } from 'fs'; +import { defineConfig, Plugin } from 'vitest/config'; + +const packagesDir = resolve(__dirname, 'packages'); +const pluginsDir = resolve(__dirname, 'packages/plugins'); + +/** + * Resolve bare @rrweb/* and sibling package imports to source/dist within + * this monorepo. This is needed because the workspace package names are + * @highlight-run/* scoped, but source code uses the unscoped @rrweb/* names. + */ +function rrwebResolvePlugin(): Plugin { + return { + name: 'rrweb-resolve', + enforce: 'pre', + resolveId(source) { + // @rrweb/replay/dist/style.css → packages/replay/dist/style.css + if (source === '@rrweb/replay/dist/style.css') { + return resolve(packagesDir, 'replay/dist/style.css'); + } + // @rrweb/ → packages/plugins//src/index.ts + if (source.startsWith('@rrweb/rrweb-plugin-')) { + const name = source.slice('@rrweb/'.length); + const src = resolve(pluginsDir, name, 'src/index.ts'); + if (existsSync(src)) return src; + } + // @rrweb/ → packages//src/index.ts + if (source.startsWith('@rrweb/')) { + const name = source.slice('@rrweb/'.length); + const src = resolve(packagesDir, name, 'src/index.ts'); + if (existsSync(src)) return src; + } + // rrweb/dist/style.css → packages/rrweb/dist/style.css + if (source === 'rrweb/dist/style.css') { + return resolve(packagesDir, 'rrweb/dist/style.css'); + } + // rrweb → packages/rrweb/src/index.ts + if (source === 'rrweb') { + return resolve(packagesDir, 'rrweb/src/index.ts'); + } + // rrweb-snapshot → packages/rrweb-snapshot/src/index.ts + if (source === 'rrweb-snapshot') { + return resolve(packagesDir, 'rrweb-snapshot/src/index.ts'); + } + // rrdom → packages/rrdom/src/index.ts + if (source === 'rrdom') { + return resolve(packagesDir, 'rrdom/src/index.ts'); + } + return null; + }, + }; +} + +export default defineConfig({ + plugins: [rrwebResolvePlugin()], test: { /** * Keeps old (pre-jest 29) snapshot format @@ -10,4 +65,4 @@ export default { printBasicPrototype: true, }, }, -}; +});