fix: flush pending changesets immediately after reconnect#2
fix: flush pending changesets immediately after reconnect#2deepshekhardas wants to merge 130 commits into
Conversation
Bumps [jsdom](https://github.com/jsdom/jsdom) from 28.0.0 to 28.1.0. - [Release notes](https://github.com/jsdom/jsdom/releases) - [Changelog](https://github.com/jsdom/jsdom/blob/main/Changelog.md) - [Commits](jsdom/jsdom@28.0.0...28.1.0) --- updated-dependencies: - dependency-name: jsdom dependency-version: 28.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [underscore](https://github.com/jashkenas/underscore) from 1.13.7 to 1.13.8. - [Commits](https://github.com/jashkenas/underscore/commits) --- updated-dependencies: - dependency-name: underscore dependency-version: 1.13.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [oidc-provider](https://github.com/panva/node-oidc-provider) from 9.6.0 to 9.6.1. - [Release notes](https://github.com/panva/node-oidc-provider/releases) - [Changelog](https://github.com/panva/node-oidc-provider/blob/main/CHANGELOG.md) - [Commits](panva/node-oidc-provider@v9.6.0...v9.6.1) --- updated-dependencies: - dependency-name: oidc-provider dependency-version: 9.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
basically copy/pasting contributing.md but gives qodo a reference point, I'd of used a sym link but I don't know how well that would have worked so for now lets just add some cruft and see what happens..
* docs: add AGENTS.MD for AI and developer guidance * docs: update project name from Etherpad Lite to Etherpad * docs: fix incorrect test directory path in AGENTS.MD * docs: correct test stack description in AGENTS.MD (Mocha is primary) * docs: fix incorrect easysync documentation path in AGENTS.MD * chore: add .pr_agent.toml to enable automatic PR review/description on push * docs: remove nodejs version from README and AGENTS.MD (prefer package.json) * docs: standardize all indentation to 2 spaces * chore: update src/package.json node engine to match root (>=20.0.0)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](docker/login-action@v3...v4) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](docker/build-push-action@v6...v7) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](docker/metadata-action@v5...v6) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](docker/setup-buildx-action@v3...v4) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit) from 8.2.1 to 8.2.2. - [Release notes](https://github.com/express-rate-limit/express-rate-limit/releases) - [Commits](express-rate-limit/express-rate-limit@v8.2.1...v8.2.2) --- updated-dependencies: - dependency-name: express-rate-limit dependency-version: 8.2.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@v3...v4) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…er#7358) Bumps the dev-dependencies group with 16 updates: | Package | From | To | | --- | --- | --- | | [@types/formidable](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/formidable) | `3.4.6` | `3.5.0` | | [@types/jquery](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jquery) | `3.5.33` | `4.0.0` | | [@types/jsdom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsdom) | `27.0.0` | `28.0.0` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.2.3` | `25.3.5` | | [@types/supertest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/supertest) | `6.0.3` | `7.2.0` | | [@types/whatwg-mimetype](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/whatwg-mimetype) | `3.0.2` | `5.0.0` | | [eslint](https://github.com/eslint/eslint) | `10.0.0` | `10.0.3` | | [sinon](https://github.com/sinonjs/sinon) | `21.0.1` | `21.0.2` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.55.0` | `8.56.1` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.55.0` | `8.56.1` | | [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh) | `0.5.0` | `0.5.2` | | [i18next](https://github.com/i18next/i18next) | `25.8.8` | `25.8.16` | | [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `0.564.0` | `0.577.0` | | [react-hook-form](https://github.com/react-hook-form/react-hook-form) | `7.71.1` | `7.71.2` | | [react-i18next](https://github.com/i18next/react-i18next) | `16.5.4` | `16.5.6` | | [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) | `7.13.0` | `7.13.1` | Updates `@types/formidable` from 3.4.6 to 3.5.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/formidable) Updates `@types/jquery` from 3.5.33 to 4.0.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jquery) Updates `@types/jsdom` from 27.0.0 to 28.0.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsdom) Updates `@types/node` from 25.2.3 to 25.3.5 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `@types/supertest` from 6.0.3 to 7.2.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/supertest) Updates `@types/whatwg-mimetype` from 3.0.2 to 5.0.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/whatwg-mimetype) Updates `eslint` from 10.0.0 to 10.0.3 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](eslint/eslint@v10.0.0...v10.0.3) Updates `sinon` from 21.0.1 to 21.0.2 - [Release notes](https://github.com/sinonjs/sinon/releases) - [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md) - [Commits](sinonjs/sinon@v21.0.1...v21.0.2) Updates `@typescript-eslint/eslint-plugin` from 8.55.0 to 8.56.1 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.56.1/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.55.0 to 8.56.1 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.56.1/packages/parser) Updates `eslint-plugin-react-refresh` from 0.5.0 to 0.5.2 - [Release notes](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/releases) - [Changelog](https://github.com/ArnaudBarre/eslint-plugin-react-refresh/blob/main/CHANGELOG.md) - [Commits](ArnaudBarre/eslint-plugin-react-refresh@v0.5.0...v0.5.2) Updates `i18next` from 25.8.8 to 25.8.16 - [Release notes](https://github.com/i18next/i18next/releases) - [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md) - [Commits](i18next/i18next@v25.8.8...v25.8.16) Updates `lucide-react` from 0.564.0 to 0.577.0 - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/0.577.0/packages/lucide-react) Updates `react-hook-form` from 7.71.1 to 7.71.2 - [Release notes](https://github.com/react-hook-form/react-hook-form/releases) - [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md) - [Commits](react-hook-form/react-hook-form@v7.71.1...v7.71.2) Updates `react-i18next` from 16.5.4 to 16.5.6 - [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md) - [Commits](i18next/react-i18next@v16.5.4...v16.5.6) Updates `react-router-dom` from 7.13.0 to 7.13.1 - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.13.1/packages/react-router-dom) --- updated-dependencies: - dependency-name: "@types/formidable" dependency-version: 3.5.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@types/jquery" dependency-version: 4.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: "@types/jsdom" dependency-version: 28.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: "@types/node" dependency-version: 25.3.5 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@types/supertest" dependency-version: 7.2.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: "@types/whatwg-mimetype" dependency-version: 5.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: eslint dependency-version: 10.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: sinon dependency-version: 21.0.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.56.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@typescript-eslint/parser" dependency-version: 8.56.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: eslint-plugin-react-refresh dependency-version: 0.5.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: i18next dependency-version: 25.8.16 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: lucide-react dependency-version: 0.577.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: react-hook-form dependency-version: 7.71.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: react-i18next dependency-version: 16.5.6 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: react-router-dom dependency-version: 7.13.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [openapi-backend](https://github.com/openapistack/openapi-backend) from 5.15.0 to 5.16.1. - [Release notes](https://github.com/openapistack/openapi-backend/releases) - [Commits](openapistack/openapi-backend@5.15.0...5.16.1) --- updated-dependencies: - dependency-name: openapi-backend dependency-version: 5.16.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [jose](https://github.com/panva/jose) from 6.1.3 to 6.2.1. - [Release notes](https://github.com/panva/jose/releases) - [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md) - [Commits](panva/jose@v6.1.3...v6.2.1) --- updated-dependencies: - dependency-name: jose dependency-version: 6.2.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [ejs](https://github.com/mde/ejs) from 4.0.1 to 5.0.1. - [Release notes](https://github.com/mde/ejs/releases) - [Changelog](https://github.com/mde/ejs/blob/main/RELEASE_NOTES_v4.md) - [Commits](mde/ejs@v4.0.1...v5.0.1) --- updated-dependencies: - dependency-name: ejs dependency-version: 5.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [oidc-provider](https://github.com/panva/node-oidc-provider) from 9.6.1 to 9.7.0. - [Release notes](https://github.com/panva/node-oidc-provider/releases) - [Changelog](https://github.com/panva/node-oidc-provider/blob/main/CHANGELOG.md) - [Commits](panva/node-oidc-provider@v9.6.1...v9.7.0) --- updated-dependencies: - dependency-name: oidc-provider dependency-version: 9.7.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [axios](https://github.com/axios/axios) from 1.13.5 to 1.13.6. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.13.5...v1.13.6) --- updated-dependencies: - dependency-name: axios dependency-version: 1.13.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…r#7366) Bumps the dev-dependencies group with 7 updates: | Package | From | To | | --- | --- | --- | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.3.5` | `25.4.0` | | [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `4.0.18` | `4.1.0` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.56.1` | `8.57.0` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.56.1` | `8.57.0` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `5.1.4` | `6.0.0` | | [i18next](https://github.com/i18next/i18next) | `25.8.16` | `25.8.18` | | [react-i18next](https://github.com/i18next/react-i18next) | `16.5.6` | `16.5.8` | Updates `@types/node` from 25.3.5 to 25.4.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `vitest` from 4.0.18 to 4.1.0 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/vitest) Updates `@typescript-eslint/eslint-plugin` from 8.56.1 to 8.57.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.0/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.56.1 to 8.57.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.0/packages/parser) Updates `@vitejs/plugin-react` from 5.1.4 to 6.0.0 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.0/packages/plugin-react) Updates `i18next` from 25.8.16 to 25.8.18 - [Release notes](https://github.com/i18next/i18next/releases) - [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md) - [Commits](i18next/i18next@v25.8.16...v25.8.18) Updates `react-i18next` from 16.5.6 to 16.5.8 - [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md) - [Commits](i18next/react-i18next@v16.5.6...v16.5.8) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 25.4.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: vitest dependency-version: 4.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.57.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@typescript-eslint/parser" dependency-version: 8.57.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: dev-dependencies - dependency-name: i18next dependency-version: 25.8.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: react-i18next dependency-version: 16.5.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](actions/upload-artifact@v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.27.3 to 0.27.4. - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) - [Commits](evanw/esbuild@v0.27.3...v0.27.4) --- updated-dependencies: - dependency-name: esbuild dependency-version: 0.27.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit) from 8.2.2 to 8.3.1. - [Release notes](https://github.com/express-rate-limit/express-rate-limit/releases) - [Commits](express-rate-limit/express-rate-limit@v8.2.2...v8.3.1) --- updated-dependencies: - dependency-name: express-rate-limit dependency-version: 8.3.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…r#7368) Bumps the dev-dependencies group with 3 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) and [vite-plugin-static-copy](https://github.com/sapphi-red/vite-plugin-static-copy). Updates `@types/node` from 25.4.0 to 25.5.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `@vitejs/plugin-react` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.1/packages/plugin-react) Updates `vite-plugin-static-copy` from 3.2.0 to 3.3.0 - [Release notes](https://github.com/sapphi-red/vite-plugin-static-copy/releases) - [Changelog](https://github.com/sapphi-red/vite-plugin-static-copy/blob/main/CHANGELOG.md) - [Commits](https://github.com/sapphi-red/vite-plugin-static-copy/compare/vite-plugin-static-copy@3.2.0...vite-plugin-static-copy@3.3.0) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 25.5.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: vite-plugin-static-copy dependency-version: 3.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
) PRs now run a minimal test matrix; full matrix runs on push to develop. Changes: - Backend tests: PRs test on Node 24 only (Linux). Windows tests only run on push to develop. Reduces from 12 to 2 jobs for PRs. - Upgrade-from-latest-release: PRs test on Node 24 only (1 job vs 3). - Frontend admin tests: PRs test on Node 24 only (1 job vs 3). This reduces PR CI from ~25 jobs to ~10, preventing runner exhaustion when multiple PRs are merged in succession. The full matrix (3 Node versions × Linux + Windows) still runs on every push to develop. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…her#7448) * fix: add periodic cleanup of expired/stale sessions from database SessionStore now runs a periodic cleanup (every hour, plus once on startup) that removes: - Sessions with expired cookies (expires date in the past) - Sessions with no expiry that contain no data beyond the default cookie (the empty sessions that accumulate indefinitely per ether#5010) Without this, sessions accumulated forever in the database because: 1. Sessions with no maxAge never got an expiry date 2. On server restart, in-memory expiration timeouts were lost 3. There was no mechanism to clean up sessions that were never accessed again Fixes ether#5010 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve TypeScript error for sessionStore.startCleanup() Use a local variable for the SessionStore instance to avoid type narrowing issues with the module-level Store|null variable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Qodo review — chained timeouts, cleanup tests, docs - Replace setInterval with chained setTimeout to prevent overlapping cleanup runs on large databases - Store and clear startup timeout in shutdown() to prevent leaks - Add .unref() on all timers so they don't delay process exit - Fix misleading docstring — cleanup removes empty no-expiry sessions, not sessions older than STALE_SESSION_MAX_AGE_MS (removed unused const) - Add 5 regression tests: expired sessions removed, empty sessions removed, sessions with data preserved, valid sessions preserved, shutdown cancels timer Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add cookie.sessionCleanup setting to control session cleanup Session cleanup is now gated behind cookie.sessionCleanup (default true). Admins who want to keep stale sessions can set this to false in settings.json. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the cleanup timeout fires, check the in-memory exp.real before reading from the DB. If touch() extended the expiry (but the old timeout fires late, e.g. on slow CI), reschedule instead of reading potentially stale cached data from the DB and destroying the session. Also increased test expiry times so the "touch after eligible for refresh" test isn't sensitive to event loop delays on slow machines. Fixes flaky SessionStore test from ether#7448. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: handle git submodule in Docker build When etherpad-lite is checked out as a submodule, .git is a file (gitlink) instead of a directory, so COPY .git/HEAD fails. The previous glob-based workaround (HEA[D], ref[s]) does not work with buildah (podman-container-tools/buildah#5742). Copy the whole .git entry instead and remove it in a RUN step when it is a submodule gitlink file. The .dockerignore already strips heavy objects so the image size is unaffected for normal checkouts. Fixes ether#6663 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: document BUILD_ENV=copy bypass for builds without .git Adds a comment explaining how to build from source tarballs or other contexts where .git metadata is unavailable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use pnpm instead of npm in updatePlugins.sh The script used npm outdated which doesn't work with pnpm workspaces, and pnpm install which doesn't update existing packages. Changed to pnpm outdated and pnpm update respectively. Fixes ether#6670 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: scope plugin updates to ep_etherpad-lite and exclude core package - Use --filter ep_etherpad-lite so pnpm operates on the right workspace - Exclude ep_etherpad-lite from the plugin list - Handle pnpm outdated exit codes correctly (returns 1 when outdated) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lation (ether#7467) * fix: correct readFileSync calls in LinkInstaller to fix plugin installation pathToFileURL() was incorrectly wrapping paths passed to readFileSync(), causing ENOENT errors that were silently caught. Using plain paths with 'utf-8' encoding fixes plugin dependency resolution. Fixes ether#6811 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add backend tests for LinkInstaller dependency resolution Covers the readFileSync fix from the plugin installation bug where pathToFileURL incorrectly wrapped file paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: only track dependency in map after successful setup Previously dependenciesMap.set() ran after the catch block, marking dependencies as tracked even when linking or package.json reading failed. This blocked later cleanup via removeSubDependency(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…er#7464) * fix: RTL URL parameter rtl=false now correctly disables RTL mode The rtl parameter callback only handled rtl=true (checkVal was 'true'), so rtl=false was ignored and the layout stayed in RTL from the cookie. Now accepts any value and sets rtlIsTrue = (val === 'true'). Also always applies the RTL setting instead of only when true, so switching from rtl=true to rtl=false takes effect. Fixes ether#5559 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: only override RTL when explicitly set via URL/server config The unconditional changeViewOption('rtlIsTrue', false) overwrote cookie-persisted RTL preferences and language-direction defaults. Track explicit setting with rtlIsExplicit flag so we only override when the user or server actually specified an rtl value. Adds regression tests for rtl=true, rtl=false, and cookie persistence. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: move RTL override into postAceInit to fix race condition The RTL changeViewOption call was racing with padeditor.init() — the async setViewOptions(initialViewOptions) at the end of init overwrote the URL-param-based RTL setting. Moving it into postAceInit ensures padeditor is fully initialized. Also switched tests to use Playwright auto-retrying assertions for robustness. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve Playwright test failures for RTL URL parameter Three issues fixed: - setCheckbox used .attr('checked') instead of .prop('checked'), so the JS checked property was never set and Playwright saw unchecked state - html10n localized event overwrote RTL setting from URL params and cookie preferences; now skips override when either is active - Server default padOptions.rtl:false was treated as explicit, overwriting cookie-persisted RTL; added fromUrl flag to distinguish URL from server All 94 Playwright tests and 740 backend tests pass locally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…xport (ether#7470) * fix: preserve ordered list numbering across unordered list interruptions in export When ordered lists were interrupted by unordered lists, each new <ol> segment started at 1 instead of continuing the previous numbering. Track running counts per indent level and emit start attributes. Fixes ether#6471 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: respect explicit start attributes and reset counters per level - line.start takes priority over counter-based continuation when present - Counter is seeded from line.start to keep subsequent continuations aligned - Counters for closed indent levels are cleared when list depth decreases Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: sort language dropdown alphabetically by native name Languages in the settings dropdown were ordered by language code, making it hard to find specific languages. Now sorted alphabetically by their native display name. Fixes ether#3263 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: verify language dropdown is sorted by native name Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: numbered list wrapped lines now indent correctly Changed text-indent to padding-left for ordered list indentation. text-indent only affects the first line, so wrapped text didn't align with the numbered content above it. Fixes ether#2581 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: verify numbered list uses padding-left instead of text-indent Regression test for ether#2581. Verifies that ordered list items use padding-left (which indents all lines including wrapped ones) rather than text-indent (which only indents the first line). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use correct path for connection diagnostics POST The relative path '../ep/pad/connection-diagnostic-info' resolved incorrectly in subdirectory setups. Use absolute path from the application root. Fixes ether#4191 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: verify connection diagnostics endpoint is reachable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ether#7473) * fix: very old .etherpad imports could break import due to lack of author metadata, allow this now * test: add regression tests for old .etherpad import without author Tests that importing an old .etherpad export (circa 2014) where revision records lack meta.author succeeds without error, and that getRevisionAuthor returns '' for such revisions. Covers the fix for ether#6785. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: prevent race condition in session cleanup timeout When the cleanup timeout fires, check the in-memory exp.real before reading from the DB. If touch() extended the expiry (but the old timeout fires late, e.g. on slow CI), reschedule instead of reading potentially stale cached data from the DB and destroying the session. Also increased test expiry times so the "touch after eligible for refresh" test isn't sensitive to event loop delays on slow machines. Fixes flaky SessionStore test from ether#7448. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: dev mode entrypoint paths respect x-proxy-path header In dev mode, the /watch/* script paths were hard-coded as absolute paths without considering the x-proxy-path header used for subdirectory reverse proxy setups. This caused 404s for the script tags when hosting Etherpad on a subdirectory URL (e.g., /pad). Now reads the x-proxy-path header from the request and prefixes the entrypoint path, matching how admin.ts handles proxy paths. Fixes ether#7137 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: make proxy path tests deterministic in production mode Tests now verify entrypoint paths and x-proxy-path header handling in production mode (where tests run) rather than conditionally asserting only in dev mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * security: sanitize x-proxy-path header to prevent XSS The header value was injected directly into <script src="..."> without sanitization. An attacker who can set request headers could inject arbitrary HTML/JS. Now only allows path-safe characters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…her#7474) * fix: increase max socket.io message size to 10MB for large pastes The default maxHttpBufferSize of 50KB caused socket.io to drop connections when pasting >10,000 characters. Increased to 10MB which safely accommodates large paste operations. Fixes ether#4951 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: reduce default maxHttpBufferSize to 1MB 10MB was too generous and creates a DoS vector. 1MB (socket.io's own default) is sufficient for large pastes while limiting memory abuse. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The CJS compatibility block added in fd97532 only defined getters, making settings properties read-only for plugins using require(). Plugins like ep_webrtc need to mutate settings (e.g. requireAuthentication) in tests. Add setters so CJS consumers can write properties too. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…7484) Bumps [rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) from 10.0.1 to 11.0.0. - [Release notes](https://github.com/animir/node-rate-limiter-flexible/releases) - [Commits](animir/node-rate-limiter-flexible@v10.0.1...v11.0.0) --- updated-dependencies: - dependency-name: rate-limiter-flexible dependency-version: 11.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [lru-cache](https://github.com/isaacs/node-lru-cache) from 11.2.7 to 11.3.0. - [Changelog](https://github.com/isaacs/node-lru-cache/blob/main/CHANGELOG.md) - [Commits](isaacs/node-lru-cache@v11.2.7...v11.3.0) --- updated-dependencies: - dependency-name: lru-cache dependency-version: 11.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…r#7482) Bumps the dev-dependencies group with 2 updates: [eslint](https://github.com/eslint/eslint) and [vite-plugin-static-copy](https://github.com/sapphi-red/vite-plugin-static-copy). Updates `eslint` from 10.1.0 to 10.2.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](eslint/eslint@v10.1.0...v10.2.0) Updates `vite-plugin-static-copy` from 4.0.0 to 4.0.1 - [Release notes](https://github.com/sapphi-red/vite-plugin-static-copy/releases) - [Changelog](https://github.com/sapphi-red/vite-plugin-static-copy/blob/main/CHANGELOG.md) - [Commits](https://github.com/sapphi-red/vite-plugin-static-copy/compare/vite-plugin-static-copy@4.0.0...vite-plugin-static-copy@4.0.1) --- updated-dependencies: - dependency-name: eslint dependency-version: 10.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: vite-plugin-static-copy dependency-version: 4.0.1 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
After reconnecting, setUpSocket() did not call handleUserChanges(), so any edits made while disconnected were not sent to the server until the user made another change. This caused divergent pad state between users. Now calls handleUserChanges() after reconnect to immediately transmit any pending local changesets. Fixes ether#5108 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Calling handleUserChanges() synchronously in setUpSocket() caused "Cannot read properties of null (reading 'changeset')" because the editor isn't fully initialized on first connect. Deferred with setTimeout(500ms) to allow initialization to complete. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verifies that edits made while disconnected are transmitted to the server immediately upon reconnection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onnect setUpSocket() only runs during initialization. Move handleUserChanges() to the reconnect code path so pending edits are flushed when the connection is re-established. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The existing fix in setChannelState('CONNECTED') calls handleUserChanges(),
but at that point isPendingRevision is still true so changes are blocked.
The real trigger must be in setIsPendingRevision(): when it transitions
from true to false (after all CLIENT_RECONNECT messages are processed),
call handleUserChanges() to flush any locally-queued edits.
Also adds a targeted regression test that simulates the exact reconnect
state transitions and verifies pending edits reach the server.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced the fragile offline/online simulation with a direct test that uses separate browser contexts. Simplified to a single test that exercises the exact setIsPendingRevision(false) -> handleUserChanges() codepath and verifies the flushed text is visible from another client. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The reconnect test requires access to pad.collabClient internals which are not exposed on window in the browser context. Playwright cannot call setStateIdle/setIsPendingRevision/setChannelState. The backend tests adequately cover the code fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Calling handleUserChanges() in setChannelState('CONNECTED') fires
synchronously on first connect before the editor is fully initialized,
breaking chat/user_name tests. The setIsPendingRevision(false) trigger
is sufficient for the reconnect path, and the existing
setTimeout(handleUserChanges, 500) in setUpSocket() already handles
the initial connect.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ision trigger
The setTimeout(handleUserChanges, 500) in setUpSocket was a timing hack
that:
- Only fires on initial connect (setUpSocket is called once at the end
of getCollabClient; reconnects go through pad.ts:248 which calls
setChannelState('CONNECTED') directly, bypassing setUpSocket).
- Doesn't actually fix issue ether#5108 (the reconnect-flush bug). That's
fixed deterministically by the wasPending && !value trigger in
setIsPendingRevision, which fires whenever the server's CLIENT_RECONNECT
message lands (both for noChanges and after replaying revisions).
- Introduced a 500ms race window on initial pad load.
The reconnect path now relies entirely on the deterministic event-based
trigger (setIsPendingRevision), with no timing assumptions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
5 issues found across 174 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/node/hooks/express/specialpages.ts">
<violation number="1" location="src/node/hooks/express/specialpages.ts:24">
P1: `x-proxy-path` sanitization still allows protocol-relative URLs (for example `//host`), enabling external script loading via `entrypoint`.</violation>
</file>
<file name="admin/src/localization/i18n.ts">
<violation number="1" location="admin/src/localization/i18n.ts:29">
P1: Return after invoking the error callback to avoid calling the backend callback twice on JSON parse failures.</violation>
</file>
<file name="README.md">
<violation number="1" location="README.md:103">
P2: The README now omits the minimum supported Node.js version, which conflicts with the project requirement (`node >=20.0.0`) and can cause users to run unsupported environments.</violation>
</file>
<file name="admin/src/components/IconButton.tsx">
<violation number="1" location="admin/src/components/IconButton.tsx:13">
P3: Avoid concatenating an optional `className` directly; when omitted it renders `"undefined"` as a CSS class.</violation>
</file>
<file name="admin/package.json">
<violation number="1" location="admin/package.json:23">
P1: `@vitejs/plugin-react` 6.x requires Vite 8, but this package is still pinned to Vite 7.2.10, creating an incompatible dependency set.</violation>
</file>
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
| // Only allow path-like characters (letters, digits, hyphens, underscores, slashes, dots). | ||
| const sanitizeProxyPath = (req: any): string => { | ||
| const raw = req.header('x-proxy-path') || ''; | ||
| return raw.replace(/[^a-zA-Z0-9\-_\/\.]/g, ''); |
There was a problem hiding this comment.
P1: x-proxy-path sanitization still allows protocol-relative URLs (for example //host), enabling external script loading via entrypoint.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/node/hooks/express/specialpages.ts, line 24:
<comment>`x-proxy-path` sanitization still allows protocol-relative URLs (for example `//host`), enabling external script loading via `entrypoint`.</comment>
<file context>
@@ -17,6 +17,13 @@ import prometheus from "../../prometheus";
+// Only allow path-like characters (letters, digits, hyphens, underscores, slashes, dots).
+const sanitizeProxyPath = (req: any): string => {
+ const raw = req.header('x-proxy-path') || '';
+ return raw.replace(/[^a-zA-Z0-9\-_\/\.]/g, '');
+};
+
</file context>
| return raw.replace(/[^a-zA-Z0-9\-_\/\.]/g, ''); | |
| return raw.replace(/[^a-zA-Z0-9\-_\/\.]/g, '').replace(/\/{2,}/g, '/').replace(/\.\./g, '').replace(/^\/?/, '/').replace(/\/$/, ''); |
| try { | ||
| json = JSON.parse(await localeJSON.text()) | ||
| } catch(e) { | ||
| callback(new Error("Error loading"), null); |
There was a problem hiding this comment.
P1: Return after invoking the error callback to avoid calling the backend callback twice on JSON parse failures.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At admin/src/localization/i18n.ts, line 29:
<comment>Return after invoking the error callback to avoid calling the backend callback twice on JSON parse failures.</comment>
<file context>
@@ -6,52 +6,50 @@ import LanguageDetector from 'i18next-browser-languagedetector'
+ try {
+ json = JSON.parse(await localeJSON.text())
+ } catch(e) {
+ callback(new Error("Error loading"), null);
+ }
+
</file context>
| callback(new Error("Error loading"), null); | |
| return callback(new Error("Error loading"), null); |
| "@vitejs/plugin-react": "^5.1.4", | ||
| "@typescript-eslint/eslint-plugin": "^8.58.0", | ||
| "@typescript-eslint/parser": "^8.58.0", | ||
| "@vitejs/plugin-react": "^6.0.1", |
There was a problem hiding this comment.
P1: @vitejs/plugin-react 6.x requires Vite 8, but this package is still pinned to Vite 7.2.10, creating an incompatible dependency set.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At admin/package.json, line 23:
<comment>`@vitejs/plugin-react` 6.x requires Vite 8, but this package is still pinned to Vite 7.2.10, creating an incompatible dependency set.</comment>
<file context>
@@ -18,27 +18,27 @@
- "@vitejs/plugin-react": "^5.1.4",
+ "@typescript-eslint/eslint-plugin": "^8.58.0",
+ "@typescript-eslint/parser": "^8.58.0",
+ "@vitejs/plugin-react": "^6.0.1",
"babel-plugin-react-compiler": "19.1.0-rc.3",
- "eslint": "^10.0.0",
</file context>
| "@vitejs/plugin-react": "^6.0.1", | |
| "@vitejs/plugin-react": "^5.1.4", |
| ### Requirements | ||
|
|
||
| [Node.js](https://nodejs.org/) >= **18.18.2**. | ||
| [Node.js](https://nodejs.org/). |
There was a problem hiding this comment.
P2: The README now omits the minimum supported Node.js version, which conflicts with the project requirement (node >=20.0.0) and can cause users to run unsupported environments.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 103:
<comment>The README now omits the minimum supported Node.js version, which conflicts with the project requirement (`node >=20.0.0`) and can cause users to run unsupported environments.</comment>
<file context>
@@ -100,7 +100,7 @@ volumes:
### Requirements
-[Node.js](https://nodejs.org/) >= **18.18.2**.
+[Node.js](https://nodejs.org/).
### Windows, macOS, Linux
</file context>
| [Node.js](https://nodejs.org/). | |
| [Node.js](https://nodejs.org/) >= **20.0.0**. |
| {icon} | ||
| <span>{title}</span> | ||
| </button> | ||
| return <button style={style} onClick={onClick} className={"icon-button "+ className} disabled={disabled}> |
There was a problem hiding this comment.
P3: Avoid concatenating an optional className directly; when omitted it renders "undefined" as a CSS class.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At admin/src/components/IconButton.tsx, line 13:
<comment>Avoid concatenating an optional `className` directly; when omitted it renders `"undefined"` as a CSS class.</comment>
<file context>
@@ -1,17 +1,17 @@
- {icon}
- <span>{title}</span>
- </button>
+ return <button style={style} onClick={onClick} className={"icon-button "+ className} disabled={disabled}>
+ {icon}
+ <span>{title}</span>
</file context>
…d-test ELIFECYCLE (ether#7838) * test(ci): heartbeat + running-test pointer in backend test diagnostics Backend tests silently die with code 255 mid-suite ~22% of the time on develop (most often Windows-with-plugins, Node 24). Each kill lands 300±50 ms after the previous test's clean ✔ teardown line and produces no failing-test marker, no error, no Mocha summary, and — despite the unconditional handlers in `diagnostics.ts` — none of the JS-level death events fire either. Recent example: run 26311025244 (`Windows with Plugins (24)`); both attempts crashed at completely different "last test" locations, so the dying test itself isn't to blame. The existing diagnostics only set lastSeenTest in afterEach, so if the kill lands during the NEXT test's setup or body — which is exactly the ~300ms gap we observe — the pointer reads as the previous (passing) test. That hides whether we're between tests or inside one, and which one. Two changes: 1. Track currentTest in beforeEach as well as lastFinishedTest in afterEach. Every diag line now carries both, so the death point is bracketable regardless of which lifecycle phase the kill interrupts. 2. Add a 1Hz heartbeat that writeSyncs the running-test name plus `process.memoryUsage()` (rss, heap) and the active-handle and active-request counts. The interval is unref'd so it never holds the event loop open by itself. Cost is roughly one extra log line per second of mocha runtime (~60-120 lines per CI run). When the next failure fires, the last heartbeat narrows the kill window to ≤1s, the running pointer names the test on the rails at that moment, and the handle/memory trace gives a sparkline that exposes sudden spikes — a leaked socket, an unref'd timer, a runaway map — that would otherwise be invisible at the runner-log level. No behavior change on successful runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: heartbeat _getActiveHandles optional chain bug (Qodo #2) Qodo correctly flagged `_getActiveHandles?.().length` as a latent TypeError: `?.()` guards the call but the call's `undefined` return on a missing method still hits `.length`, which throws. Since the heartbeat fires on a setInterval inside the mocha bootstrap, a Node build without the underscore-prefixed internals would take down the whole backend test run. Capture the array first, then read `.length` only when it actually exists. -1 stays as the "API missing" sentinel. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(ci): per-test start diag + drop stray console.log noise Follow-up to the heartbeat PR after run 26397693748 confirmed the diagnostic works (the kill landed at importexportGetPost.ts 'Import authorization checks > authn anonymous !exist -> fail', ~300 ms after the previous test's ✔). Two cleanups so the next failure pinpoints faster and reads cleaner: 1. diagnostics.ts: emit a `test start: <name>` diag line in the mocha beforeEach hook, after setting the currentTest pointer. The 1Hz heartbeat misses tests that take less than a second, and the silent kills land ~300 ms after a test boundary — precisely the gap where heartbeat resolution fails. A start line per test gives sub-millisecond resolution on which test was on the rails when the process died. 2. specs/api/importexportGetPost.ts: drop a stray `console.log(importedPads)` debug leftover (and the duplicate `await importEtherpad(records)` only present to feed it) in the `malformed .etherpad files are rejected` block. The leftover dumped a ~600-line reflection of a supertest Response object to the CI log on every successful run, drowning the surrounding test output and making the silent-kill window much harder to read. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(ci): write node-report on every heartbeat tick Run 26398054688 narrowed the kill to a specific test (pad.ts > Gets text on a pad Id and doesn't have an excess newline) but the test body is a trivial supertest GET — the kill bypasses all JS handlers, so we can't capture stack state at death. Two failures across two runs share the shape: an agent.{get,post} + common.generateJWTToken() call dies ~300-600 ms after test start, with no JS-visible cause. The next step is V8 + native stack. Hook into the existing 1Hz heartbeat to call process.report.writeReport(path) whenever a report directory is set. The Windows backend-tests workflow already wires up `--report-directory=${{ github.workspace }}/node-report` via NODE_OPTIONS and uploads that directory as an artifact on failure, so the rolling snapshots ride for free on the existing upload step. Each report (~50 KB) contains: - V8 + native call stacks for all threads - libuv active handles (open TCP, timers, file handles) - JS heap statistics - resourceUsage + system info - shared-object list On the next reproduction the latest report before ELIFECYCLE will sit ~0-1 s before the kill — enough to see whether the V8 stack is inside jose's WebCrypto sign path, inside supertest's TCP roundtrip, or somewhere unexpected entirely. NODE_REPORT_DIR is also honored as an explicit override for local repro / non-workflow runs. Cost: ~6 files (~300 KB) per Windows backend-test failure, plus ~50 ms event-loop pause per heartbeat. No-op when neither env var is set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: writeReport with bare filename, not mixed-slash absolute path Run 26398830249 exposed the path-separator bug in the previous commit: every heartbeat tick on the Windows runner logged Failed to open Node.js report file: D:\a\etherpad\etherpad/node-report/hb-NNNN-...json directory: D:\a\etherpad\etherpad/node-report (errno: 22) — EINVAL. The workflow sets --report-directory with forward-slash separators on Windows, then this code concatenated another `/` plus the filename, producing a path Node's report writer rejects. writeReport(fileName) takes a BARE filename and resolves it against the configured report directory using the platform-correct separator internally. Switch to that. For local repro overrides via NODE_REPORT_DIR, push the path into process.report.directory (the documented config knob) instead of joining it into the call site. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(ci): write node-report on test boundaries, throttled to 4Hz Run 26398985832 proved the heartbeat-only report cadence isn't tight enough: the last report before the kill was hb-0013 at +16201ms, ~1.5 s before ELIFECYCLE at +17701ms — during which ~30 tests fired, including the dying one (`authn anonymous !exist -> fail`). The captured V8 stack is just our heartbeat code, not the dying test. Move the writeReport call to a shared tryWriteReport() helper and invoke it from BOTH the heartbeat AND mocha's beforeEach hook, throttled to one report per 250 ms. That gives ≤250 ms resolution on the kill window — close enough that the latest report captures state from inside the dying test rather than from the test ~30 slots earlier. The heartbeat always writes (so we don't lose the no-test-running ticks during setup); beforeEach only writes when the throttle window has elapsed. Cost ceiling: ~4 reports/sec × ~12 s test phase ≈ 48 reports (~2.5 MB) per failing run. Each writeReport adds ~50 ms of event-loop pause — at 4Hz that's 20% of wall time spent in diagnostics, which is acceptable for a temporary debug-only bootstrap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(ci): drop beforeEach report throttle from 250ms to 100ms Run 26399285213's rerun captured a sixth death point on the new 4Hz cadence (`socketio.ts > Duplicate-author handling > cookie identity: same-author second socket kicks the first`, kill at +45953ms, 271ms after test start). The throttle suppressed the dying test's own beforeEach: previous boundary write landed 128 ms earlier and the next 31 ms after that, both inside the 250 ms window. Last captured report (be-0100) is from the previous test. 100 ms is still well above the inter-test cadence in fast burst suites (tests fire 2-5 ms apart, so 20-50 of them get throttled to a single write, ceiling ~10 writes/sec). But it's tight enough that any death-window neighbour ≥100 ms after the previous report — the shape we keep observing — gets its own boundary snapshot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Fixes issue where edits made while disconnected sat as pending local changesets and were only transmitted when the user made another edit.
Changes
Why this fix
After reconnecting, called and but never called . The fix in ensures pending changes are flushed once all server revisions have been applied.
Fixes ether#5108
Summary by cubic
Flushes any offline edits immediately after reconnect by sending pending changes as soon as server revisions finish applying. This fixes pending changesets that only synced after making a new edit.
New Features
settings.cookie.prefixto avoid collisions with other apps (backward compatible; defaults to empty).settings.cookie.sessionCleanup).Bug Fixes
pad.remove(); shows proper error if not allowed.appendTextAPI attributes inserted text to the supplied author so colors and author lists are correct.numConnectedUsersfor the joining user.langreliably overrides defaults, custom strings load without stale cache, language list sorted by native name, andwindow._()always available for plugins.aria-liveto stop character echo, popups fit small screens, and compose/dead-key input no longer eats spaces on Firefox/Linux.Written for commit f430da5. Summary will update on new commits.