Showing preview only (8,587K chars total). Download the full file or copy to clipboard to get everything.
Repository: socketio/socket.io
Branch: main
Commit: e4d016bd5b4d
Files: 756
Total size: 8.1 MB
Directory structure:
gitextract_cbdandz_/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── build-examples.yml
│ ├── ci-browser.yml
│ ├── ci.yml
│ └── publish.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── docs/
│ ├── README.md
│ ├── engine.io-protocol/
│ │ ├── v3-test-suite/
│ │ │ ├── .gitignore
│ │ │ ├── index.html
│ │ │ ├── node-imports.js
│ │ │ ├── package.json
│ │ │ └── test-suite.js
│ │ ├── v3.md
│ │ ├── v4-current.md
│ │ └── v4-test-suite/
│ │ ├── .gitignore
│ │ ├── index.html
│ │ ├── node-imports.js
│ │ ├── package.json
│ │ └── test-suite.js
│ └── socket.io-protocol/
│ ├── v3.md
│ ├── v4.md
│ ├── v5-current.md
│ └── v5-test-suite/
│ ├── .gitignore
│ ├── index.html
│ ├── node-imports.js
│ ├── package.json
│ └── test-suite.js
├── examples/
│ ├── .gitignore
│ ├── ReactNativeExample/
│ │ ├── .bundle/
│ │ │ └── config
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── .prettierrc.js
│ │ ├── .watchmanconfig
│ │ ├── App.tsx
│ │ ├── Gemfile
│ │ ├── README.md
│ │ ├── __tests__/
│ │ │ └── App.test.tsx
│ │ ├── android/
│ │ │ ├── app/
│ │ │ │ ├── build.gradle
│ │ │ │ ├── debug.keystore
│ │ │ │ ├── proguard-rules.pro
│ │ │ │ └── src/
│ │ │ │ ├── debug/
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ └── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── reactnativeexample/
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ └── MainApplication.kt
│ │ │ │ └── res/
│ │ │ │ ├── drawable/
│ │ │ │ │ └── rn_edit_text_material.xml
│ │ │ │ └── values/
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── build.gradle
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradle.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ └── settings.gradle
│ │ ├── app.json
│ │ ├── babel.config.js
│ │ ├── index.js
│ │ ├── ios/
│ │ │ ├── .xcode.env
│ │ │ ├── Podfile
│ │ │ ├── ReactNativeExample/
│ │ │ │ ├── AppDelegate.h
│ │ │ │ ├── AppDelegate.mm
│ │ │ │ ├── Images.xcassets/
│ │ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Info.plist
│ │ │ │ ├── LaunchScreen.storyboard
│ │ │ │ └── main.m
│ │ │ ├── ReactNativeExample.xcodeproj/
│ │ │ │ ├── project.pbxproj
│ │ │ │ └── xcshareddata/
│ │ │ │ └── xcschemes/
│ │ │ │ └── ReactNativeExample.xcscheme
│ │ │ └── ReactNativeExampleTests/
│ │ │ ├── Info.plist
│ │ │ └── ReactNativeExampleTests.m
│ │ ├── jest.config.js
│ │ ├── metro.config.js
│ │ ├── package.json
│ │ ├── server/
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── socket.js
│ │ └── tsconfig.json
│ ├── angular-todomvc/
│ │ ├── .browserslistrc
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── angular.json
│ │ ├── e2e/
│ │ │ ├── protractor.conf.js
│ │ │ ├── src/
│ │ │ │ ├── app.e2e-spec.ts
│ │ │ │ └── app.po.ts
│ │ │ └── tsconfig.json
│ │ ├── karma.conf.js
│ │ ├── package.json
│ │ ├── server.ts
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── app.component.css
│ │ │ │ ├── app.component.html
│ │ │ │ ├── app.component.spec.ts
│ │ │ │ ├── app.component.ts
│ │ │ │ ├── app.module.ts
│ │ │ │ └── store.ts
│ │ │ ├── assets/
│ │ │ │ └── .gitkeep
│ │ │ ├── environments/
│ │ │ │ ├── environment.prod.ts
│ │ │ │ └── environment.ts
│ │ │ ├── index.html
│ │ │ ├── main.ts
│ │ │ ├── polyfills.ts
│ │ │ ├── styles.css
│ │ │ └── test.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.spec.json
│ │ └── tslint.json
│ ├── basic-crud-application/
│ │ ├── README.md
│ │ ├── angular-client/
│ │ │ ├── .editorconfig
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── angular.json
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ ├── app/
│ │ │ │ │ ├── app.component.css
│ │ │ │ │ ├── app.component.html
│ │ │ │ │ ├── app.component.spec.ts
│ │ │ │ │ ├── app.component.ts
│ │ │ │ │ ├── app.config.ts
│ │ │ │ │ ├── app.routes.ts
│ │ │ │ │ └── store.ts
│ │ │ │ ├── assets/
│ │ │ │ │ └── .gitkeep
│ │ │ │ ├── environments/
│ │ │ │ │ ├── environment.development.ts
│ │ │ │ │ └── environment.ts
│ │ │ │ ├── index.html
│ │ │ │ ├── main.ts
│ │ │ │ └── styles.css
│ │ │ ├── tsconfig.app.json
│ │ │ ├── tsconfig.json
│ │ │ └── tsconfig.spec.json
│ │ ├── common/
│ │ │ └── events.ts
│ │ ├── server/
│ │ │ ├── lib/
│ │ │ │ ├── app.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── todo-management/
│ │ │ │ │ ├── todo.handlers.ts
│ │ │ │ │ └── todo.repository.ts
│ │ │ │ └── util.ts
│ │ │ ├── package.json
│ │ │ ├── test/
│ │ │ │ └── todo-management/
│ │ │ │ └── todo.tests.ts
│ │ │ └── tsconfig.json
│ │ ├── server-postgres-cluster/
│ │ │ ├── README.md
│ │ │ ├── docker-compose.yml
│ │ │ ├── lib/
│ │ │ │ ├── app.js
│ │ │ │ ├── cluster.js
│ │ │ │ ├── index.js
│ │ │ │ ├── todo-management/
│ │ │ │ │ ├── todo.handlers.js
│ │ │ │ │ └── todo.repository.js
│ │ │ │ └── util.js
│ │ │ └── package.json
│ │ └── vue-client/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── jsconfig.json
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── index.html
│ │ │ └── styles.css
│ │ ├── src/
│ │ │ ├── App.vue
│ │ │ ├── main.js
│ │ │ ├── socket.js
│ │ │ └── stores/
│ │ │ └── todo.js
│ │ └── vue.config.js
│ ├── basic-websocket-client/
│ │ ├── README.md
│ │ ├── check-bundle-size.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ └── index.js
│ │ └── test/
│ │ └── index.js
│ ├── chat/
│ │ ├── README.md
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-engine-node-cluster/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── package.json
│ │ └── server.js
│ ├── cluster-engine-redis/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── compose.yaml
│ │ ├── package.json
│ │ └── server.js
│ ├── cluster-haproxy/
│ │ ├── README.md
│ │ ├── docker-compose.yml
│ │ ├── haproxy.cfg
│ │ └── server/
│ │ ├── Dockerfile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-httpd/
│ │ ├── README.md
│ │ ├── docker-compose.yml
│ │ ├── httpd.conf
│ │ └── server/
│ │ ├── Dockerfile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-nginx/
│ │ ├── README.md
│ │ ├── client/
│ │ │ ├── Dockerfile
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── docker-compose.yml
│ │ ├── nginx.conf
│ │ └── server/
│ │ ├── Dockerfile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-traefik/
│ │ ├── README.md
│ │ ├── docker-compose.yml
│ │ ├── server/
│ │ │ ├── Dockerfile
│ │ │ ├── index.js
│ │ │ ├── package.json
│ │ │ └── public/
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── style.css
│ │ └── traefik.yml
│ ├── connection-state-recovery-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── .codesandbox/
│ │ │ │ ├── Dockerfile
│ │ │ │ └── tasks.json
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── esm/
│ │ ├── .codesandbox/
│ │ │ ├── Dockerfile
│ │ │ └── tasks.json
│ │ ├── index.html
│ │ ├── index.js
│ │ └── package.json
│ ├── create-react-app-example/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ └── robots.txt
│ │ ├── server.js
│ │ └── src/
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ ├── custom-parsers/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── .gitignore
│ │ │ └── index.html
│ │ ├── src/
│ │ │ ├── client1.js
│ │ │ ├── client2.js
│ │ │ ├── client3.js
│ │ │ ├── client4.js
│ │ │ ├── custom-parser.js
│ │ │ └── server.js
│ │ └── support/
│ │ └── webpack.config.js
│ ├── es-modules/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── package.json
│ │ └── server.js
│ ├── expo-example/
│ │ ├── .gitignore
│ │ ├── App.js
│ │ ├── app.json
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── server/
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── socket.js
│ ├── express-session-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── esm/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── ts/
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── nestjs-example/
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── .prettierrc
│ │ ├── README.md
│ │ ├── nest-cli.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app.controller.spec.ts
│ │ │ ├── app.controller.ts
│ │ │ ├── app.module.ts
│ │ │ ├── app.service.ts
│ │ │ ├── events/
│ │ │ │ ├── events.gateway.ts
│ │ │ │ └── events.module.ts
│ │ │ └── main.ts
│ │ ├── test/
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── jest-e2e.json
│ │ ├── tsconfig.build.json
│ │ ├── tsconfig.json
│ │ └── views/
│ │ └── index.hbs
│ ├── nextjs-app-router/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── jsconfig.json
│ │ ├── next.config.mjs
│ │ ├── package.json
│ │ ├── server.js
│ │ └── src/
│ │ ├── app/
│ │ │ ├── globals.css
│ │ │ ├── layout.js
│ │ │ ├── page.js
│ │ │ └── page.module.css
│ │ └── socket.js
│ ├── nextjs-pages-router/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── jsconfig.json
│ │ ├── next.config.mjs
│ │ ├── package.json
│ │ ├── server.js
│ │ └── src/
│ │ ├── pages/
│ │ │ ├── _app.js
│ │ │ ├── _document.js
│ │ │ ├── api/
│ │ │ │ └── hello.js
│ │ │ └── index.js
│ │ ├── socket.js
│ │ └── styles/
│ │ ├── Home.module.css
│ │ └── globals.css
│ ├── nuxt-example/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── app.vue
│ │ ├── components/
│ │ │ ├── Connection.client.vue
│ │ │ └── socket.ts
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ ├── server/
│ │ │ ├── plugins/
│ │ │ │ └── socket.io.ts
│ │ │ └── tsconfig.json
│ │ └── tsconfig.json
│ ├── nwjs-example/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── package.json
│ │ └── server/
│ │ ├── index.js
│ │ └── package.json
│ ├── passport-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── login.html
│ │ │ └── package.json
│ │ ├── esm/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── login.html
│ │ │ └── package.json
│ │ └── ts/
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── login.html
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── passport-jwt-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── esm/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── ts/
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── postgres-adapter-example/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── cluster.js
│ │ ├── compose.yaml
│ │ ├── package.json
│ │ └── server.js
│ ├── private-messaging/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── public/
│ │ │ └── index.html
│ │ ├── server/
│ │ │ ├── cluster.js
│ │ │ ├── docker-compose.yml
│ │ │ ├── index.js
│ │ │ ├── messageStore.js
│ │ │ ├── package.json
│ │ │ └── sessionStore.js
│ │ └── src/
│ │ ├── App.vue
│ │ ├── components/
│ │ │ ├── Chat.vue
│ │ │ ├── MessagePanel.vue
│ │ │ ├── SelectUsername.vue
│ │ │ ├── StatusIcon.vue
│ │ │ └── User.vue
│ │ ├── main.js
│ │ └── socket.js
│ ├── rollup-server-bundle/
│ │ ├── .gitignore
│ │ ├── index.js
│ │ ├── package.json
│ │ └── rollup.config.js
│ ├── tweet-stream/
│ │ ├── index.js
│ │ └── package.json
│ ├── typescript-client-example/
│ │ ├── cjs/
│ │ │ ├── client.ts
│ │ │ ├── package.json
│ │ │ └── tsconfig.json
│ │ └── esm/
│ │ ├── client.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── typescript-example/
│ │ ├── cjs/
│ │ │ ├── client.ts
│ │ │ ├── package.json
│ │ │ ├── server.ts
│ │ │ └── tsconfig.json
│ │ └── esm/
│ │ ├── client.ts
│ │ ├── package.json
│ │ ├── server.ts
│ │ └── tsconfig.json
│ ├── webpack-build/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── package.json
│ │ └── webpack.config.js
│ ├── webpack-build-server/
│ │ ├── README.md
│ │ ├── index.js
│ │ ├── package.json
│ │ └── webpack.config.js
│ ├── webtransport/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── generate_cert.sh
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── open_chrome.sh
│ │ └── package.json
│ └── whiteboard/
│ ├── README.md
│ ├── index.js
│ ├── package.json
│ └── public/
│ ├── index.html
│ ├── main.js
│ └── style.css
├── package.json
└── packages/
├── engine.io/
│ ├── .eslintrc.json
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── examples/
│ │ ├── esm-import/
│ │ │ ├── README.md
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── latency/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── package.json
│ │ │ └── public/
│ │ │ ├── index.js
│ │ │ └── style.css
│ │ ├── memory-usage/
│ │ │ ├── .gitignore
│ │ │ ├── client.js
│ │ │ ├── package.json
│ │ │ └── server.js
│ │ └── memory-usage-webtransport/
│ │ ├── .gitignore
│ │ ├── client.js
│ │ ├── generate_cert.sh
│ │ ├── package.json
│ │ └── server.js
│ ├── lib/
│ │ ├── contrib/
│ │ │ └── types.cookie.ts
│ │ ├── engine.io.ts
│ │ ├── parser-v3/
│ │ │ ├── index.ts
│ │ │ └── utf8.ts
│ │ ├── server.ts
│ │ ├── socket.ts
│ │ ├── transport.ts
│ │ ├── transports/
│ │ │ ├── index.ts
│ │ │ ├── polling-jsonp.ts
│ │ │ ├── polling.ts
│ │ │ ├── websocket.ts
│ │ │ └── webtransport.ts
│ │ ├── transports-uws/
│ │ │ ├── index.ts
│ │ │ ├── polling.ts
│ │ │ └── websocket.ts
│ │ └── userver.ts
│ ├── package.json
│ ├── test/
│ │ ├── .eslintrc.json
│ │ ├── common.js
│ │ ├── engine.io.js
│ │ ├── fixtures/
│ │ │ ├── ca.crt
│ │ │ ├── ca.key
│ │ │ ├── client.crt
│ │ │ ├── client.csr
│ │ │ ├── client.key
│ │ │ ├── client.pfx
│ │ │ ├── generate_certs.sh
│ │ │ ├── server-close-upgraded.js
│ │ │ ├── server-close-upgrading.js
│ │ │ ├── server-close.js
│ │ │ ├── server.crt
│ │ │ ├── server.csr
│ │ │ └── server.key
│ │ ├── middlewares.js
│ │ ├── parser.js
│ │ ├── server.js
│ │ ├── util.mjs
│ │ └── webtransport.mjs
│ ├── tsconfig.json
│ └── wrapper.mjs
├── engine.io-client/
│ ├── .gitignore
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── lib/
│ │ ├── browser-entrypoint.ts
│ │ ├── contrib/
│ │ │ ├── has-cors.ts
│ │ │ ├── parseqs.ts
│ │ │ └── parseuri.ts
│ │ ├── globals.node.ts
│ │ ├── globals.ts
│ │ ├── index.ts
│ │ ├── socket.ts
│ │ ├── transport.ts
│ │ ├── transports/
│ │ │ ├── index.ts
│ │ │ ├── polling-fetch.ts
│ │ │ ├── polling-xhr.node.ts
│ │ │ ├── polling-xhr.ts
│ │ │ ├── polling.ts
│ │ │ ├── websocket.node.ts
│ │ │ ├── websocket.ts
│ │ │ └── webtransport.ts
│ │ └── util.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── bundle-size.js
│ │ ├── package.cjs.json
│ │ ├── package.esm.json
│ │ ├── prod.config.js
│ │ ├── rollup.config.esm.js
│ │ ├── rollup.config.umd.js
│ │ └── webpack.config.js
│ ├── test/
│ │ ├── arraybuffer/
│ │ │ ├── index.js
│ │ │ ├── polling.js
│ │ │ └── ws.js
│ │ ├── binary-fallback.js
│ │ ├── blob/
│ │ │ ├── index.js
│ │ │ ├── polling.js
│ │ │ └── ws.js
│ │ ├── connection.js
│ │ ├── engine.io-client.js
│ │ ├── fixtures/
│ │ │ ├── no-unref.js
│ │ │ ├── unref-polling-only.js
│ │ │ ├── unref-websocket-only.js
│ │ │ └── unref.js
│ │ ├── index.js
│ │ ├── node.js
│ │ ├── parseuri.js
│ │ ├── socket.js
│ │ ├── support/
│ │ │ ├── env.js
│ │ │ ├── hooks.js
│ │ │ ├── public/
│ │ │ │ └── worker.js
│ │ │ └── server.js
│ │ ├── transport.js
│ │ ├── util-wt.mjs
│ │ ├── util.js
│ │ ├── webtransport.mjs
│ │ └── xmlhttprequest.js
│ ├── tsconfig.esm.json
│ └── tsconfig.json
├── engine.io-parser/
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── benchmarks/
│ │ ├── index.js
│ │ └── results.md
│ ├── lib/
│ │ ├── commons.ts
│ │ ├── contrib/
│ │ │ └── base64-arraybuffer.ts
│ │ ├── decodePacket.browser.ts
│ │ ├── decodePacket.ts
│ │ ├── encodePacket.browser.ts
│ │ ├── encodePacket.ts
│ │ └── index.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── package.cjs.json
│ │ └── package.esm.json
│ ├── test/
│ │ ├── browser.ts
│ │ ├── index.ts
│ │ ├── node.ts
│ │ └── util.ts
│ ├── tsconfig.esm.json
│ └── tsconfig.json
├── socket.io/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── RELEASING.md
│ ├── Readme.md
│ ├── client-dist/
│ │ └── socket.io.js
│ ├── lib/
│ │ ├── broadcast-operator.ts
│ │ ├── client.ts
│ │ ├── index.ts
│ │ ├── namespace.ts
│ │ ├── parent-namespace.ts
│ │ ├── socket-types.ts
│ │ ├── socket.ts
│ │ ├── typed-events.ts
│ │ └── uws.ts
│ ├── package.json
│ ├── test/
│ │ ├── close.ts
│ │ ├── connection-state-recovery.ts
│ │ ├── fixtures/
│ │ │ ├── big.json
│ │ │ └── server-close.ts
│ │ ├── handshake.ts
│ │ ├── index.ts
│ │ ├── messaging-many.ts
│ │ ├── middleware.ts
│ │ ├── namespaces.ts
│ │ ├── server-attachment.ts
│ │ ├── socket-middleware.ts
│ │ ├── socket-timeout.ts
│ │ ├── socket.io.test-d.ts
│ │ ├── socket.ts
│ │ ├── support/
│ │ │ ├── expectjs.d.ts
│ │ │ └── util.ts
│ │ ├── utility-methods.ts
│ │ ├── uws.ts
│ │ └── v2-compatibility.ts
│ ├── tsconfig.json
│ └── wrapper.mjs
├── socket.io-adapter/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── lib/
│ │ ├── cluster-adapter.ts
│ │ ├── contrib/
│ │ │ └── yeast.ts
│ │ ├── in-memory-adapter.ts
│ │ └── index.ts
│ ├── package.json
│ ├── test/
│ │ ├── cluster-adapter.ts
│ │ ├── index.ts
│ │ └── util.ts
│ └── tsconfig.json
├── socket.io-client/
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── RELEASING.md
│ ├── babel.config.js
│ ├── docs/
│ │ └── README.md
│ ├── lib/
│ │ ├── browser-entrypoint.ts
│ │ ├── contrib/
│ │ │ └── backo2.ts
│ │ ├── index.ts
│ │ ├── manager.ts
│ │ ├── on.ts
│ │ ├── socket.ts
│ │ └── url.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── bundle-size.js
│ │ ├── package.esm.json
│ │ ├── rollup.config.esm.js
│ │ ├── rollup.config.umd.js
│ │ └── rollup.config.umd.msgpack.js
│ ├── test/
│ │ ├── .eslintrc.json
│ │ ├── browser-runner.ts
│ │ ├── connection-state-recovery.ts
│ │ ├── connection.ts
│ │ ├── fixtures/
│ │ │ ├── no-unref.ts
│ │ │ ├── unref-during-reconnection.ts
│ │ │ ├── unref-polling-only.ts
│ │ │ ├── unref-websocket-only.ts
│ │ │ └── unref.ts
│ │ ├── index.ts
│ │ ├── node.ts
│ │ ├── retry.ts
│ │ ├── socket.ts
│ │ ├── support/
│ │ │ ├── hooks.ts
│ │ │ ├── server.ts
│ │ │ └── util.ts
│ │ ├── typed-events.test-d.ts
│ │ └── url.ts
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── wdio.conf.js
├── socket.io-cluster-adapter/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── assets/
│ │ └── adapter.excalidraw
│ ├── lib/
│ │ └── index.ts
│ ├── package.json
│ ├── test/
│ │ ├── index.ts
│ │ ├── util.ts
│ │ └── worker.js
│ └── tsconfig.json
├── socket.io-cluster-engine/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── compose.yaml
│ ├── lib/
│ │ ├── cluster.ts
│ │ ├── engine.ts
│ │ ├── index.ts
│ │ └── redis.ts
│ ├── package.json
│ ├── test/
│ │ ├── cluster.ts
│ │ ├── in-memory.ts
│ │ ├── redis.ts
│ │ ├── util.ts
│ │ └── worker.js
│ └── tsconfig.json
├── socket.io-component-emitter/
│ ├── History.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── component.json
│ ├── lib/
│ │ ├── cjs/
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── esm/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ └── package.json
│ ├── package.json
│ └── test/
│ └── emitter.js
├── socket.io-parser/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── babel.config.js
│ ├── bench/
│ │ ├── index.js
│ │ └── results.md
│ ├── lib/
│ │ ├── binary.ts
│ │ ├── index.ts
│ │ └── is-binary.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── package.cjs.json
│ │ └── package.esm.json
│ ├── test/
│ │ ├── arraybuffer.js
│ │ ├── blob.js
│ │ ├── buffer.js
│ │ ├── helpers.js
│ │ ├── index.js
│ │ ├── parser.js
│ │ └── support/
│ │ └── env.js
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── wdio.conf.js
├── socket.io-postgres-emitter/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── assets/
│ │ └── emitter.excalidraw
│ ├── compose.yaml
│ ├── lib/
│ │ ├── index.ts
│ │ └── typed-events.ts
│ ├── package.json
│ ├── test/
│ │ ├── index.ts
│ │ └── util.ts
│ └── tsconfig.json
└── socket.io-redis-streams-emitter/
├── CHANGELOG.md
├── LICENSE
├── README.md
├── compose.yaml
├── lib/
│ ├── adapter-types.ts
│ ├── index.ts
│ ├── typed-events.ts
│ └── util.ts
├── package.json
├── test/
│ ├── index.ts
│ └── util.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'to triage'
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Please fill the following code example:
Socket.IO server version: `x.y.z`
*Server*
```js
import { Server } from "socket.io";
const io = new Server(3000, {});
io.on("connection", (socket) => {
console.log(`connect ${socket.id}`);
socket.on("disconnect", () => {
console.log(`disconnect ${socket.id}`);
});
});
```
Socket.IO client version: `x.y.z`
*Client*
```js
import { io } from "socket.io-client";
const socket = io("ws://localhost:3000/", {});
socket.on("connect", () => {
console.log(`connect ${socket.id}`);
});
socket.on("disconnect", () => {
console.log("disconnect");
});
```
**Expected behavior**
A clear and concise description of what you expected to happen.
**Platform:**
- Device: [e.g. Samsung S8]
- OS: [e.g. Android 9.2]
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Ask a Question
url: https://github.com/socketio/socket.io/discussions/new?category=q-a
about: Ask the community for help
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'enhancement'
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
### The kind of change this PR does introduce
* [x] a bug fix
* [ ] a new feature
* [ ] an update to the documentation
* [ ] a code change that improves performance
* [ ] other
### Current behavior
### New behavior
### Other information (e.g. related issues)
================================================
FILE: .github/workflows/build-examples.yml
================================================
name: Build examples
on:
schedule:
- cron: '0 0 * * 0'
permissions:
contents: read
jobs:
build-examples:
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
example:
- custom-parsers
- typescript-example/cjs
- typescript-example/esm
- typescript-client-example/cjs
- typescript-client-example/esm
- webpack-build
- webpack-build-server
- basic-crud-application/angular-client
- basic-crud-application/vue-client
- nextjs-pages-router
- nextjs-app-router
- nuxt-example
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js 20
uses: actions/setup-node@v6
with:
node-version: 20
- name: Build ${{ matrix.example }}
run: |
cd examples/${{ matrix.example }}
npm install
npm run build
================================================
FILE: .github/workflows/ci-browser.yml
================================================
name: CI (browser)
on:
push:
branches:
- '**'
paths:
- 'packages/engine.io-parser/**'
- 'packages/engine.io-client/**'
- 'packages/socket.io-parser/**'
- 'packages/socket.io-client/**'
permissions:
contents: read
jobs:
test-browser:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js 20
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Compile each package
run: npm run compile --workspaces --if-present
- name: Run tests
run: npm test --workspace=socket.io-parser --workspace=socket.io-client
env:
BROWSERS: 1
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches:
- '**'
pull_request:
schedule:
- cron: '0 0 * * 0'
permissions:
contents: read
jobs:
test-node:
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
node-version:
- 20
- 22
- 24
services:
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: changeit
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Compile each package
run: npm run compile --workspaces --if-present
- name: Run tests
run: npm test --workspaces
- name: Run tests with uws (engine.io)
run: npm run test:uws --workspace=engine.io
if: ${{ matrix.node-version == '18' }}
- name: Run tests with fetch instead of XHR (engine.io-client)
run: npm run test:node-fetch --workspace=engine.io-client
if: ${{ matrix.node-version == '18' }}
- name: Run tests with Node.js native WebSocket (engine.io-client)
run: npm run test:node-builtin-ws --workspace=engine.io-client
if: ${{ matrix.node-version == '22' }}
================================================
FILE: .github/workflows/publish.yml
================================================
# reference: https://docs.npmjs.com/trusted-publishers#for-github-actions
name: Publish
on:
push:
tags:
# expected format: <package>@<version> (example: socket.io@1.2.3)
- '**@*'
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js 24
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Compile each package
run: npm run compile --workspaces --if-present
- name: Publish package
run: npm publish --workspace=${GITHUB_REF_NAME%@*} --access public
================================================
FILE: .gitignore
================================================
.DS_Store
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
benchmarks/*.png
node_modules
coverage
.idea
.nyc_output
dist/
build/
================================================
FILE: CHANGELOG.md
================================================
# Changelog
Here are the detailed changelogs for each package in this monorepo:
| Package | Changelog |
|------------------------------------|----------------------------------------------------------------|
| `engine.io` | [link](packages/engine.io/CHANGELOG.md) |
| `engine.io-client` | [link](packages/engine.io-client/CHANGELOG.md) |
| `engine.io-parser` | [link](packages/engine.io-parser/CHANGELOG.md) |
| `socket.io` | [link](packages/socket.io/CHANGELOG.md) |
| `socket.io-adapter` | [link](packages/socket.io-adapter/CHANGELOG.md) |
| `socket.io-client` | [link](packages/socket.io-client/CHANGELOG.md) |
| `@socket.io/cluster-adapter` | [link](packages/socket.io-cluster-adapter/CHANGELOG.md) |
| `@socket.io/cluster-engine` | [link](packages/socket.io-cluster-engine/CHANGELOG.md) |
| `@socket.io/component-emitter` | [link](packages/socket.io-component-emitter/History.md) |
| `socket.io-parser` | [link](packages/socket.io-parser/CHANGELOG.md) |
| `@socket.io/postgres-emitter` | [link](packages/socket.io-postgres-emitter/CHANGELOG.md) |
| `@socket.io/redis-streams-emitter` | [link](/packages/socket.io-redis-streams-emitter/CHANGELOG.md) |
================================================
FILE: CONTRIBUTING.md
================================================
# Socket.IO Contributing Guide
Thanks a lot for your interest in contributing to Socket.IO!
Before submitting your contribution, please make sure to take a moment and read through the following guidelines:
<!-- TOC -->
* [Before you start](#before-you-start)
* [Guidelines for reporting a bug](#guidelines-for-reporting-a-bug)
* [Guidelines for requesting a feature](#guidelines-for-requesting-a-feature)
* [Guidelines for creating a pull request](#guidelines-for-creating-a-pull-request)
* [Bug fix](#bug-fix)
* [New feature](#new-feature)
* [Project structure](#project-structure)
* [Development setup](#development-setup)
* [Commands](#commands)
* [Compile with TypeScript](#compile-with-typescript)
* [Apply formatting](#apply-formatting)
* [Run the tests](#run-the-tests)
<!-- TOC -->
## Before you start
Our [issues list](https://github.com/socketio/socket.io/issues) is exclusively reserved for bug reports and feature requests. For usage questions, please use the following resources:
- read the [docs](https://socket.io/docs/v4/)
- check the [troubleshooting guide](https://socket.io/docs/v4/troubleshooting-connection-issues/)
- look for/ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/socket.io)
- create a new [discussion](https://github.com/socketio/socket.io/discussions/new?category=q-a)
## Guidelines for reporting a bug
If you think that you have found a security vulnerability in our project, please do not create an issue in this GitHub repository, but rather refer to our [security policy](./SECURITY.md).
Please make sure that the bug hasn't already been reported in our [issues list](https://github.com/socketio/socket.io/issues?q=label%3Abug+), as it may already have been fixed in a recent version. However, if the bug was reported in an old, closed issue but persists, you should open a new issue instead of commenting on the old issue.
After these checks, please [create a new bug report](https://github.com/socketio/socket.io/issues/new/choose) with all the necessary details:
- package versions
- platform (device, browser, operating system)
- a minimal reproduction (you can fork [this repository](https://github.com/socketio/socket.io-fiddle))
Without a clear way to reproduce the bug, we unfortunately won't be able to help you.
## Guidelines for requesting a feature
Please make sure that the feature hasn't already been requested in our [issues list](https://github.com/socketio/socket.io/labels/enhancement).
After these checks, please [create a new feature request](https://github.com/socketio/socket.io/issues/new/choose) with all the necessary details:
- what the problem is
- what you want to happen
- any alternative solutions or features you have considered
## Guidelines for creating a pull request
### Bug fix
- if you fix a bug which is described in our [issues list](https://github.com/socketio/socket.io/issues), please add a reference to it in the description of your pull request. Otherwise, please provide all necessary details to reproduce the bug, as described [above](#guidelines-for-reporting-a-bug).
- add one or more test cases, in order to avoid any regression in the future
- make sure existing tests still pass
### New feature
- we strongly suggest that you first open a [feature request](#guidelines-for-requesting-a-feature) and have it approved before working on it. In that case, please add a reference to it in the description of your pull request.
- add one or more test cases, in order to avoid any regression in the future
- make sure existing tests still pass
## Project structure
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) which contains the source of the following packages:
| Package | Description |
|--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `engine.io` | The server-side implementation of the low-level communication layer. |
| `engine.io-client` | The client-side implementation of the low-level communication layer. |
| `engine.io-parser` | The parser responsible for encoding and decoding Engine.IO packets, used by both the `engine.io` and `engine.io-client` packages. |
| `socket.io` | The server-side implementation of the bidirectional channel, built on top on the `engine.io` package. |
| `socket.io-adapter` | An extensible component responsible for broadcasting a packet to all connected clients, used by the `socket.io` package. |
| `socket.io-client` | The client-side implementation of the bidirectional channel, built on top on the `engine.io-client` package. |
| `@socket.io/cluster-engine` | A cluster-friendly engine to share load between multiple Node.js processes (without sticky sessions) |
| `@socket.io/component-emitter` | An `EventEmitter` implementation, similar to the one provided by [Node.js](https://nodejs.org/api/events.html) but for all platforms. |
| `socket.io-parser` | The parser responsible for encoding and decoding Socket.IO packets, used by both the `socket.io` and `socket.io-client` packages. |
## Development setup
You will need [Node.js](https://nodejs.org) **version 18+**, and [`npm`](https://docs.npmjs.com/about-npm) **version 7+**, as we make use of npm's [workspaces feature](https://docs.npmjs.com/cli/v10/using-npm/workspaces).
After cloning the repository, please run:
```bash
npm ci
```
to install all dependencies.
Here is the list of tools that we use:
- [TypeScript](https://www.typescriptlang.org/) as the development language
- [Rollup](https://rollupjs.org/) for production bundling
- [Prettier](https://prettier.io/) for code formatting
- [Mocha](https://mochajs.org/) for testing
- [WebdriverIO](https://webdriver.io/) for browser and mobile testing
## Commands
Each npm workspace corresponds to a package. You can run the command:
- on all workspaces with the `--workspace` command-line argument (abbreviated `-ws`)
- on a specific workspace with the `--workspace=<some-workspace>` command-line argument
### Compile with TypeScript
For all workspaces:
```bash
npm run compile -ws --if-present
```
For a specific workspace:
```bash
npm run compile --workspace=socket.io
```
### Apply formatting
For all workspaces:
```bash
npm run format:fix -ws
```
For a specific workspace:
```bash
npm run format:fix --workspace=socket.io
```
### Run the tests
For all workspaces:
```bash
npm test -ws
```
For a specific workspace:
```bash
npm test --workspace=socket.io
```
### Generate the changelog
Install the [`conventional-changelog-cli`](https://www.npmjs.com/package/conventional-changelog-cli) package:
```bash
npm i -g conventional-changelog-cli
```
Then run:
```bash
cd packages/engine.io-client
conventional-changelog -p angular --tag-prefix "engine.io-client@" --commit-path .
```
================================================
FILE: LICENSE
================================================
(The MIT License)
Copyright (c) 2014-present Guillermo Rauch and Socket.IO contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# socket.io
[](https://www.npmjs.com/package/socket.io)
[](https://github.com/socketio/socket.io/actions/workflows/ci.yml)
[]((https://www.npmjs.com/package/socket.io))
## Getting Started
Please check our documentation [here](https://socket.io).
## Questions
Our [issues list](https://github.com/socketio/socket.io/issues) is exclusively reserved for bug reports and feature requests. For usage questions, please use the following resources:
- read our [documentation](https://socket.io/docs/v4/)
- check our [troubleshooting guide](https://socket.io/docs/v4/troubleshooting-connection-issues/)
- look for/ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/socket.io)
- create a new [discussion](https://github.com/socketio/socket.io/discussions/new?category=q-a)
## Security
If you think that you have found a security vulnerability in our project, please do not create an issue in this GitHub repository, but rather refer to our [Security Policy](./SECURITY.md).
## Issues and contribution
Please make sure to read our [Contributing Guide](./CONTRIBUTING.md) before creating an issue or making a pull request.
Thanks to everyone who has already contributed to Socket.IO!
<a href="https://github.com/socketio/socket.io/graphs/contributors"><img src="https://opencollective.com/socketio/contributors.svg?width=890" /></a>
## License
[MIT](https://opensource.org/licenses/MIT)
================================================
FILE: SECURITY.md
================================================
# Security Policy
<!-- TOC -->
* [Supported Versions](#supported-versions)
* [Reporting a Vulnerability](#reporting-a-vulnerability)
* [History](#history)
* [For the `socket.io` package](#for-the-socketio-package)
* [For the `socket.io-client` package](#for-the-socketio-client-package)
<!-- TOC -->
## Supported Versions
| Version | Supported |
|---------|--------------------|
| 4.x | :white_check_mark: |
| 3.x | :white_check_mark: |
| 2.4.x | :white_check_mark: |
| < 2.4.0 | :x: |
## Reporting a Vulnerability
To report a security vulnerability in this package, please send an email to [@darrachequesne](https://github.com/darrachequesne) (see address in profile) describing the vulnerability and how to reproduce it.
We will get back to you as soon as possible and publish a fix if necessary.
:warning: IMPORTANT :warning: please do not create an issue in this repository, as attackers might take advantage of it. Thank you in advance for your responsible disclosure.
## History
### For the `socket.io` package
| Date | Description | CVE number | Affected versions | Patched versions |
|--------------|------------------------------------------------------------------------------|------------------|-------------------------------------|-----------------------|
| July 2012 | [Insecure randomness](https://github.com/advisories/GHSA-qv2v-m59f-v5fw) | `CVE-2017-16031` | `<= 0.9.6` | `0.9.7` |
| January 2021 | [CORS misconfiguration](https://github.com/advisories/GHSA-fxwf-4rqh-v8g3) | `CVE-2020-28481` | `< 2.4.0` | `2.4.0` |
| June 2024 | [Unhandled 'error' event](https://github.com/advisories/GHSA-25hc-qcg6-38wj) | `CVE-2024-38355` | `< 2.5.1` <br/> `>= 3.0.0, < 4.6.2` | `2.5.1` <br/> `4.6.2` |
From the transitive dependencies:
| Date | Dependency | Description | CVE number |
|---------------|--------------------|-------------------------------------------------------------------------------------------------------------------------|------------------|
| January 2016 | `ws` | [Buffer vulnerability](https://github.com/advisories/GHSA-2mhh-w6q8-5hxw) | `CVE-2016-10518` |
| January 2016 | `ws` | [DoS due to excessively large websocket message](https://github.com/advisories/GHSA-6663-c963-2gqg) | `CVE-2016-10542` |
| November 2017 | `ws` | [DoS in the `Sec-Websocket-Extensions` header parser](https://github.com/advisories/GHSA-5v72-xg48-5rpm) | `-` |
| February 2020 | `engine.io` | [Resource exhaustion](https://github.com/advisories/GHSA-j4f2-536g-r55m) | `CVE-2020-36048` |
| January 2021 | `socket.io-parser` | [Resource exhaustion](https://github.com/advisories/GHSA-xfhh-g9f5-x4m4) | `CVE-2020-36049` |
| May 2021 | `ws` | [ReDoS in `Sec-Websocket-Protocol` header](https://github.com/advisories/GHSA-6fc8-4gx4-v693) | `CVE-2021-32640` |
| January 2022 | `engine.io` | [Uncaught exception](https://github.com/advisories/GHSA-273r-mgr4-v34f) | `CVE-2022-21676` |
| October 2022 | `socket.io-parser` | [Insufficient validation when decoding a Socket.IO packet](https://github.com/advisories/GHSA-qm95-pgcg-qqfq) | `CVE-2022-2421` |
| November 2022 | `engine.io` | [Uncaught exception](https://github.com/advisories/GHSA-r7qp-cfhv-p84w) | `CVE-2022-41940` |
| May 2023 | `engine.io` | [Uncaught exception](https://github.com/advisories/GHSA-q9mw-68c2-j6m5) | `CVE-2023-31125` |
| May 2023 | `socket.io-parser` | [Insufficient validation when decoding a Socket.IO packet](https://github.com/advisories/GHSA-cqmj-92xf-r6r9) | `CVE-2023-32695` |
| June 2024 | `ws` | [DoS when handling a request with many HTTP headers](https://github.com/advisories/GHSA-3h5v-q93c-6h6q) | `CVE-2024-37890` |
| March 2026 | `socket.io-parser` | [Unbounded number of binary attachments](https://github.com/socketio/socket.io/security/advisories/GHSA-677m-j7p3-52f9) | `CVE-2026-33151` |
### For the `socket.io-client` package
From the transitive dependencies:
| Date | Dependency | Description | CVE number |
|---------------|--------------------|-------------------------------------------------------------------------------------------------------------------------|------------------|
| January 2016 | `ws` | [Buffer vulnerability](https://github.com/advisories/GHSA-2mhh-w6q8-5hxw) | `CVE-2016-10518` |
| January 2016 | `ws` | [DoS due to excessively large websocket message](https://github.com/advisories/GHSA-6663-c963-2gqg) | `CVE-2016-10542` |
| October 2016 | `engine.io-client` | [Insecure Defaults Allow MITM Over TLS](https://github.com/advisories/GHSA-4r4m-hjwj-43p8) | `CVE-2016-10536` |
| November 2017 | `ws` | [DoS in the `Sec-Websocket-Extensions` header parser](https://github.com/advisories/GHSA-5v72-xg48-5rpm) | `-` |
| January 2021 | `socket.io-parser` | [Resource exhaustion](https://github.com/advisories/GHSA-xfhh-g9f5-x4m4) | `CVE-2020-36049` |
| May 2021 | `ws` | [ReDoS in `Sec-Websocket-Protocol` header](https://github.com/advisories/GHSA-6fc8-4gx4-v693) | `CVE-2021-32640` |
| October 2022 | `socket.io-parser` | [Insufficient validation when decoding a Socket.IO packet](https://github.com/advisories/GHSA-qm95-pgcg-qqfq) | `CVE-2022-2421` |
| May 2023 | `socket.io-parser` | [Insufficient validation when decoding a Socket.IO packet](https://github.com/advisories/GHSA-cqmj-92xf-r6r9) | `CVE-2023-32695` |
| June 2024 | `ws` | [DoS when handling a request with many HTTP headers](https://github.com/advisories/GHSA-3h5v-q93c-6h6q) | `CVE-2024-37890` |
| March 2026 | `socket.io-parser` | [Unbounded number of binary attachments](https://github.com/socketio/socket.io/security/advisories/GHSA-677m-j7p3-52f9) | `CVE-2026-33151` |
================================================
FILE: docs/README.md
================================================
The documentation has been moved to the website [here](https://socket.io/docs/).
================================================
FILE: docs/engine.io-protocol/v3-test-suite/.gitignore
================================================
node_modules
================================================
FILE: docs/engine.io-protocol/v3-test-suite/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test suite for the Engine.IO protocol</title>
<link rel="stylesheet" href="https://unpkg.com/mocha@9/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="https://unpkg.com/mocha@9/mocha.js"></script>
<script src="https://unpkg.com/chai@4/chai.js" ></script>
<script src="https://unpkg.com/chai-string@1/chai-string.js" ></script>
<script class="mocha-init">
mocha.setup("bdd");
mocha.checkLeaks();
</script>
<script type="module" src="test-suite.js"></script>
<script class="mocha-exec">
mocha.run();
</script>
</body>
</html>
================================================
FILE: docs/engine.io-protocol/v3-test-suite/node-imports.js
================================================
import fetch from "node-fetch";
import { WebSocket } from "ws";
import chai from "chai";
import chaiString from "chai-string";
chai.use(chaiString);
globalThis.fetch = fetch;
globalThis.WebSocket = WebSocket;
globalThis.chai = chai;
================================================
FILE: docs/engine.io-protocol/v3-test-suite/package.json
================================================
{
"name": "engine.io-protocol-test-suite",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"format": "prettier -w *.js",
"test": "mocha test-suite.js"
},
"devDependencies": {
"chai": "^4.3.6",
"chai-string": "^1.5.0",
"mocha": "^9.2.1",
"node-fetch": "^3.2.0",
"prettier": "^2.5.1",
"ws": "^8.5.0"
}
}
================================================
FILE: docs/engine.io-protocol/v3-test-suite/test-suite.js
================================================
const isNodejs = typeof window === "undefined";
if (isNodejs) {
// make the tests runnable in both the browser and Node.js
await import("./node-imports.js");
}
const { expect } = chai;
const URL = "http://localhost:3000";
const WS_URL = URL.replace("http", "ws");
const PING_INTERVAL = 300;
const PING_TIMEOUT = 200;
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
function waitFor(socket, eventType) {
return new Promise((resolve) => {
socket.addEventListener(
eventType,
(event) => {
resolve(event);
},
{ once: true }
);
});
}
function decodePayload(payload) {
const firstColonIndex = payload.indexOf(":");
const length = payload.substring(0, firstColonIndex);
const packet = payload.substring(firstColonIndex + 1);
return [length, packet];
}
async function initLongPollingSession(supportsBinary = false) {
const response = await fetch(`${URL}/engine.io/?EIO=3&transport=polling` + (supportsBinary ? "" : "&b64=1"));
const text = await response.text();
const [, content] = decodePayload(text);
return JSON.parse(content.substring(1)).sid;
}
describe("Engine.IO protocol", () => {
describe("handshake", () => {
describe("HTTP long-polling", () => {
it("successfully opens a session", async () => {
const response = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling`
);
expect(response.status).to.eql(200);
const text = await response.text();
const [length, content] = decodePayload(text);
expect(length).to.eql(content.length.toString());
expect(content).to.startsWith("0");
const value = JSON.parse(content.substring(1));
expect(value.sid).to.be.a("string");
expect(value.upgrades).to.eql(["websocket"]);
expect(value.pingInterval).to.eql(PING_INTERVAL);
expect(value.pingTimeout).to.eql(PING_TIMEOUT);
expect(value.maxPayload).to.be.oneOf([undefined, 1000000]);
});
it("fails with an invalid 'transport' query parameter", async () => {
const response = await fetch(`${URL}/engine.io/?EIO=3`);
expect(response.status).to.eql(400);
const response2 = await fetch(`${URL}/engine.io/?EIO=3&transport=abc`);
expect(response2.status).to.eql(400);
});
it("fails with an invalid request method", async () => {
const response = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling`,
{
method: "post",
}
);
expect(response.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("successfully opens a session", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("0");
const value = JSON.parse(data.substring(1));
expect(value.sid).to.be.a("string");
expect(value.upgrades).to.eql([]);
expect(value.pingInterval).to.eql(PING_INTERVAL);
expect(value.pingTimeout).to.eql(PING_TIMEOUT);
expect(value.maxPayload).to.be.oneOf([undefined, 1000000]);
socket.close();
});
it("fails with an invalid 'EIO' query parameter", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?transport=websocket`
);
if (isNodejs) {
socket.on("error", () => {});
}
waitFor(socket, "close");
const socket2 = new WebSocket(
`${WS_URL}/engine.io/?EIO=abc&transport=websocket`
);
if (isNodejs) {
socket2.on("error", () => {});
}
waitFor(socket2, "close");
});
it("fails with an invalid 'transport' query parameter", async () => {
const socket = new WebSocket(`${WS_URL}/engine.io/?EIO=3`);
if (isNodejs) {
socket.on("error", () => {});
}
waitFor(socket, "close");
const socket2 = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=abc`
);
if (isNodejs) {
socket2.on("error", () => {});
}
waitFor(socket2, "close");
});
});
});
describe("message", () => {
describe("HTTP long-polling", () => {
it("sends and receives a payload containing one plain text packet", async () => {
const sid = await initLongPollingSession();
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "6:4hello",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("6:4hello");
});
it("sends and receives a payload containing several plain text packets", async () => {
const sid = await initLongPollingSession();
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "6:4test16:4test26:4test3",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("6:4test16:4test26:4test3");
});
it("sends and receives a payload containing plain text and binary packets (base64 encoded)", async () => {
const sid = await initLongPollingSession();
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "6:4hello10:b4AQIDBA==",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("6:4hello10:b4AQIDBA==");
});
it("sends and receives a payload containing plain text and binary packets (binary)", async () => {
const sid = await initLongPollingSession(true);
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "6:4hello10:b4AQIDBA==",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const buffer = await pollResponse.arrayBuffer();
// 0 => string
// 6 => byte length
// 255 => delimiter
// 52 => 4 (MESSAGE packet type)
// 104 101 108 108 111 => "hello"
// 1 => binary
// 5 => byte length
// 255 => delimiter
// 4 => 4 (MESSAGE packet type)
// 1 2 3 4 => binary message
expect(buffer).to.eql(Uint8Array.from([0, 6, 255, 52, 104, 101, 108, 108, 111, 1, 5, 255, 4, 1, 2, 3, 4]).buffer);
});
it("closes the session upon invalid packet format", async () => {
const sid = await initLongPollingSession();
try {
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "abc",
}
);
expect(pushResponse.status).to.eql(400);
} catch (e) {
// node-fetch throws when the request is closed abnormally
}
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
});
// FIXME CORS error
it.skip("closes the session upon duplicate poll requests", async () => {
const sid = await initLongPollingSession();
const pollResponses = await Promise.all([
fetch(`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`),
sleep(5).then(() => fetch(`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}&t=burst`)),
]);
expect(pollResponses[0].status).to.eql(200);
const content = await pollResponses[0].text();
expect(content).to.eql("1:1");
// the Node.js implementation uses HTTP 500 (Internal Server Error), but HTTP 400 seems more suitable
expect(pollResponses[1].status).to.be.oneOf([400, 500]);
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(500);
});
});
describe("WebSocket", () => {
it("sends and receives a plain text packet", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
await waitFor(socket, "open");
await waitFor(socket, "message"); // handshake
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
socket.close();
});
it("sends and receives a binary packet", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
socket.binaryType = "arraybuffer";
await waitFor(socket, "message"); // handshake
socket.send(Uint8Array.from([4, 1, 2, 3, 4]));
const { data } = await waitFor(socket, "message");
expect(data).to.eql(Uint8Array.from([4, 1, 2, 3, 4]).buffer);
socket.close();
});
it("closes the session upon invalid packet format", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
await waitFor(socket, "message"); // handshake
socket.send("abc");
await waitFor(socket, "close");
socket.close();
});
});
});
describe("heartbeat", function () {
this.timeout(5000);
describe("HTTP long-polling", () => {
it("sends ping/pong packets", async () => {
const sid = await initLongPollingSession();
for (let i = 0; i < 3; i++) {
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "1:2",
}
);
expect(pushResponse.status).to.eql(200);
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("1:3");
}
});
it("closes the session upon ping timeout", async () => {
const sid = await initLongPollingSession();
await sleep(PING_INTERVAL + PING_TIMEOUT);
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`,
{
method: "post",
body: "1:2",
}
);
expect(pushResponse.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("sends ping/pong packets", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
const x = await waitFor(socket, "message"); // handshake
for (let i = 0; i < 3; i++) {
socket.send("2");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("3");
}
socket.close();
});
it("closes the session upon ping timeout", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
await waitFor(socket, "close"); // handshake
});
});
});
describe("close", () => {
describe("HTTP long-polling", () => {
it("forcefully closes the session", async () => {
const sid = await initLongPollingSession();
const [pollResponse] = await Promise.all([
fetch(`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`),
fetch(`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`, {
method: "post",
body: "1:1",
}),
]);
expect(pollResponse.status).to.eql(200);
const pullContent = await pollResponse.text();
expect(pullContent).to.eql("1:6");
const pollResponse2 = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse2.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("forcefully closes the session", async () => {
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket`
);
await waitFor(socket, "message"); // handshake
socket.send("1");
await waitFor(socket, "close");
});
});
});
describe("upgrade", () => {
it("successfully upgrades from HTTP long-polling to WebSocket", async () => {
const sid = await initLongPollingSession();
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
// send probe
socket.send("2probe");
const probeResponse = await waitFor(socket, "message");
expect(probeResponse.data).to.eql("3probe");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("1:6"); // "noop" packet to cleanly end the HTTP long-polling request
// complete upgrade
socket.send("5");
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
});
it("ignores HTTP requests with same sid after upgrade", async () => {
const sid = await initLongPollingSession();
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
const res = await waitFor(socket, "message");
expect(res.data).to.eql("3probe");
socket.send("5");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=3&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
});
it("ignores WebSocket connection with same sid after upgrade", async () => {
const sid = await initLongPollingSession();
const socket = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
const res = await waitFor(socket, "message");
expect(res.data).to.eql("3probe");
socket.send("5");
const socket2 = new WebSocket(
`${WS_URL}/engine.io/?EIO=3&transport=websocket&sid=${sid}`
);
await waitFor(socket2, "close");
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
});
});
});
================================================
FILE: docs/engine.io-protocol/v3.md
================================================
# Engine.IO Protocol
This document describes the Engine.IO protocol. For a reference JavaScript
implementation, take a look at
[engine.io-parser](https://github.com/learnboost/engine.io-parser),
[engine.io-client](https://github.com/learnboost/engine.io-client)
and [engine.io](https://github.com/learnboost/engine.io).
Table of Contents:
- [Revision](#revision)
- [Anatomy of an Engine.IO session](#anatomy-of-an-engineio-session)
- [Sample session](#sample-session)
- [Sample session with WebSocket only](#sample-session-with-websocket-only)
- [URLs](#urls)
- [Encoding](#encoding)
- [Packet](#packet)
- [0 open](#0-open)
- [1 close](#1-close)
- [2 ping](#2-ping)
- [3 pong](#3-pong)
- [4 message](#4-message)
- [5 upgrade](#5-upgrade)
- [6 noop](#6-noop)
- [Payload](#payload)
- [Transports](#transports)
- [Polling](#polling)
- [XHR](#xhr)
- [JSONP](#jsonp)
- [WebSocket](#websocket)
- [Transport upgrading](#transport-upgrading)
- [Timeouts](#timeouts)
- [Difference between v2 and v3](#difference-between-v2-and-v3)
- [Test suite](#test-suite)
## Revision
This is revision **3** of the Engine.IO protocol.
The revision 2 can be found here: https://github.com/socketio/engine.io-protocol/tree/v2
## Anatomy of an Engine.IO session
1. Transport establishes a connection to the Engine.IO URL .
2. Server responds with an `open` packet with JSON-encoded handshake data:
- `sid` session id (`String`)
- `upgrades` possible transport upgrades (`Array` of `String`)
- `pingTimeout` server configured ping timeout, used for the client
to detect that the server is unresponsive (`Number`)
- `pingInterval` server configured ping interval, used for the client
to detect that the server is unresponsive (`Number`)
3. Server must respond to periodic `ping` packets sent by the client
with `pong` packets.
4. Client and server can exchange `message` packets at will.
5. Polling transports can send a `close` packet to close the socket, since
they're expected to be "opening" and "closing" all the time.
### Sample session
- Request n°1 (open packet)
```
GET /engine.io/?EIO=3&transport=polling&t=N8hyd6w
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
96:0{"sid":"lv_VI97HAXpY6yYWAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
```
Details:
```
96 => number of characters (not bytes)
: => separator
0 => "open" packet type
{"sid":... => the handshake data
```
Note: the `t` query param is used to ensure that the request is not cached by the browser.
- Request n°2 (message in):
`socket.send('hey')` is executed on the server:
```
GET /engine.io/?EIO=3&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
4:4hey
```
Details:
```
4 => number of characters
: => separator
4 => "message" packet type
hey => the actual message
```
- Request n°3 (message out)
`socket.send('hello'); socket.send('world');` is executed on the client:
```
POST /engine.io/?EIO=3&transport=polling&t=N8hzxke&sid=lv_VI97HAXpY6yYWAAAC
> Content-Type: text/plain; charset=UTF-8
6:4hello6:4world
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
ok
```
Details:
```
6 => number of characters of the 1st packet
: => separator
4 => "message" packet type
hello => the 1st message
6 => number of characters of the 2nd packet
: => separator
4 => "message" message type
world => the 2nd message
```
- Request n°4 (WebSocket upgrade)
```
GET /engine.io/?EIO=3&transport=websocket&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 101 Switching Protocols
```
WebSocket frames:
```
< 2probe => probe request
> 3probe => probe response
> 5 => "upgrade" packet type
> 4hello => message (not concatenated)
> 4world
> 2 => "ping" packet type
< 3 => "pong" packet type
> 1 => "close" packet type
```
### Sample session with WebSocket only
In that case, the client only enables WebSocket (without HTTP polling).
```
GET /engine.io/?EIO=3&transport=websocket
< HTTP/1.1 101 Switching Protocols
```
WebSocket frames:
```
< 0{"sid":"lv_VI97HAXpY6yYWAAAC","pingInterval":25000,"pingTimeout":5000} => handshake
< 4hey
> 4hello => message (not concatenated)
> 4world
< 2 => "ping" packet type
> 3 => "pong" packet type
> 1 => "close" packet type
```
## URLs
An Engine.IO url is composed as follows:
```
/engine.io/[?<query string>]
```
- The `engine.io` pathname should only be changed by higher-level
frameworks whose protocol sits on top of engine's.
- The query string is optional and has six reserved keys:
- `transport`: indicates the transport name. Supported ones by default are
`polling`, `websocket`.
- `j`: if the transport is `polling` but a JSONP response is required, `j`
must be set with the JSONP response index.
- `sid`: if the client has been given a session id, it must be included
in the querystring.
- `b64`: if the client doesn't support XHR2, `b64=1` is sent in the query string
to signal the server that all binary data should be sent base64 encoded.
- `EIO`: the version of the protocol
- `t`: a hashed-timestamp used for cache-busting
*FAQ:* Is the `/engine.io` portion modifiable?
Provided the server is customized to intercept requests under a different
path segment, yes.
*FAQ:* What determines whether an option is going to be part of the path
versus being encoded as part of the query string? In other words, why
is the `transport` not part of the URL?
It's convention that the path segments remain *only* that which allows to
disambiguate whether a request should be handled by a given Engine.IO
server instance or not. As it stands, it's only the Engine.IO prefix
(`/engine.io`) and the resource (`default` by default).
## Encoding
There's two distinct types of encodings
- packet
- payload
### Packet
An encoded packet can be UTF-8 string or binary data. The packet encoding format for a string is as follows
```
<packet type id>[<data>]
```
example:
```
2probe
```
For binary data the encoding is identical. When sending binary data, the packet
type id is sent in the first byte of the binary contents, followed by the
actual packet data. Example:
```
4|0|1|2|3|4|5
```
In the above example each byte is separated by a pipe character and shown as an
integer. So the above packet is of type message (see below), and contains
binary data that corresponds to an array of integers with values 0, 1, 2, 3, 4
and 5.
The packet type id is an integer. The following are the accepted packet
types.
#### 0 open
Sent from the server when a new transport is opened (recheck)
#### 1 close
Request the close of this transport but does not shutdown the connection itself.
#### 2 ping
Sent by the client. Server should answer with a pong packet containing the same data
example
1. client sends: ```2probe```
2. server sends: ```3probe```
#### 3 pong
Sent by the server to respond to ping packets.
#### 4 message
actual message, client and server should call their callbacks with the data.
##### example 1
1. server sends: ```4HelloWorld```
2. client receives and calls callback ```socket.on('message', function (data) { console.log(data); });```
##### example 2
1. client sends: ```4HelloWorld```
2. server receives and calls callback ```socket.on('message', function (data) { console.log(data); });```
#### 5 upgrade
Before engine.io switches a transport, it tests, if server and client can communicate over this transport.
If this test succeed, the client sends an upgrade packets which requests the server to flush its cache on
the old transport and switch to the new transport.
#### 6 noop
A noop packet. Used primarily to force a poll cycle when an incoming websocket connection is received.
##### example
1. client connects through new transport
2. client sends ```2probe```
3. server receives and sends ```3probe```
4. client receives and sends ```5```
5. server flushes and closes old transport and switches to new.
### Payload
A payload is a series of encoded packets tied together. The payload encoding format is as follows when only strings are sent and XHR2 is not supported:
```
<length1>:<packet1>[<length2>:<packet2>[...]]
```
* length: length of the packet in __characters__
* packet: actual packets as descriped above
When XHR2 is not supported, the same encoding principle is used also when
binary data is sent, but it is sent as base64 encoded strings. For the purposes of decoding, an identifier `b` is
put before a packet encoding that contains binary data. A combination of any
number of strings and base64 encoded strings can be sent. Here is an example of
base 64 encoded messages:
```
<length of base64 representation of the data + 1 (for packet type)>:b<packet1 type><packet1 data in b64>[...]
```
When XHR2 is supported, a similar principle is used, but everything is encoded
directly into binary, so that it can be sent as binary over XHR. The format is
the following:
```
<0 for string data, 1 for binary data><Any number of numbers between 0 and 9><The number 255><packet1 (first type,
then data)>[...]
```
If a combination of UTF-8 strings and binary data is sent, the string values
are represented so that each character is written as a character code into a
byte.
The payload is used for transports which do not support framing, as the polling protocol for example.
- Example without binary:
```
[
{
"type": "message",
"data": "hello"
},
{
"type": "message",
"data": "€"
}
]
```
is encoded to:
```
6:4hello2:4€
```
Please note that we are not counting bytes, but characters, hence 2 (1 + 1) instead of 4 (1 + 3).
- Example with binary (both the client and the transport support binary):
```
[
{
"type": "message",
"data": "€"
},
{
"type": "message",
"data": buffer <01 02 03 04>
}
]
```
is encoded to:
```
buffer <00 04 ff 34 e2 82 ac 01 04 ff 01 02 03 04>
with:
00 => string header
04 => string length in bytes
ff => separator
34 => "message" packet type ("4")
e2 82 ac => "€"
01 => binary header
04 => buffer length in bytes
ff => separator
01 02 03 04 => buffer content
```
- Example with binary (either the client or the transport does not support binary):
```
[
{
"type": "message",
"data": "€"
},
{
"type": "message",
"data": buffer <01 02 03 04>
}
]
```
is encoded to:
```
2:4€10:b4AQIDBA==
with
2 => number of characters of the 1st packet
: => separator
4 => "message" packet type
€
10 => number of characters of the 2nd packet
: => separator
b => indicates a base64 packet
4 => "message" packet type
AQIDBA== => buffer content encoded in base64
```
## Transports
An engine.io server must support three transports:
- websocket
- polling
- jsonp
- xhr
### Polling
The polling transport consists of recurring GET requests by the client
to the server to get data, and POST requests with payloads from the
client to the server to send data.
#### XHR
The server must support CORS responses.
#### JSONP
The server implementation must respond with valid JavaScript. The URL
contains a query string parameter `j` that must be used in the response.
`j` is an integer.
The format of a JSONP packet.
```
`___eio[` <j> `]("` <encoded payload> `");`
```
To ensure that the payload gets processed correctly, it must be escaped
in such a way that the response is still valid JavaScript. Passing the
encoded payload through a JSON encoder is a good way to escape it.
Example JSONP frame returned by the server:
```
___eio[4]("packet data");
```
##### Posting data
The client posts data through a hidden iframe. The data gets to the server
in the URI encoded format as follows:
```
d=<escaped packet payload>
```
In addition to the regular qs escaping, in order to prevent
inconsistencies with `\n` handling by browsers, `\n` gets escaped as `\\n`
prior to being POSTd.
### WebSocket
Encoding payloads _should not_ be used for WebSocket, as the protocol
already has a lightweight framing mechanism.
In order to send a payload of messages, encode packets individually
and `send()` them in succession.
## Transport upgrading
A connection always starts with polling (either XHR or JSONP). WebSocket
gets tested on the side by sending a probe. If the probe is responded
from the server, an upgrade packet is sent.
To ensure no messages are lost, the upgrade packet will only be sent
once all the buffers of the existing transport are flushed and the
transport is considered _paused_.
When the server receives the upgrade packet, it must assume this is the
new transport channel and send all existing buffers (if any) to it.
The probe sent by the client is a `ping` packet with `probe` sent as data.
The probe sent by the server is a `pong` packet with `probe` sent as data.
Moving forward, upgrades other than just `polling -> x` are being considered.
## Timeouts
The client must use the `pingTimeout` and the `pingInterval` sent as part
of the handshake (with the `open` packet) to determine whether the server
is unresponsive.
The client sends a `ping` packet. If no packet type is received within
`pingTimeout`, the client considers the socket disconnected. If a `pong`
packet is actually received, the client will wait `pingInterval` before
sending a `ping` packet again.
Since the two values are shared between the server and the client, the server
will also be able to detect whether the client becomes unresponsive when it
does not receive any data within `pingTimeout + pingInterval`.
## Difference between v2 and v3
- add support for binary data
v2 is included in Socket.IO v0.9, while v3 is included in Socket.IO v1/v2.
## Test suite
The test suite in the `test-suite/` directory lets you check the compliance of a server implementation.
Usage:
- in Node.js: `npm ci && npm test`
- in a browser: simply open the `index.html` file in your browser
For reference, here is expected configuration for the JavaScript server to pass all tests:
```js
import { listen } from "engine.io";
const server = listen(3000, {
pingInterval: 300,
pingTimeout: 200,
allowEIO3: true,
maxPayload: 1e6,
cors: {
origin: "*"
}
});
server.on("connection", socket => {
socket.on("data", (...args) => {
socket.send(...args);
});
});
```
================================================
FILE: docs/engine.io-protocol/v4-current.md
================================================
# Engine.IO Protocol
This document describes the 4th version of the Engine.IO protocol.
**Table of content**
- [Introduction](#introduction)
- [Transports](#transports)
- [HTTP long-polling](#http-long-polling)
- [Request path](#request-path)
- [Query parameters](#query-parameters)
- [Headers](#headers)
- [Sending and receiving data](#sending-and-receiving-data)
- [Sending data](#sending-data)
- [Receiving data](#receiving-data)
- [WebSocket](#websocket)
- [Protocol](#protocol)
- [Handshake](#handshake)
- [Heartbeat](#heartbeat)
- [Upgrade](#upgrade)
- [Message](#message)
- [Packet encoding](#packet-encoding)
- [HTTP long-polling](#http-long-polling-1)
- [WebSocket](#websocket-1)
- [History](#history)
- [From v2 to v3](#from-v2-to-v3)
- [From v3 to v4](#from-v3-to-v4)
- [Test suite](#test-suite)
## Introduction
The Engine.IO protocol enables [full-duplex](https://en.wikipedia.org/wiki/Duplex_(telecommunications)#FULL-DUPLEX) and low-overhead communication between a client and a server.
It is based on the [WebSocket protocol](https://en.wikipedia.org/wiki/WebSocket) and uses [HTTP long-polling](https://en.wikipedia.org/wiki/Push_technology#Long_polling) as fallback if the WebSocket connection can't be established.
The reference implementation is written in [TypeScript](https://www.typescriptlang.org/):
- server: https://github.com/socketio/engine.io
- client: https://github.com/socketio/engine.io-client
The [Socket.IO protocol](https://github.com/socketio/socket.io-protocol) is built on top of these foundations, bringing additional features over the communication channel provided by the Engine.IO protocol.
## Transports
The connection between an Engine.IO client and an Engine.IO server can be established with:
- [HTTP long-polling](#http-long-polling)
- [WebSocket](#websocket)
### HTTP long-polling
The HTTP long-polling transport (also simply referred as "polling") consists of successive HTTP requests:
- long-running `GET` requests, for receiving data from the server
- short-running `POST` requests, for sending data to the server
#### Request path
The path of the HTTP requests is `/engine.io/` by default.
It might be updated by libraries built on top of the protocol (for example, the Socket.IO protocol uses `/socket.io/`).
#### Query parameters
The following query parameters are used:
| Name | Value | Description |
|-------------|-----------|--------------------------------------------------------------------|
| `EIO` | `4` | Mandatory, the version of the protocol. |
| `transport` | `polling` | Mandatory, the name of the transport. |
| `sid` | `<sid>` | Mandatory once the session is established, the session identifier. |
If a mandatory query parameter is missing, then the server MUST respond with an HTTP 400 error status.
#### Headers
When sending binary data, the sender (client or server) MUST include a `Content-Type: application/octet-stream` header.
Without an explicit `Content-Type` header, the receiver SHOULD infer that the data is plaintext.
Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
#### Sending and receiving data
##### Sending data
To send some packets, a client MUST create an HTTP `POST` request with the packets encoded in the request body:
```
CLIENT SERVER
│ │
│ POST /engine.io/?EIO=4&transport=polling&sid=... │
│ ───────────────────────────────────────────────────► │
│ ◄──────────────────────────────────────────────────┘ │
│ HTTP 200 │
│ │
```
The server MUST return an HTTP 400 response if the session ID (from the `sid` query parameter) is not known.
To indicate success, the server MUST return an HTTP 200 response, with the string `ok` in the response body.
To ensure packet ordering, a client MUST NOT have more than one active `POST` request. Should it happen, the server MUST return an HTTP 400 error status and close the session.
##### Receiving data
To receive some packets, a client MUST create an HTTP `GET` request:
```
CLIENT SERVER
│ GET /engine.io/?EIO=4&transport=polling&sid=... │
│ ──────────────────────────────────────────────────► │
│ . │
│ . │
│ . │
│ . │
│ ◄─────────────────────────────────────────────────┘ │
│ HTTP 200 │
```
The server MUST return an HTTP 400 response if the session ID (from the `sid` query parameter) is not known.
The server MAY not respond right away if there are no packets buffered for the given session. Once there are some packets to be sent, the server SHOULD encode them (see [Packet encoding](#packet-encoding)) and send them in the response body of the HTTP request.
To ensure packet ordering, a client MUST NOT have more than one active `GET` request. Should it happen, the server MUST return an HTTP 400 error status and close the session.
### WebSocket
The WebSocket transport consists of a [WebSocket connection](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API), which provides a bidirectional and low-latency communication channel between the server and the client.
The following query parameters are used:
| Name | Value | Description |
|-------------|-------------|-------------------------------------------------------------------------------|
| `EIO` | `4` | Mandatory, the version of the protocol. |
| `transport` | `websocket` | Mandatory, the name of the transport. |
| `sid` | `<sid>` | Optional, depending on whether it's an upgrade from HTTP long-polling or not. |
If a mandatory query parameter is missing, then the server MUST close the WebSocket connection.
Each packet (read or write) is sent its own [WebSocket frame](https://datatracker.ietf.org/doc/html/rfc6455#section-5).
A client MUST NOT open more than one WebSocket connection per session. Should it happen, the server MUST close the WebSocket connection.
## Protocol
An Engine.IO packet consists of:
- a packet type
- an optional packet payload
Here is the list of available packet types:
| Type | ID | Usage |
|---------|-----|--------------------------------------------------|
| open | 0 | Used during the [handshake](#handshake). |
| close | 1 | Used to indicate that a transport can be closed. |
| ping | 2 | Used in the [heartbeat mechanism](#heartbeat). |
| pong | 3 | Used in the [heartbeat mechanism](#heartbeat). |
| message | 4 | Used to send a payload to the other side. |
| upgrade | 5 | Used during the [upgrade process](#upgrade). |
| noop | 6 | Used during the [upgrade process](#upgrade). |
### Handshake
To establish a connection, the client MUST send an HTTP `GET` request to the server:
- HTTP long-polling first (by default)
```
CLIENT SERVER
│ │
│ GET /engine.io/?EIO=4&transport=polling │
│ ───────────────────────────────────────────────────────► │
│ ◄──────────────────────────────────────────────────────┘ │
│ HTTP 200 │
│ │
```
- WebSocket-only session
```
CLIENT SERVER
│ │
│ GET /engine.io/?EIO=4&transport=websocket │
│ ───────────────────────────────────────────────────────► │
│ ◄──────────────────────────────────────────────────────┘ │
│ HTTP 101 │
│ │
```
If the server accepts the connection, then it MUST respond with an `open` packet with the following JSON-encoded payload:
| Key | Type | Description |
|----------------|------------|-------------------------------------------------------------------------------------------------------------------|
| `sid` | `string` | The session ID. |
| `upgrades` | `string[]` | The list of available [transport upgrades](#upgrade). |
| `pingInterval` | `number` | The ping interval, used in the [heartbeat mechanism](#heartbeat) (in milliseconds). |
| `pingTimeout` | `number` | The ping timeout, used in the [heartbeat mechanism](#heartbeat) (in milliseconds). |
| `maxPayload` | `number` | The maximum number of bytes per chunk, used by the client to aggregate packets into [payloads](#packet-encoding). |
Example:
```json
{
"sid": "lv_VI97HAXpY6yYWAAAC",
"upgrades": ["websocket"],
"pingInterval": 25000,
"pingTimeout": 20000,
"maxPayload": 1000000
}
```
The client MUST send the `sid` value in the query parameters of all subsequent requests.
### Heartbeat
Once the [handshake](#handshake) is completed, a heartbeat mechanism is started to check the liveness of the connection:
```
CLIENT SERVER
│ *** Handshake *** │
│ │
│ ◄───────────────────────────────────────────────── │
│ 2 │ (ping packet)
│ ─────────────────────────────────────────────────► │
│ 3 │ (pong packet)
```
At a given interval (the `pingInterval` value sent in the handshake) the server sends a `ping` packet and the client has a few seconds (the `pingTimeout` value) to send a `pong` packet back.
If the server does not receive a `pong` packet back, then it SHOULD consider that the connection is closed.
Conversely, if the client does not receive a `ping` packet within `pingInterval + pingTimeout`, then it SHOULD consider that the connection is closed.
### Upgrade
By default, the client SHOULD create an HTTP long-polling connection, and then upgrade to better transports if available.
To upgrade to WebSocket, the client MUST:
- pause the HTTP long-polling transport (no more HTTP request gets sent), to ensure that no packet gets lost
- open a WebSocket connection with the same session ID
- send a `ping` packet with the string `probe` in the payload
The server MUST:
- send a `noop` packet to any pending `GET` request (if applicable) to cleanly close HTTP long-polling transport
- respond with a `pong` packet with the string `probe` in the payload
Finally, the client MUST send a `upgrade` packet to complete the upgrade:
```
CLIENT SERVER
│ │
│ GET /engine.io/?EIO=4&transport=websocket&sid=... │
│ ───────────────────────────────────────────────────► │
│ ◄─────────────────────────────────────────────────┘ │
│ HTTP 101 (WebSocket handshake) │
│ │
│ ----- WebSocket frames ----- │
│ ─────────────────────────────────────────────────► │
│ 2probe │ (ping packet)
│ ◄───────────────────────────────────────────────── │
│ 3probe │ (pong packet)
│ ─────────────────────────────────────────────────► │
│ 5 │ (upgrade packet)
│ │
```
### Message
Once the [handshake](#handshake) is completed, the client and the server can exchange data by including it in a `message` packet.
## Packet encoding
The serialization of an Engine.IO packet depends on the type of the payload (plaintext or binary) and on the transport.
The character encoding is UTF-8 for plain text and for base64-encoded binary payloads.
### HTTP long-polling
Due to the nature of the HTTP long-polling transport, multiple packets might be concatenated in a single payload in order to increase throughput.
Format:
```
<packet type>[<data>]<separator><packet type>[<data>]<separator><packet type>[<data>][...]
```
Example:
```
4hello\x1e2\x1e4world
with:
4 => message packet type
hello => message payload
\x1e => separator
2 => ping packet type
\x1e => separator
4 => message packet type
world => message payload
```
The packets are separated by the [record separator character](https://en.wikipedia.org/wiki/C0_and_C1_control_codes#Field_separators): `\x1e`
Binary payloads MUST be base64-encoded and prefixed with a `b` character:
Example:
```
4hello\x1ebAQIDBA==
with:
4 => message packet type
hello => message payload
\x1e => separator
b => binary prefix
AQIDBA== => buffer <01 02 03 04> encoded as base64
```
The client SHOULD use the `maxPayload` value sent during the [handshake](#handshake) to decide how many packets should be concatenated.
### WebSocket
Each Engine.IO packet is sent in its own [WebSocket frame](https://datatracker.ietf.org/doc/html/rfc6455#section-5).
Format:
```
<packet type>[<data>]
```
Example:
```
4hello
with:
4 => message packet type
hello => message payload (UTF-8 encoded)
```
Binary payloads are sent as is, without modification.
## History
### From v2 to v3
- add support for binary data
The [2nd version](https://github.com/socketio/engine.io-protocol/tree/v2) of the protocol is used in Socket.IO `v0.9` and below.
The [3rd version](https://github.com/socketio/engine.io-protocol/tree/v3) of the protocol is used in Socket.IO `v1` and `v2`.
### From v3 to v4
- reverse ping/pong mechanism
The ping packets are now sent by the server, because the timers set in the browsers are not reliable enough. We
suspect that a lot of timeout problems came from timers being delayed on the client-side.
- always use base64 when encoding a payload with binary data
This change allows to treat all payloads (with or without binary) the same way, without having to take in account
whether the client or the current transport supports binary data or not.
Please note that this only applies to HTTP long-polling. Binary data is sent in WebSocket frames with no additional transformation.
- use a record separator (`\x1e`) instead of counting of characters
Counting characters prevented (or at least makes harder) to implement the protocol in other languages, which may not use
the UTF-16 encoding.
For example, `€` was encoded to `2:4€`, though `Buffer.byteLength('€') === 3`.
Note: this assumes the record separator is not used in the data.
The 4th version (current) is included in Socket.IO `v3` and above.
## Test suite
The test suite in the `test-suite/` directory lets you check the compliance of a server implementation.
Usage:
- in Node.js: `npm ci && npm test`
- in a browser: simply open the `index.html` file in your browser
For reference, here is expected configuration for the JavaScript server to pass all tests:
```js
import { listen } from "engine.io";
const server = listen(3000, {
pingInterval: 300,
pingTimeout: 200,
maxPayload: 1e6,
cors: {
origin: "*"
}
});
server.on("connection", socket => {
socket.on("data", (...args) => {
socket.send(...args);
});
});
```
================================================
FILE: docs/engine.io-protocol/v4-test-suite/.gitignore
================================================
node_modules
================================================
FILE: docs/engine.io-protocol/v4-test-suite/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test suite for the Engine.IO protocol</title>
<link rel="stylesheet" href="https://unpkg.com/mocha@9/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="https://unpkg.com/mocha@9/mocha.js"></script>
<script src="https://unpkg.com/chai@4/chai.js" ></script>
<script src="https://unpkg.com/chai-string@1/chai-string.js" ></script>
<script class="mocha-init">
mocha.setup("bdd");
mocha.checkLeaks();
</script>
<script type="module" src="test-suite.js"></script>
<script class="mocha-exec">
mocha.run();
</script>
</body>
</html>
================================================
FILE: docs/engine.io-protocol/v4-test-suite/node-imports.js
================================================
import fetch from "node-fetch";
import { WebSocket } from "ws";
import chai from "chai";
import chaiString from "chai-string";
chai.use(chaiString);
globalThis.fetch = fetch;
globalThis.WebSocket = WebSocket;
globalThis.chai = chai;
================================================
FILE: docs/engine.io-protocol/v4-test-suite/package.json
================================================
{
"name": "engine.io-protocol-test-suite",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"format": "prettier -w *.js",
"test": "mocha test-suite.js"
},
"devDependencies": {
"chai": "^4.3.6",
"chai-string": "^1.5.0",
"mocha": "^9.2.1",
"node-fetch": "^3.2.0",
"prettier": "^2.5.1",
"ws": "^8.5.0"
}
}
================================================
FILE: docs/engine.io-protocol/v4-test-suite/test-suite.js
================================================
const isNodejs = typeof window === "undefined";
if (isNodejs) {
// make the tests runnable in both the browser and Node.js
await import("./node-imports.js");
}
const { expect } = chai;
const URL = "http://localhost:3000";
const WS_URL = URL.replace("http", "ws");
const PING_INTERVAL = 300;
const PING_TIMEOUT = 200;
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
function createWebSocket(url) {
const socket = new WebSocket(url);
socket._eventBuffer = {};
socket._pendingPromises = {};
for (const eventType of ["open", "close", "message"]) {
socket._eventBuffer[eventType] = [];
socket._pendingPromises[eventType] = [];
socket.addEventListener(eventType, (event) => {
if (socket._pendingPromises[eventType].length) {
socket._pendingPromises[eventType].shift()(event);
} else {
socket._eventBuffer[eventType].push(event);
}
});
}
return socket;
}
function waitFor(socket, eventType) {
if (socket._eventBuffer[eventType].length) {
return Promise.resolve(socket._eventBuffer[eventType].shift());
} else {
return new Promise((resolve) => {
socket._pendingPromises[eventType].push(resolve);
});
}
}
async function initLongPollingSession() {
const response = await fetch(`${URL}/engine.io/?EIO=4&transport=polling`);
const content = await response.text();
return JSON.parse(content.substring(1)).sid;
}
describe("Engine.IO protocol", () => {
describe("handshake", () => {
describe("HTTP long-polling", () => {
it("successfully opens a session", async () => {
const response = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling`
);
expect(response.status).to.eql(200);
const content = await response.text();
expect(content).to.startsWith("0");
const value = JSON.parse(content.substring(1));
expect(value).to.have.all.keys(
"sid",
"upgrades",
"pingInterval",
"pingTimeout",
"maxPayload"
);
expect(value.sid).to.be.a("string");
expect(value.upgrades).to.eql(["websocket"]);
expect(value.pingInterval).to.eql(PING_INTERVAL);
expect(value.pingTimeout).to.eql(PING_TIMEOUT);
expect(value.maxPayload).to.eql(1000000);
});
it("fails with an invalid 'EIO' query parameter", async () => {
const response = await fetch(`${URL}/engine.io/?transport=polling`);
expect(response.status).to.eql(400);
const response2 = await fetch(
`${URL}/engine.io/?EIO=abc&transport=polling`
);
expect(response2.status).to.eql(400);
});
it("fails with an invalid 'transport' query parameter", async () => {
const response = await fetch(`${URL}/engine.io/?EIO=4`);
expect(response.status).to.eql(400);
const response2 = await fetch(`${URL}/engine.io/?EIO=4&transport=abc`);
expect(response2.status).to.eql(400);
});
it("fails with an invalid request method", async () => {
const response = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling`,
{
method: "post",
}
);
expect(response.status).to.eql(400);
const response2 = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling`,
{
method: "put",
}
);
expect(response2.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("successfully opens a session", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("0");
const value = JSON.parse(data.substring(1));
expect(value).to.have.all.keys(
"sid",
"upgrades",
"pingInterval",
"pingTimeout",
"maxPayload"
);
expect(value.sid).to.be.a("string");
expect(value.upgrades).to.eql([]);
expect(value.pingInterval).to.eql(PING_INTERVAL);
expect(value.pingTimeout).to.eql(PING_TIMEOUT);
expect(value.maxPayload).to.eql(1000000);
socket.close();
});
it("fails with an invalid 'EIO' query parameter", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?transport=websocket`
);
if (isNodejs) {
socket.on("error", () => {});
}
await waitFor(socket, "close");
const socket2 = createWebSocket(
`${WS_URL}/engine.io/?EIO=abc&transport=websocket`
);
if (isNodejs) {
socket2.on("error", () => {});
}
await waitFor(socket2, "close");
});
it("fails with an invalid 'transport' query parameter", async () => {
const socket = createWebSocket(`${WS_URL}/engine.io/?EIO=4`);
if (isNodejs) {
socket.on("error", () => {});
}
await waitFor(socket, "close");
const socket2 = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=abc`
);
if (isNodejs) {
socket2.on("error", () => {});
}
await waitFor(socket2, "close");
});
});
});
describe("message", () => {
describe("HTTP long-polling", () => {
it("sends and receives a payload containing one plain text packet", async () => {
const sid = await initLongPollingSession();
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
{
method: "post",
body: "4hello",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("4hello");
});
it("sends and receives a payload containing several plain text packets", async () => {
const sid = await initLongPollingSession();
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
{
method: "post",
body: "4test1\x1e4test2\x1e4test3",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("4test1\x1e4test2\x1e4test3");
});
it("sends and receives a payload containing plain text and binary packets", async () => {
const sid = await initLongPollingSession();
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
{
method: "post",
body: "4hello\x1ebAQIDBA==",
}
);
expect(pushResponse.status).to.eql(200);
const postContent = await pushResponse.text();
expect(postContent).to.eql("ok");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("4hello\x1ebAQIDBA==");
});
it("closes the session upon invalid packet format", async () => {
const sid = await initLongPollingSession();
try {
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
{
method: "post",
body: "abc",
}
);
expect(pushResponse.status).to.eql(400);
} catch (e) {
// node-fetch throws when the request is closed abnormally
}
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
});
it("closes the session upon duplicate poll requests", async () => {
const sid = await initLongPollingSession();
const pollResponses = await Promise.all([
fetch(`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`),
sleep(5).then(() => fetch(`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}&t=burst`)),
]);
expect(pollResponses[0].status).to.eql(200);
const content = await pollResponses[0].text();
expect(content).to.eql("1");
// the Node.js implementation uses HTTP 500 (Internal Server Error), but HTTP 400 seems more suitable
expect(pollResponses[1].status).to.be.oneOf([400, 500]);
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
});
it("closes the session upon cancelled polling request", async () => {
const sid = await initLongPollingSession();
const controller = new AbortController();
fetch(`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`, {
signal: controller.signal,
}).catch(() => {});
await sleep(5);
controller.abort();
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
);
expect(pollResponse.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("sends and receives a plain text packet", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "open");
await waitFor(socket, "message"); // handshake
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
socket.close();
});
it("sends and receives a binary packet", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
socket.binaryType = "arraybuffer";
await waitFor(socket, "message"); // handshake
socket.send(Uint8Array.from([1, 2, 3, 4]));
const { data } = await waitFor(socket, "message");
expect(data).to.eql(Uint8Array.from([1, 2, 3, 4]).buffer);
socket.close();
});
it("closes the session upon invalid packet format", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // handshake
socket.send("abc");
await waitFor(socket, "close");
socket.close();
});
});
});
describe("heartbeat", function () {
this.timeout(5000);
describe("HTTP long-polling", () => {
it("sends ping/pong packets", async () => {
const sid = await initLongPollingSession();
for (let i = 0; i < 3; i++) {
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("2");
const pushResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`,
{
method: "post",
body: "3",
}
);
expect(pushResponse.status).to.eql(200);
}
});
it("closes the session upon ping timeout", async () => {
const sid = await initLongPollingSession();
await sleep(PING_INTERVAL + PING_TIMEOUT);
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("sends ping/pong packets", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // handshake
for (let i = 0; i < 3; i++) {
const { data } = await waitFor(socket, "message");
expect(data).to.eql("2");
socket.send("3");
}
socket.close();
});
it("closes the session upon ping timeout", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "close"); // handshake
});
});
});
describe("close", () => {
describe("HTTP long-polling", () => {
it("forcefully closes the session", async () => {
const sid = await initLongPollingSession();
const [pollResponse] = await Promise.all([
fetch(`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`),
fetch(`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`, {
method: "post",
body: "1",
}),
]);
expect(pollResponse.status).to.eql(200);
const pullContent = await pollResponse.text();
expect(pullContent).to.eql("6");
const pollResponse2 = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse2.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("forcefully closes the session", async () => {
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // handshake
socket.send("1");
await waitFor(socket, "close");
});
});
});
describe("upgrade", () => {
it("successfully upgrades from HTTP long-polling to WebSocket", async () => {
const sid = await initLongPollingSession();
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
// send probe
socket.send("2probe");
const probeResponse = await waitFor(socket, "message");
expect(probeResponse.data).to.eql("3probe");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("6"); // "noop" packet to cleanly end the HTTP long-polling request
// complete upgrade
socket.send("5");
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
});
it("ignores HTTP requests with same sid after upgrade", async () => {
const sid = await initLongPollingSession();
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
await waitFor(socket, "message"); // "3probe"
socket.send("5");
const pollResponse = await fetch(
`${URL}/engine.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
});
it("ignores WebSocket connection with same sid after upgrade", async () => {
const sid = await initLongPollingSession();
const socket = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
await waitFor(socket, "message"); // "3probe"
socket.send("5");
const socket2 = createWebSocket(
`${WS_URL}/engine.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket2, "close");
socket.send("4hello");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("4hello");
});
});
});
================================================
FILE: docs/socket.io-protocol/v3.md
================================================
# socket.io-protocol
This document describes the Socket.IO protocol. For a reference JavaScript
implementation, take a look at
[socket.io-parser](https://github.com/socketio/socket.io-parser),
[socket.io-client](https://github.com/socketio/socket.io-client)
and [socket.io](https://github.com/socketio/socket.io).
## Table of Contents
- [Protocol version](#protocol-version)
- [Packet format](#packet-format)
- [Packet types](#packet-types)
- [CONNECT](#0---connect)
- [DISCONNECT](#1---disconnect)
- [EVENT](#2---event)
- [ACK](#3---ack)
- [ERROR](#4---error)
- [BINARY_EVENT](#5---binary_event)
- [Packet encoding](#packet-encoding)
- [Encoding format](#encoding-format)
- [Examples](#examples)
- [Exchange protocol](#exchange-protocol)
- [Connection to the default namespace](#connection-to-the-default-namespace)
- [Connection to a non-default namespace](#connection-to-a-non-default-namespace)
- [Disconnection from a non-default namespace](#disconnection-from-a-non-default-namespace)
- [Acknowledgement](#acknowledgement)
- [History](#history)
- [Difference between v3 and v2](#difference-between-v3-and-v2)
- [Difference between v2 and v1](#difference-between-v2-and-v1)
- [Initial revision](#initial-revision)
## Protocol version
This is the revision **3** of the Socket.IO protocol, included in ̀`socket.io@1.0.0...1.0.2`.
The 4th revision (included in ̀`socket.io@1.0.3...latest`) can be found here: https://github.com/socketio/socket.io-protocol/tree/master
Both the 1st and the 2nd revisions were part of the work towards Socket.IO 1.0 but were never included in a Socket.IO
release.
It is built on top of the [3rd](https://github.com/socketio/engine.io-protocol/tree/v3) revision of the Engine.IO
protocol.
While the Engine.IO protocol describes the low-level plumbing with WebSocket and HTTP long-polling, the Socket.IO
protocol adds another layer above in order to provide the following features:
- multiplexing (what we call [Namespace](https://socket.io/docs/namespaces/))
Example of the Javascript API:
```js
// server-side
const nsp = io.of("/admin");
nsp.on("connect", socket => {});
// client-side
const socket1 = io(); // default namespace
const socket2 = io("/admin");
socket2.on("connect", () => {});
```
- acknowledgement of packets
Example of the Javascript API:
```js
// on one side
socket.emit("hello", 1, () => { console.log("received"); });
// on the other side
socket.on("hello", (a, cb) => { cb(); });
```
## Packet format
A packet contains the following fields:
- a type (integer, see [below](#packet-types))
- a namespace (string)
- optionally, a payload (string | Array)
- optionally, an acknowledgment id (integer)
## Packet types
### 0 - CONNECT
This event is sent:
- by the client when requesting access to a namespace
- by the server when accepting the connection to a namespace
It does not contain any payload nor acknowledgement id.
Example:
```json
{
"type": 0,
"nsp": "/admin"
}
```
The client may include additional information (i.e. for authentication purpose) in the namespace field. Example:
```json
{
"type": 0,
"nsp": "/admin?token=1234&uid=abcd"
}
```
#### 1 - DISCONNECT
This event is used when one side wants to disconnect from a namespace.
It does not contain any payload nor acknowledgement id.
Example:
```json
{
"type": 1,
"nsp": "/admin"
}
```
#### 2 - EVENT
This event is used when one side wants to transmit some data (without binary) to the other side.
It does contain a payload, and an optional acknowledgement id.
Example:
```json
{
"type": 2,
"nsp": "/",
"data": ["hello", 1]
}
```
With an acknowledgment id:
```json
{
"type": 2,
"nsp": "/admin",
"data": ["project:delete", 123],
"id": 456
}
```
#### 3 - ACK
This event is used when one side has received an EVENT or a BINARY_EVENT with an acknowledgement id.
It contains the acknowledgement id received in the previous packet, and may contain a payload (without binary).
```json
{
"type": 3,
"nsp": "/admin",
"data": [],
"id": 456
}
```
#### 4 - ERROR
This event is sent by the server when the connection to a namespace is refused.
It may contain a payload indicating the reason of the refusal.
Example:
```json
{
"type": 4,
"nsp": "/admin",
"data": "Not authorized"
}
```
#### 5 - BINARY_EVENT
This event is used when one side wants to transmit some data (including binary) to the other side.
It does contain a payload, and an optional acknowledgement id.
Example:
```
{
"type": 5,
"nsp": "/",
"data": ["hello", <Buffer 01 02 03>]
}
```
With an acknowledgment id:
```
{
"type": 5,
"nsp": "/admin",
"data": ["project:delete", <Buffer 01 02 03>],
"id": 456
}
```
## Packet encoding
This section details the encoding used by the default parser which is included in Socket.IO server and client, and
whose source can be found [here](https://github.com/socketio/socket.io-parser).
The JS server and client implementations also supports custom parsers, which have different tradeoffs and may benefit to
certain kind of applications. Please see [socket.io-json-parser](https://github.com/darrachequesne/socket.io-json-parser)
or [socket.io-msgpack-parser](https://github.com/darrachequesne/socket.io-msgpack-parser) for example.
Please also note that each Socket.IO packet is sent as a Engine.IO `message` packet (more information [here](https://github.com/socketio/engine.io-protocol)),
so the encoded result will be prefixed by `4` when sent over the wire (in the request/response body with HTTP
long-polling, or in the WebSocket frame).
### Encoding format
```
<packet type>[<# of binary attachments>-][<namespace>,][<acknowledgment id>][JSON-stringified payload without binary]
+ binary attachments extracted
```
Note:
- the namespace is only included if it is different from the default namespace (`/`)
### Examples
- `CONNECT` packet for the default namespace
```json
{
"type": 0,
"nsp": "/"
}
```
is encoded to `0`
- `CONNECT` packet for the `/admin` namespace
```json
{
"type": 0,
"nsp": "/admin"
}
```
is encoded to `0/admin`
- `DISCONNECT` packet for the `/admin` namespace
```json
{
"type": 1,
"nsp": "/admin"
}
```
is encoded to `1/admin`
- `EVENT` packet
```json
{
"type": 2,
"nsp": "/",
"data": ["hello", 1]
}
```
is encoded to `2["hello",1]`
- `EVENT` packet with an acknowledgement id
```json
{
"type": 2,
"nsp": "/admin",
"data": ["project:delete", 123],
"id": 456
}
```
is encoded to `2/admin,456["project:delete",123]`
- `ACK` packet
```json
{
"type": 3,
"nsp": "/admin",
"data": [],
"id": 456
}
```
is encoded to `3/admin,456[]`
- `ERROR` packet
```json
{
"type": 4,
"nsp": "/admin",
"data": "Not authorized"
}
```
is encoded to `4/admin,"Not authorized"`
- `BINARY_EVENT` packet
```
{
"type": 5,
"nsp": "/",
"data": ["hello", <Buffer 01 02 03>]
}
```
is encoded to `51-["hello",{"_placeholder":true,"num":0}]` + `<Buffer 01 02 03>`
- `BINARY_EVENT` packet with an acknowledgement id
```
{
"type": 5,
"nsp": "/admin",
"data": ["project:delete", <Buffer 01 02 03>],
"id": 456
}
```
is encoded to `51-/admin,456["project:delete",{"_placeholder":true,"num":0}]` + `<Buffer 01 02 03>`
## Exchange protocol
### Connection to the default namespace
The server always send a `CONNECT` packet for the default namespace (`/`) when the connection is established.
That is, even if the client requests access to a non-default namespace, it will receive a `CONNECT` packet for the
default namespace first.
```
Server > { type: CONNECT, nsp: "/" }
```
No response is expected from the client.
### Connection to a non-default namespace
```
Client > { type: CONNECT, nsp: "/admin" }
Server > { type: CONNECT, nsp: "/admin" } (if the connection is successful)
or
Server > { type: ERROR, nsp: "/admin", data: "Not authorized" }
```
### Disconnection from a non-default namespace
```
Client > { type: DISCONNECT, nsp: "/admin" }
```
And vice versa. No response is expected from the other-side.
### Acknowledgement
```
Client > { type: EVENT, nsp: "/admin", data: ["hello"], id: 456 }
Server > { type: ACK, nsp: "/admin", data: [], id: 456 }
```
And vice versa.
## History
### Difference between v3 and v2
- remove the usage of msgpack to encode packets containing binary objects (see also [299849b](https://github.com/socketio/socket.io-parser/commit/299849b00294c3bc95817572441f3aca8ffb1f65))
### Difference between v2 and v1
- add a BINARY_EVENT packet type
This was added during the work towards Socket.IO 1.0, in order to add support for binary objects. The BINARY_EVENT
packets were encoded with [msgpack](https://msgpack.org/).
### Initial revision
This first revision was the result of the split between the Engine.IO protocol (low-level plumbing with WebSocket / HTTP
long-polling, heartbeat) and the Socket.IO protocol. It was never included in a Socket.IO release, but paved the way for
the next iterations.
## License
MIT
================================================
FILE: docs/socket.io-protocol/v4.md
================================================
# socket.io-protocol
This document describes the Socket.IO protocol. For a reference JavaScript
implementation, take a look at
[socket.io-parser](https://github.com/socketio/socket.io-parser),
[socket.io-client](https://github.com/socketio/socket.io-client)
and [socket.io](https://github.com/socketio/socket.io).
## Table of Contents
- [Protocol version](#protocol-version)
- [Packet format](#packet-format)
- [Packet types](#packet-types)
- [CONNECT](#0---connect)
- [DISCONNECT](#1---disconnect)
- [EVENT](#2---event)
- [ACK](#3---ack)
- [ERROR](#4---error)
- [BINARY_EVENT](#5---binary_event)
- [BINARY_ACK](#6---binary_ack)
- [Packet encoding](#packet-encoding)
- [Encoding format](#encoding-format)
- [Examples](#examples)
- [Exchange protocol](#exchange-protocol)
- [Connection to the default namespace](#connection-to-the-default-namespace)
- [Connection to a non-default namespace](#connection-to-a-non-default-namespace)
- [Disconnection from a non-default namespace](#disconnection-from-a-non-default-namespace)
- [Acknowledgement](#acknowledgement)
- [Sample session](#sample-session)
- [History](#history)
- [Difference between v4 and v3](#difference-between-v4-and-v3)
- [Difference between v3 and v2](#difference-between-v3-and-v2)
- [Difference between v2 and v1](#difference-between-v2-and-v1)
- [Initial revision](#initial-revision)
## Protocol version
This is the revision **4** of the Socket.IO protocol, included in `socket.io@1.0.3...latest`.
The 3rd revision (included in `socket.io@1.0.0...1.0.2`) can be found here: https://github.com/socketio/socket.io-protocol/tree/v3
Both the 1st and the 2nd revisions were part of the work towards Socket.IO 1.0 but were never included in a Socket.IO
release.
It is built on top of the [3rd](https://github.com/socketio/engine.io-protocol/tree/v3) revision of the Engine.IO
protocol.
While the Engine.IO protocol describes the low-level plumbing with WebSocket and HTTP long-polling, the Socket.IO
protocol adds another layer above in order to provide the following features:
- multiplexing (what we call [Namespace](https://socket.io/docs/namespaces/))
Example of the Javascript API:
```js
// server-side
const nsp = io.of("/admin");
nsp.on("connect", socket => {});
// client-side
const socket1 = io(); // default namespace
const socket2 = io("/admin");
socket2.on("connect", () => {});
```
- acknowledgement of packets
Example of the Javascript API:
```js
// on one side
socket.emit("hello", 1, () => { console.log("received"); });
// on the other side
socket.on("hello", (a, cb) => { cb(); });
```
## Packet format
A packet contains the following fields:
- a type (integer, see [below](#packet-types))
- a namespace (string)
- optionally, a payload (string | Array)
- optionally, an acknowledgment id (integer)
## Packet types
### 0 - CONNECT
This event is sent:
- by the client when requesting access to a namespace
- by the server when accepting the connection to a namespace
It does not contain any payload nor acknowledgement id.
Example:
```json
{
"type": 0,
"nsp": "/admin"
}
```
The client may include additional information (i.e. for authentication purpose) in the namespace field. Example:
```json
{
"type": 0,
"nsp": "/admin?token=1234&uid=abcd"
}
```
#### 1 - DISCONNECT
This event is used when one side wants to disconnect from a namespace.
It does not contain any payload nor acknowledgement id.
Example:
```json
{
"type": 1,
"nsp": "/admin"
}
```
#### 2 - EVENT
This event is used when one side wants to transmit some data (without binary) to the other side.
It does contain a payload, and an optional acknowledgement id.
Example:
```json
{
"type": 2,
"nsp": "/",
"data": ["hello", 1]
}
```
With an acknowledgment id:
```json
{
"type": 2,
"nsp": "/admin",
"data": ["project:delete", 123],
"id": 456
}
```
#### 3 - ACK
This event is used when one side has received an EVENT or a BINARY_EVENT with an acknowledgement id.
It contains the acknowledgement id received in the previous packet, and may contain a payload (without binary).
```json
{
"type": 3,
"nsp": "/admin",
"data": [],
"id": 456
}
```
#### 4 - ERROR
This event is sent by the server when the connection to a namespace is refused.
It may contain a payload indicating the reason of the refusal.
Example:
```json
{
"type": 4,
"nsp": "/admin",
"data": "Not authorized"
}
```
#### 5 - BINARY_EVENT
This event is used when one side wants to transmit some data (including binary) to the other side.
It does contain a payload, and an optional acknowledgement id.
Example:
```
{
"type": 5,
"nsp": "/",
"data": ["hello", <Buffer 01 02 03>]
}
```
With an acknowledgment id:
```
{
"type": 5,
"nsp": "/admin",
"data": ["project:delete", <Buffer 01 02 03>],
"id": 456
}
```
#### 6 - BINARY_ACK
This event is used when one side has received an EVENT or a BINARY_EVENT with an acknowledgement id.
It contains the acknowledgement id received in the previous packet, and contain a payload including binary.
Example:
```
{
"type": 6,
"nsp": "/admin",
"data": [<Buffer 03 02 01>],
"id": 456
}
```
## Packet encoding
This section details the encoding used by the default parser which is included in Socket.IO server and client, and
whose source can be found [here](https://github.com/socketio/socket.io-parser).
The JS server and client implementations also supports custom parsers, which have different tradeoffs and may benefit to
certain kind of applications. Please see [socket.io-json-parser](https://github.com/darrachequesne/socket.io-json-parser)
or [socket.io-msgpack-parser](https://github.com/darrachequesne/socket.io-msgpack-parser) for example.
Please also note that each Socket.IO packet is sent as a Engine.IO `message` packet (more information [here](https://github.com/socketio/engine.io-protocol)),
so the encoded result will be prefixed by `4` when sent over the wire (in the request/response body with HTTP
long-polling, or in the WebSocket frame).
### Encoding format
```
<packet type>[<# of binary attachments>-][<namespace>,][<acknowledgment id>][JSON-stringified payload without binary]
+ binary attachments extracted
```
Note:
- the namespace is only included if it is different from the default namespace (`/`)
### Examples
- `CONNECT` packet for the default namespace
```json
{
"type": 0,
"nsp": "/"
}
```
is encoded to `0`
- `CONNECT` packet for the `/admin` namespace
```json
{
"type": 0,
"nsp": "/admin"
}
```
is encoded to `0/admin,`
- `DISCONNECT` packet for the `/admin` namespace
```json
{
"type": 1,
"nsp": "/admin"
}
```
is encoded to `1/admin,`
- `EVENT` packet
```json
{
"type": 2,
"nsp": "/",
"data": ["hello", 1]
}
```
is encoded to `2["hello",1]`
- `EVENT` packet with an acknowledgement id
```json
{
"type": 2,
"nsp": "/admin",
"data": ["project:delete", 123],
"id": 456
}
```
is encoded to `2/admin,456["project:delete",123]`
- `ACK` packet
```json
{
"type": 3,
"nsp": "/admin",
"data": [],
"id": 456
}
```
is encoded to `3/admin,456[]`
- `ERROR` packet
```json
{
"type": 4,
"nsp": "/admin",
"data": "Not authorized"
}
```
is encoded to `4/admin,"Not authorized"`
- `BINARY_EVENT` packet
```
{
"type": 5,
"nsp": "/",
"data": ["hello", <Buffer 01 02 03>]
}
```
is encoded to `51-["hello",{"_placeholder":true,"num":0}]` + `<Buffer 01 02 03>`
- `BINARY_EVENT` packet with an acknowledgement id
```
{
"type": 5,
"nsp": "/admin",
"data": ["project:delete", <Buffer 01 02 03>],
"id": 456
}
```
is encoded to `51-/admin,456["project:delete",{"_placeholder":true,"num":0}]` + `<Buffer 01 02 03>`
- `BINARY_ACK` packet
```
{
"type": 6,
"nsp": "/admin",
"data": [<Buffer 03 02 01>],
"id": 456
}
```
is encoded to `61-/admin,456[{"_placeholder":true,"num":0}]` + `<Buffer 03 02 01>`
## Exchange protocol
### Connection to the default namespace
The server always send a `CONNECT` packet for the default namespace (`/`) when the connection is established.
That is, even if the client requests access to a non-default namespace, it will receive a `CONNECT` packet for the
default namespace first.
```
Server > { type: CONNECT, nsp: "/" }
```
No response is expected from the client.
### Connection to a non-default namespace
```
Client > { type: CONNECT, nsp: "/admin" }
Server > { type: CONNECT, nsp: "/admin" } (if the connection is successful)
or
Server > { type: ERROR, nsp: "/admin", data: "Not authorized" }
```
### Disconnection from a non-default namespace
```
Client > { type: DISCONNECT, nsp: "/admin" }
```
And vice versa. No response is expected from the other-side.
### Acknowledgement
```
Client > { type: EVENT, nsp: "/admin", data: ["hello"], id: 456 }
Server > { type: ACK, nsp: "/admin", data: [], id: 456 }
or
Server > { type: BINARY_ACK, nsp: "/admin", data: [ <Buffer 01 02 03> ], id: 456 }
```
And vice versa.
## Sample session
Here is an example of what is sent over the wire when combining both the Engine.IO and the Socket.IO protocols.
- Request n°1 (open packet)
```
GET /socket.io/?EIO=3&transport=polling&t=N8hyd6w
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
96:0{"sid":"lv_VI97HAXpY6yYWAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}2:40
```
Details:
```
96 => number of characters (not bytes) of the first message
: => separator
0 => Engine.IO "open" packet type
{"sid":... => the Engine.IO handshake data
2 => number of characters of the 2nd message
: => separator
4 => Engine.IO "message" packet type
0 => Socket.IO "CONNECT" packet type
```
Note: the `t` query param is used to ensure that the request is not cached by the browser.
- Request n°2 (message in):
`socket.emit('hey', 'Jude')` is executed on the server:
```
GET /socket.io/?EIO=3&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
16:42["hey","Jude"]
```
Details:
```
16 => number of characters
: => separator
4 => Engine.IO "message" packet type
2 => Socket.IO "EVENT" packet type
[...] => content
```
- Request n°3 (message out)
`socket.emit('hello'); socket.emit('world');` is executed on the client:
```
POST /socket.io/?EIO=3&transport=polling&t=N8hzxke&sid=lv_VI97HAXpY6yYWAAAC
> Content-Type: text/plain; charset=UTF-8
11:42["hello"]11:42["world"]
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
ok
```
Details:
```
11 => number of characters of the 1st packet
: => separator
4 => Engine.IO "message" packet type
2 => Socket.IO "EVENT" packet type
["hello"] => the 1st content
11 => number of characters of the 2nd packet
: => separator
4 => Engine.IO "message" packet type
2 => Socket.IO "EVENT" packet type
["world"] => the 2nd content
```
- Request n°4 (WebSocket upgrade)
```
GET /socket.io/?EIO=3&transport=websocket&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 101 Switching Protocols
```
WebSocket frames:
```
< 2probe => Engine.IO probe request
> 3probe => Engine.IO probe response
> 5 => Engine.IO "upgrade" packet type
> 42["hello"]
> 42["world"]
> 40/admin, => request access to the admin namespace (Socket.IO "CONNECT" packet)
< 40/admin, => grant access to the admin namespace
> 42/admin,1["tellme"] => Socket.IO "EVENT" packet with acknowledgement
< 461-/admin,1[{"_placeholder":true,"num":0}] => Socket.IO "BINARY_ACK" packet with a placeholder
< <binary> => the binary attachment (sent in the following frame)
... after a while without message
> 2 => Engine.IO "ping" packet type
< 3 => Engine.IO "pong" packet type
> 1 => Engine.IO "close" packet type
```
## History
### Difference between v4 and v3
- add a `BINARY_ACK` packet type
Previously, an `ACK` packet was always treated as if it may contain binary objects, with recursive search for such
objects, which could hurt performance.
### Difference between v3 and v2
- remove the usage of msgpack to encode packets containing binary objects (see also [299849b](https://github.com/socketio/socket.io-parser/commit/299849b00294c3bc95817572441f3aca8ffb1f65))
### Difference between v2 and v1
- add a `BINARY_EVENT` packet type
This was added during the work towards Socket.IO 1.0, in order to add support for binary objects. The `BINARY_EVENT`
packets were encoded with [msgpack](https://msgpack.org/).
### Initial revision
This first revision was the result of the split between the Engine.IO protocol (low-level plumbing with WebSocket / HTTP
long-polling, heartbeat) and the Socket.IO protocol. It was never included in a Socket.IO release, but paved the way for
the next iterations.
## License
MIT
================================================
FILE: docs/socket.io-protocol/v5-current.md
================================================
# Socket.IO Protocol
This document describes the 5th version of the Socket.IO protocol.
**Table of content**
- [Introduction](#introduction)
- [Exchange protocol](#exchange-protocol)
- [Connection to a namespace](#connection-to-a-namespace)
- [Sending and receiving data](#sending-and-receiving-data)
- [Acknowledgement](#acknowledgement)
- [Disconnection from a namespace](#disconnection-from-a-namespace)
- [Packet encoding](#packet-encoding)
- [Format](#format)
- [Examples](#examples)
- [Connection to a namespace](#connection-to-a-namespace-1)
- [Sending and receiving data](#sending-and-receiving-data-1)
- [Acknowledgement](#acknowledgement-1)
- [Disconnection from a namespace](#disconnection-from-a-namespace-1)
- [Sample session](#sample-session)
- [History](#history)
- [Difference between v5 and v4](#difference-between-v5-and-v4)
- [Difference between v4 and v3](#difference-between-v4-and-v3)
- [Difference between v3 and v2](#difference-between-v3-and-v2)
- [Difference between v2 and v1](#difference-between-v2-and-v1)
- [Initial revision](#initial-revision)
- [Test suite](#test-suite)
## Introduction
The Socket.IO protocol enables [full-duplex](https://en.wikipedia.org/wiki/Duplex_(telecommunications)#FULL-DUPLEX) and low-overhead communication between a client and a server.
It is built on top of [the Engine.IO protocol](https://github.com/socketio/engine.io-protocol), which handles the low-level plumbing with WebSocket and HTTP long-polling.
The Socket.IO protocol adds the following features:
- multiplexing (referred as ["namespace"](https://socket.io/docs/v4/namespaces) in the Socket.IO jargon)
Example with the JavaScript API:
*Server*
```js
// declare the namespace
const namespace = io.of("/admin");
// handle the connection to the namespace
namespace.on("connection", (socket) => {
// ...
});
```
*Client*
```js
// reach the main namespace
const socket1 = io();
// reach the "/admin" namespace (with the same underlying WebSocket connection)
const socket2 = io("/admin");
// handle the connection to the namespace
socket2.on("connect", () => {
// ...
});
```
- acknowledgement of packets
Example with the JavaScript API:
```js
// on one side
socket.emit("hello", "foo", (arg) => {
console.log("received", arg);
});
// on the other side
socket.on("hello", (arg, ack) => {
ack("bar");
});
```
The reference implementation is written in [TypeScript](https://www.typescriptlang.org/):
- server: https://github.com/socketio/socket.io
- client: https://github.com/socketio/socket.io-client
## Exchange protocol
A Socket.IO packet contains the following fields:
- a packet type (integer)
- a namespace (string)
- optionally, a payload (Object | Array)
- optionally, an acknowledgment id (integer)
Here is the list of available packet types:
| Type | ID | Usage |
|---------------|-----|---------------------------------------------------------------------------------------|
| CONNECT | 0 | Used during the [connection to a namespace](#connection-to-a-namespace). |
| DISCONNECT | 1 | Used when [disconnecting from a namespace](#disconnection-from-a-namespace). |
| EVENT | 2 | Used to [send data](#sending-and-receiving-data) to the other side. |
| ACK | 3 | Used to [acknowledge](#acknowledgement) an event. |
| CONNECT_ERROR | 4 | Used during the [connection to a namespace](#connection-to-a-namespace). |
| BINARY_EVENT | 5 | Used to [send binary data](#sending-and-receiving-data) to the other side. |
| BINARY_ACK | 6 | Used to [acknowledge](#acknowledgement) an event (the response includes binary data). |
### Connection to a namespace
At the beginning of a Socket.IO session, the client MUST send a `CONNECT` packet:
The server MUST respond with either:
- a `CONNECT` packet if the connection is successful, with the session ID in the payload
- or a `CONNECT_ERROR` packet if the connection is not allowed
```
CLIENT SERVER
│ ───────────────────────────────────────────────────────► │
│ { type: CONNECT, namespace: "/" } │
│ ◄─────────────────────────────────────────────────────── │
│ { type: CONNECT, namespace: "/", data: { sid: "..." } } │
```
If the server does not receive a `CONNECT` packet first, then it MUST close the connection immediately.
A client MAY be connected to multiple namespaces at the same time, with the same underlying WebSocket connection.
Examples:
- with the main namespace (named `"/"`)
```
Client > { type: CONNECT, namespace: "/" }
Server > { type: CONNECT, namespace: "/", data: { sid: "wZX3oN0bSVIhsaknAAAI" } }
```
- with a custom namespace
```
Client > { type: CONNECT, namespace: "/admin" }
Server > { type: CONNECT, namespace: "/admin", data: { sid: "oSO0OpakMV_3jnilAAAA" } }
```
- with an additional payload
```
Client > { type: CONNECT, namespace: "/admin", data: { "token": "123" } }
Server > { type: CONNECT, namespace: "/admin", data: { sid: "iLnRaVGHY4B75TeVAAAB" } }
```
- in case the connection is refused
```
Client > { type: CONNECT, namespace: "/" }
Server > { type: CONNECT_ERROR, namespace: "/", data: { message: "Not authorized" } }
```
### Sending and receiving data
Once the [connection to a namespace](#connection-to-a-namespace) is established, the client and the server can begin exchanging data:
```
CLIENT SERVER
│ ───────────────────────────────────────────────────────► │
│ { type: EVENT, namespace: "/", data: ["foo"] } │
│ │
│ ◄─────────────────────────────────────────────────────── │
│ { type: EVENT, namespace: "/", data: ["bar"] } │
```
The payload is mandatory and MUST be a non-empty array. If that's not the case, then the receiver MUST close the connection.
Examples:
- with the main namespace
```
Client > { type: EVENT, namespace: "/", data: ["foo"] }
```
- with a custom namespace
```
Server > { type: EVENT, namespace: "/admin", data: ["bar"] }
```
- with binary data
```
Client > { type: BINARY_EVENT, namespace: "/", data: ["baz", <Buffer <01 02 03 04>> ] }
```
### Acknowledgement
The sender MAY include an event ID in order to request an acknowledgement from the receiver:
```
CLIENT SERVER
│ ───────────────────────────────────────────────────────► │
│ { type: EVENT, namespace: "/", data: ["foo"], id: 12 } │
│ ◄─────────────────────────────────────────────────────── │
│ { type: ACK, namespace: "/", data: ["bar"], id: 12 } │
```
The receiver MUST respond with an `ACK` packet with the same event ID.
The payload is mandatory and MUST be an array (possibly empty).
Examples:
- with the main namespace
```
Client > { type: EVENT, namespace: "/", data: ["foo"], id: 12 }
Server > { type: ACK, namespace: "/", data: [], id: 12 }
```
- with a custom namespace
```
Server > { type: EVENT, namespace: "/admin", data: ["foo"], id: 13 }
Client > { type: ACK, namespace: "/admin", data: ["bar"], id: 13 }
```
- with binary data
```
Client > { type: BINARY_EVENT, namespace: "/", data: ["foo", <buffer <01 02 03 04> ], id: 14 }
Server > { type: ACK, namespace: "/", data: ["bar"], id: 14 }
or
Server > { type: EVENT, namespace: "/", data: ["foo" ], id: 15 }
Client > { type: BINARY_ACK, namespace: "/", data: ["bar", <buffer <01 02 03 04>], id: 15 }
```
### Disconnection from a namespace
At any time, one side can end the connection to a namespace by sending a `DISCONNECT` packet:
```
CLIENT SERVER
│ ───────────────────────────────────────────────────────► │
│ { type: DISCONNECT, namespace: "/" } │
```
No response is expected from the other side. The low-level connection MAY be kept alive if the client is connected to another namespace.
## Packet encoding
This section details the encoding used by the default parser which is included in Socket.IO server and client, and
whose source can be found [here](https://github.com/socketio/socket.io-parser).
The JavaScript server and client implementations also supports custom parsers, which have different tradeoffs and may benefit to
certain kind of applications. Please see [socket.io-json-parser](https://github.com/socketio/socket.io-json-parser)
or [socket.io-msgpack-parser](https://github.com/socketio/socket.io-msgpack-parser) for example.
Please also note that each Socket.IO packet is sent as a Engine.IO `message` packet (more information [here](https://github.com/socketio/engine.io-protocol)),
so the encoded result will be prefixed by the character `"4"` when sent over the wire (in the request/response body with HTTP
long-polling, or in the WebSocket frame).
### Format
```
<packet type>[<# of binary attachments>-][<namespace>,][<acknowledgment id>][JSON-stringified payload without binary]
+ binary attachments extracted
```
Note: the namespace is only included if it is different from the main namespace (`/`)
### Examples
#### Connection to a namespace
- with the main namespace
*Packet*
```
{ type: CONNECT, namespace: "/" }
```
*Encoded*
```
0
```
- with a custom namespace
*Packet*
```
{ type: CONNECT, namespace: "/admin", data: { sid: "oSO0OpakMV_3jnilAAAA" } }
```
*Encoded*
```
0/admin,{"sid":"oSO0OpakMV_3jnilAAAA"}
```
- in case the connection is refused
*Packet*
```
{ type: CONNECT_ERROR, namespace: "/", data: { message: "Not authorized" } }
```
*Encoded*
```
4{"message":"Not authorized"}
```
#### Sending and receiving data
- with the main namespace
*Packet*
```
{ type: EVENT, namespace: "/", data: ["foo"] }
```
*Encoded*
```
2["foo"]
```
- with a custom namespace
*Packet*
```
{ type: EVENT, namespace: "/admin", data: ["bar"] }
```
*Encoded*
```
2/admin,["bar"]
```
- with binary data
*Packet*
```
{ type: BINARY_EVENT, namespace: "/", data: ["baz", <Buffer <01 02 03 04>> ] }
```
*Encoded*
```
51-["baz",{"_placeholder":true,"num":0}]
+ <Buffer <01 02 03 04>>
```
- with multiple attachments
*Packet*
```
{ type: BINARY_EVENT, namespace: "/admin", data: ["baz", <Buffer <01 02>>, <Buffer <03 04>> ] }
```
*Encoded*
```
52-/admin,["baz",{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]
+ <Buffer <01 02>>
+ <Buffer <03 04>>
```
Please remember that each Socket.IO packet is wrapped in a Engine.IO `message` packet, so they will be prefixed by the character `"4"` when sent over the wire.
Example: `{ type: EVENT, namespace: "/", data: ["foo"] }` will be sent as `42["foo"]`
#### Acknowledgement
- with the main namespace
*Packet*
```
{ type: EVENT, namespace: "/", data: ["foo"], id: 12 }
```
*Encoded*
```
212["foo"]
```
- with a custom namespace
*Packet*
```
{ type: ACK, namespace: "/admin", data: ["bar"], id: 13 }
```
*Encoded*
```
3/admin,13["bar"]`
```
- with binary data
*Packet*
```
{ type: BINARY_ACK, namespace: "/", data: ["bar", <Buffer <01 02 03 04>>], id: 15 }
```
*Encoded*
```
61-15["bar",{"_placeholder":true,"num":0}]
+ <Buffer <01 02 03 04>>
```
#### Disconnection from a namespace
- with the main namespace
*Packet*
```
{ type: DISCONNECT, namespace: "/" }
```
*Encoded*
```
1
```
- with a custom namespace
```
{ type: DISCONNECT, namespace: "/admin" }
```
*Encoded*
```
1/admin,
```
## Sample session
Here is an example of what is sent over the wire when combining both the Engine.IO and the Socket.IO protocols.
- Request n°1 (open packet)
```
GET /socket.io/?EIO=4&transport=polling&t=N8hyd6w
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
0{"sid":"lv_VI97HAXpY6yYWAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000,"maxPayload":1000000}
```
Details:
```
0 => Engine.IO "open" packet type
{"sid":... => the Engine.IO handshake data
```
Note: the `t` query param is used to ensure that the request is not cached by the browser.
- Request n°2 (namespace connection request):
```
POST /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
40
```
Details:
```
4 => Engine.IO "message" packet type
0 => Socket.IO "CONNECT" packet type
```
- Request n°3 (namespace connection approval)
```
GET /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
40{"sid":"wZX3oN0bSVIhsaknAAAI"}
```
- Request n°4
`socket.emit('hey', 'Jude')` is executed on the server:
```
GET /socket.io/?EIO=4&transport=polling&t=N8hyd7H&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
42["hey","Jude"]
```
Details:
```
4 => Engine.IO "message" packet type
2 => Socket.IO "EVENT" packet type
[...] => content
```
- Request n°5 (message out)
`socket.emit('hello'); socket.emit('world');` is executed on the client:
```
POST /socket.io/?EIO=4&transport=polling&t=N8hzxke&sid=lv_VI97HAXpY6yYWAAAC
> Content-Type: text/plain; charset=UTF-8
42["hello"]\x1e42["world"]
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
ok
```
Details:
```
4 => Engine.IO "message" packet type
2 => Socket.IO "EVENT" packet type
["hello"] => the 1st content
\x1e => separator
4 => Engine.IO "message" packet type
2 => Socket.IO "EVENT" packet type
["world"] => the 2nd content
```
- Request n°6 (WebSocket upgrade)
```
GET /socket.io/?EIO=4&transport=websocket&sid=lv_VI97HAXpY6yYWAAAC
< HTTP/1.1 101 Switching Protocols
```
WebSocket frames:
```
< 2probe => Engine.IO probe request
> 3probe => Engine.IO probe response
> 5 => Engine.IO "upgrade" packet type
> 42["hello"]
> 42["world"]
> 40/admin, => request access to the admin namespace (Socket.IO "CONNECT" packet)
< 40/admin,{"sid":"-G5j-67EZFp-q59rADQM"} => grant access to the admin namespace
> 42/admin,1["tellme"] => Socket.IO "EVENT" packet with acknowledgement
< 461-/admin,1[{"_placeholder":true,"num":0}] => Socket.IO "BINARY_ACK" packet with a placeholder
< <binary> => the binary attachment (sent in the following frame)
... after a while without message
> 2 => Engine.IO "ping" packet type
< 3 => Engine.IO "pong" packet type
> 1 => Engine.IO "close" packet type
```
## History
### Difference between v5 and v4
The 5th revision (current) of the Socket.IO protocol is used in Socket.IO v3 and above (`v3.0.0` was released in November 2020).
It is built on top of the 4th revision of [the Engine.IO protocol](https://github.com/socketio/engine.io-protocol) (hence the `EIO=4` query parameter).
List of changes:
- remove the implicit connection to the default namespace
In previous versions, a client was always connected to the default namespace, even if it requested access to another namespace.
This is not the case anymore, the client must send a `CONNECT` packet in any case.
Commits: [09b6f23](https://github.com/socketio/socket.io/commit/09b6f2333950b8afc8c1400b504b01ad757876bd) (server) and [249e0be](https://github.com/socketio/socket.io-client/commit/249e0bef9071e7afd785485961c4eef0094254e8) (client)
- rename `ERROR` to `CONNECT_ERROR`
The meaning and the code number (4) are not modified: this packet type is still used by the server when the connection to a namespace is refused. But we feel the name is more self-descriptive.
Commits: [d16c035](https://github.com/socketio/socket.io/commit/d16c035d258b8deb138f71801cb5aeedcdb3f002) (server) and [13e1db7c](https://github.com/socketio/socket.io-client/commit/13e1db7c94291c583d843beaa9e06ee041ae4f26) (client).
- the `CONNECT` packet now can contain a payload
The client can send a payload for authentication/authorization purposes. Example:
```json
{
"type": 0,
"nsp": "/admin",
"data": {
"token": "123"
}
}
```
In case of success, the server responds with a payload contain the ID of the Socket. Example:
```json
{
"type": 0,
"nsp": "/admin",
"data": {
"sid": "CjdVH4TQvovi1VvgAC5Z"
}
}
```
This change means that the ID of the Socket.IO connection will now be different from the ID of the underlying Engine.IO connection (the one that is found in the query parameters of the HTTP requests).
Commits: [2875d2c](https://github.com/socketio/socket.io/commit/2875d2cfdfa463e64cb520099749f543bbc4eb15) (server) and [bbe94ad](https://github.com/socketio/socket.io-client/commit/bbe94adb822a306c6272e977d394e3e203cae25d) (client)
- the payload `CONNECT_ERROR` packet is now an object instead of a plain string
Commits: [54bf4a4](https://github.com/socketio/socket.io/commit/54bf4a44e9e896dfb64764ee7bd4e8823eb7dc7b) (server) and [0939395](https://github.com/socketio/socket.io-client/commit/09393952e3397a0c71f239ea983f8ec1623b7c21) (client)
### Difference between v4 and v3
The 4th revision of the Socket.IO protocol is used in Socket.IO v1 (`v1.0.3` was released in June 2014) and v2 (`v2.0.0` was released in May 2017).
The details of the revision can be found here: https://github.com/socketio/socket.io-protocol/tree/v4
It is built on top of the 3rd revision of [the Engine.IO protocol](https://github.com/socketio/engine.io-protocol) (hence the `EIO=3` query parameter).
List of changes:
- add a `BINARY_ACK` packet type
Previously, an `ACK` packet was always treated as if it may contain binary objects, with recursive search for such
objects, which could hurt performance.
Reference: https://github.com/socketio/socket.io-parser/commit/ca4f42a922ba7078e840b1bc09fe3ad618acc065
### Difference between v3 and v2
The 3rd revision of the Socket.IO protocol is used in early Socket.IO v1 versions (`socket.io@1.0.0...1.0.2`) (released in May 2014).
The details of the revision can be found here: https://github.com/socketio/socket.io-protocol/tree/v3
List of changes:
- remove the usage of msgpack to encode packets containing binary objects (see also [299849b](https://github.com/socketio/socket.io-parser/commit/299849b00294c3bc95817572441f3aca8ffb1f65))
### Difference between v2 and v1
List of changes:
- add a `BINARY_EVENT` packet type
This was added during the work towards Socket.IO 1.0, in order to add support for binary objects. The `BINARY_EVENT`
packets were encoded with [msgpack](https://msgpack.org/).
### Initial revision
This first revision was the result of the split between the Engine.IO protocol (low-level plumbing with WebSocket / HTTP
long-polling, heartbeat) and the Socket.IO protocol. It was never included in a Socket.IO release, but paved the way for
the next iterations.
## Test suite
The test suite in the [`test-suite/`](https://github.com/socketio/socket.io-protocol/tree/main/test-suite) directory lets you check the compliance of a server implementation.
Usage:
- in Node.js: `npm ci && npm test`
- in a browser: simply open the `index.html` file in your browser
For reference, here is expected configuration for the JavaScript server to pass all tests:
```js
import { Server } from "socket.io";
const io = new Server(3000, {
pingInterval: 300,
pingTimeout: 200,
maxPayload: 1000000,
connectTimeout: 1000,
cors: {
origin: "*"
}
});
io.on("connection", (socket) => {
socket.emit("auth", socket.handshake.auth);
socket.on("message", (...args) => {
socket.emit.apply(socket, ["message-back", ...args]);
});
socket.on("message-with-ack", (...args) => {
const ack = args.pop();
ack(...args);
})
});
io.of("/custom").on("connection", (socket) => {
socket.emit("auth", socket.handshake.auth);
});
```
## License
MIT
================================================
FILE: docs/socket.io-protocol/v5-test-suite/.gitignore
================================================
node_modules
================================================
FILE: docs/socket.io-protocol/v5-test-suite/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test suite for the Socket.IO protocol</title>
<link rel="stylesheet" href="https://unpkg.com/mocha@9/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="https://unpkg.com/mocha@9/mocha.js"></script>
<script src="https://unpkg.com/chai@4/chai.js" ></script>
<script src="https://unpkg.com/chai-string@1/chai-string.js" ></script>
<script class="mocha-init">
mocha.setup("bdd");
mocha.checkLeaks();
</script>
<script type="module" src="test-suite.js"></script>
<script class="mocha-exec">
mocha.run();
</script>
</body>
</html>
================================================
FILE: docs/socket.io-protocol/v5-test-suite/node-imports.js
================================================
import fetch from "node-fetch";
import { WebSocket } from "ws";
import chai from "chai";
import chaiString from "chai-string";
chai.use(chaiString);
globalThis.fetch = fetch;
globalThis.WebSocket = WebSocket;
globalThis.chai = chai;
================================================
FILE: docs/socket.io-protocol/v5-test-suite/package.json
================================================
{
"name": "socket.io-protocol-test-suite",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"format": "prettier -w *.js",
"test": "mocha test-suite.js"
},
"devDependencies": {
"chai": "^4.3.6",
"chai-string": "^1.5.0",
"mocha": "^9.2.1",
"node-fetch": "^3.2.0",
"prettier": "^2.5.1",
"ws": "^8.5.0"
}
}
================================================
FILE: docs/socket.io-protocol/v5-test-suite/test-suite.js
================================================
const isNodejs = typeof window === "undefined";
if (isNodejs) {
// make the tests runnable in both the browser and Node.js
await import("./node-imports.js");
}
const { expect } = chai;
const URL = "http://localhost:3000";
const WS_URL = URL.replace("http", "ws");
const PING_INTERVAL = 300;
const PING_TIMEOUT = 200;
function sleep(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
}
function createWebSocket(url) {
const socket = new WebSocket(url);
socket._eventBuffer = {};
socket._pendingPromises = {};
for (const eventType of ["open", "close", "message"]) {
socket._eventBuffer[eventType] = [];
socket._pendingPromises[eventType] = [];
socket.addEventListener(eventType, (event) => {
if (socket._pendingPromises[eventType].length) {
socket._pendingPromises[eventType].shift()(event);
} else {
socket._eventBuffer[eventType].push(event);
}
});
}
return socket;
}
function waitFor(socket, eventType) {
if (socket._eventBuffer[eventType].length) {
return Promise.resolve(socket._eventBuffer[eventType].shift());
} else {
return new Promise((resolve) => {
socket._pendingPromises[eventType].push(resolve);
});
}
}
function waitForPackets(socket, count) {
const packets = [];
return new Promise((resolve) => {
const handler = (event) => {
if (event.data === "2") {
// ignore PING packets
return;
}
packets.push(event.data);
if (packets.length === count) {
socket.removeEventListener("message", handler);
resolve(packets);
}
};
socket.addEventListener("message", handler);
});
}
async function initLongPollingSession() {
const response = await fetch(`${URL}/socket.io/?EIO=4&transport=polling`);
const content = await response.text();
return JSON.parse(content.substring(1)).sid;
}
async function initSocketIOConnection() {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
socket.binaryType = "arraybuffer";
await waitFor(socket, "message"); // Engine.IO handshake
socket.send("40");
await waitFor(socket, "message"); // Socket.IO handshake
await waitFor(socket, "message"); // "auth" packet
return socket;
}
describe("Engine.IO protocol", () => {
describe("handshake", () => {
describe("HTTP long-polling", () => {
it("should successfully open a session", async () => {
const response = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling`
);
expect(response.status).to.eql(200);
const content = await response.text();
expect(content).to.startsWith("0");
const value = JSON.parse(content.substring(1));
expect(value).to.have.all.keys(
"sid",
"upgrades",
"pingInterval",
"pingTimeout",
"maxPayload"
);
expect(value.sid).to.be.a("string");
expect(value.upgrades).to.eql(["websocket"]);
expect(value.pingInterval).to.eql(PING_INTERVAL);
expect(value.pingTimeout).to.eql(PING_TIMEOUT);
expect(value.maxPayload).to.eql(1000000);
});
it("should fail with an invalid 'EIO' query parameter", async () => {
const response = await fetch(`${URL}/socket.io/?transport=polling`);
expect(response.status).to.eql(400);
const response2 = await fetch(
`${URL}/socket.io/?EIO=abc&transport=polling`
);
expect(response2.status).to.eql(400);
});
it("should fail with an invalid 'transport' query parameter", async () => {
const response = await fetch(`${URL}/socket.io/?EIO=4`);
expect(response.status).to.eql(400);
const response2 = await fetch(`${URL}/socket.io/?EIO=4&transport=abc`);
expect(response2.status).to.eql(400);
});
it("should fail with an invalid request method", async () => {
const response = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling`,
{
method: "post",
}
);
expect(response.status).to.eql(400);
const response2 = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling`,
{
method: "put",
}
);
expect(response2.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("should successfully open a session", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("0");
const value = JSON.parse(data.substring(1));
expect(value).to.have.all.keys(
"sid",
"upgrades",
"pingInterval",
"pingTimeout",
"maxPayload"
);
expect(value.sid).to.be.a("string");
expect(value.upgrades).to.eql([]);
expect(value.pingInterval).to.eql(PING_INTERVAL);
expect(value.pingTimeout).to.eql(PING_TIMEOUT);
expect(value.maxPayload).to.eql(1000000);
socket.close();
});
it("should fail with an invalid 'EIO' query parameter", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?transport=websocket`
);
if (isNodejs) {
socket.on("error", () => {});
}
await waitFor(socket, "close");
const socket2 = createWebSocket(
`${WS_URL}/socket.io/?EIO=abc&transport=websocket`
);
if (isNodejs) {
socket2.on("error", () => {});
}
await waitFor(socket2, "close");
});
it("should fail with an invalid 'transport' query parameter", async () => {
const socket = createWebSocket(`${WS_URL}/socket.io/?EIO=4`);
if (isNodejs) {
socket.on("error", () => {});
}
await waitFor(socket, "close");
const socket2 = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=abc`
);
if (isNodejs) {
socket2.on("error", () => {});
}
await waitFor(socket2, "close");
});
});
});
describe("heartbeat", function () {
this.timeout(5000);
describe("HTTP long-polling", () => {
it("should send ping/pong packets", async () => {
const sid = await initLongPollingSession();
for (let i = 0; i < 3; i++) {
const pollResponse = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(200);
const pollContent = await pollResponse.text();
expect(pollContent).to.eql("2");
const pushResponse = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`,
{
method: "post",
body: "3",
}
);
expect(pushResponse.status).to.eql(200);
}
});
it("should close the session upon ping timeout", async () => {
const sid = await initLongPollingSession();
await sleep(PING_INTERVAL + PING_TIMEOUT);
const pollResponse = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("should send ping/pong packets", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // handshake
for (let i = 0; i < 3; i++) {
const { data } = await waitFor(socket, "message");
expect(data).to.eql("2");
socket.send("3");
}
socket.close();
});
it("should close the session upon ping timeout", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "close"); // handshake
});
});
});
describe("close", () => {
describe("HTTP long-polling", () => {
it("should forcefully close the session", async () => {
const sid = await initLongPollingSession();
const [pollResponse] = await Promise.all([
fetch(`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`),
fetch(`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`, {
method: "post",
body: "1",
}),
]);
expect(pollResponse.status).to.eql(200);
const pullContent = await pollResponse.text();
expect(pullContent).to.eql("6");
const pollResponse2 = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse2.status).to.eql(400);
});
});
describe("WebSocket", () => {
it("should forcefully close the session", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // handshake
socket.send("1");
await waitFor(socket, "close");
});
});
});
describe("upgrade", () => {
it("should successfully upgrade from HTTP long-polling to WebSocket", async () => {
const sid = await initLongPollingSession();
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
// send probe
socket.send("2probe");
const probeResponse = await waitFor(socket, "message");
expect(probeResponse.data).to.eql("3probe");
// complete upgrade
socket.send("5");
});
it("should ignore HTTP requests with same sid after upgrade", async () => {
const sid = await initLongPollingSession();
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
await waitFor(socket, "message"); // "3probe"
socket.send("5");
const pollResponse = await fetch(
`${URL}/socket.io/?EIO=4&transport=polling&sid=${sid}`
);
expect(pollResponse.status).to.eql(400);
});
it("should ignore WebSocket connection with same sid after upgrade", async () => {
const sid = await initLongPollingSession();
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket, "open");
socket.send("2probe");
await waitFor(socket, "message"); // "3probe"
socket.send("5");
const socket2 = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket&sid=${sid}`
);
await waitFor(socket2, "close");
});
});
});
describe("Socket.IO protocol", () => {
describe("connect", () => {
it("should allow connection to the main namespace", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // Engine.IO handshake
socket.send("40");
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("40");
const handshake = JSON.parse(data.substring(2));
expect(handshake).to.have.all.keys("sid");
expect(handshake.sid).to.be.a("string");
const authPacket = await waitFor(socket, "message");
expect(authPacket.data).to.eql('42["auth",{}]');
});
it("should allow connection to the main namespace with a payload", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // Engine.IO handshake
socket.send('40{"token":"123"}');
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("40");
const handshake = JSON.parse(data.substring(2));
expect(handshake).to.have.all.keys("sid");
expect(handshake.sid).to.be.a("string");
const authPacket = await waitFor(socket, "message");
expect(authPacket.data).to.eql('42["auth",{"token":"123"}]');
});
it("should allow connection to a custom namespace", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // Engine.IO handshake
socket.send("40/custom,");
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("40/custom,");
const handshake = JSON.parse(data.substring(10));
expect(handshake).to.have.all.keys("sid");
expect(handshake.sid).to.be.a("string");
const authPacket = await waitFor(socket, "message");
expect(authPacket.data).to.eql('42/custom,["auth",{}]');
});
it("should allow connection to a custom namespace with a payload", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // Engine.IO handshake
socket.send('40/custom,{"token":"abc"}');
const { data } = await waitFor(socket, "message");
expect(data).to.startsWith("40/custom,");
const handshake = JSON.parse(data.substring(10));
expect(handshake).to.have.all.keys("sid");
expect(handshake.sid).to.be.a("string");
const authPacket = await waitFor(socket, "message");
expect(authPacket.data).to.eql('42/custom,["auth",{"token":"abc"}]');
});
it("should disallow connection to an unknown namespace", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // Engine.IO handshake
socket.send("40/random");
const { data } = await waitFor(socket, "message");
expect(data).to.eql('44/random,{"message":"Invalid namespace"}');
});
it("should disallow connection with an invalid handshake", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "message"); // Engine.IO handshake
socket.send("4abc");
await waitFor(socket, "close");
});
it("should close the connection if no handshake is received", async () => {
const socket = createWebSocket(
`${WS_URL}/socket.io/?EIO=4&transport=websocket`
);
await waitFor(socket, "close");
});
});
describe("disconnect", () => {
it("should disconnect from the main namespace", async () => {
const socket = await initSocketIOConnection();
socket.send("41");
const { data } = await waitFor(socket, "message");
expect(data).to.eql("2");
});
it("should connect then disconnect from a custom namespace", async () => {
const socket = await initSocketIOConnection();
await waitFor(socket, "message"); // ping
socket.send("40/custom");
await waitFor(socket, "message"); // Socket.IO handshake
await waitFor(socket, "message"); // auth packet
socket.send("41/custom");
socket.send('42["message","message to main namespace"]');
const { data } = await waitFor(socket, "message");
expect(data).to.eql('42["message-back","message to main namespace"]');
});
});
describe("message", () => {
it("should send a plain-text packet", async () => {
const socket = await initSocketIOConnection();
socket.send('42["message",1,"2",{"3":[true]}]');
const { data } = await waitFor(socket, "message");
expect(data).to.eql('42["message-back",1,"2",{"3":[true]}]');
});
it("should send a packet with binary attachments", async () => {
const socket = await initSocketIOConnection();
socket.send(
'452-["message",{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]'
);
socket.send(Uint8Array.from([1, 2, 3]));
socket.send(Uint8Array.from([4, 5, 6]));
const packets = await waitForPackets(socket, 3);
expect(packets[0]).to.eql(
'452-["message-back",{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]'
);
expect(packets[1]).to.eql(Uint8Array.from([1, 2, 3]).buffer);
expect(packets[2]).to.eql(Uint8Array.from([4, 5, 6]).buffer);
socket.close();
});
it("should send a plain-text packet with an ack", async () => {
const socket = await initSocketIOConnection();
socket.send('42456["message-with-ack",1,"2",{"3":[false]}]');
const { data } = await waitFor(socket, "message");
expect(data).to.eql('43456[1,"2",{"3":[false]}]');
});
it("should send a packet with binary attachments and an ack", async () => {
const socket = await initSocketIOConnection();
socket.send(
'452-789["message-with-ack",{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]'
);
socket.send(Uint8Array.from([1, 2, 3]));
socket.send(Uint8Array.from([4, 5, 6]));
const packets = await waitForPackets(socket, 3);
expect(packets[0]).to.eql(
'462-789[{"_placeholder":true,"num":0},{"_placeholder":true,"num":1}]'
);
expect(packets[1]).to.eql(Uint8Array.from([1, 2, 3]).buffer);
expect(packets[2]).to.eql(Uint8Array.from([4, 5, 6]).buffer);
socket.close();
});
it("should close the connection upon invalid format (unknown packet type)", async () => {
const socket = await initSocketIOConnection();
socket.send("4abc");
await waitFor(socket, "close");
});
it("should close the connection upon invalid format (invalid payload format)", async () => {
const socket = await initSocketIOConnection();
socket.send("42{}");
await waitFor(socket, "close");
});
it("should close the connection upon invalid format (invalid ack id)", async () => {
const socket = await initSocketIOConnection();
socket.send('42abc["message-with-ack",1,"2",{"3":[false]}]');
await waitFor(socket, "close");
});
});
});
================================================
FILE: examples/.gitignore
================================================
package-lock.json
================================================
FILE: examples/ReactNativeExample/.bundle/config
================================================
BUNDLE_PATH: "vendor/bundle"
BUNDLE_FORCE_RUBY_PLATFORM: 1
================================================
FILE: examples/ReactNativeExample/.eslintrc.js
================================================
module.exports = {
root: true,
extends: '@react-native',
};
================================================
FILE: examples/ReactNativeExample/.gitignore
================================================
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
ios/.xcode.env.local
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
.cxx/
*.keystore
!debug.keystore
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/
**/fastlane/report.xml
**/fastlane/Preview.html
**/fastlane/screenshots
**/fastlane/test_output
# Bundle artifact
*.jsbundle
# Ruby / CocoaPods
/ios/Pods/
/vendor/bundle/
# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*
# testing
/coverage
================================================
FILE: examples/ReactNativeExample/.prettierrc.js
================================================
module.exports = {
arrowParens: 'avoid',
bracketSameLine: true,
bracketSpacing: false,
singleQuote: true,
trailingComma: 'all',
};
================================================
FILE: examples/ReactNativeExample/.watchmanconfig
================================================
{}
================================================
FILE: examples/ReactNativeExample/App.tsx
================================================
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
*/
import React from 'react';
import type {PropsWithChildren} from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import { socket } from './socket';
import { useEffect, useState } from 'react';
import {
Colors,
DebugInstructions,
Header,
LearnMoreLinks,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
type SectionProps = PropsWithChildren<{
title: string;
}>;
function Section({children, title}: SectionProps): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.sectionContainer}>
<Text
style={[
styles.sectionTitle,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
{title}
</Text>
<Text
style={[
styles.sectionDescription,
{
color: isDarkMode ? Colors.light : Colors.dark,
},
]}>
{children}
</Text>
</View>
);
}
function App(): React.JSX.Element {
const [isConnected, setIsConnected] = useState(false);
const [transport, setTransport] = useState('N/A');
useEffect(() => {
if (socket.connected) {
onConnect();
}
function onConnect() {
setIsConnected(true);
setTransport(socket.io.engine.transport.name);
socket.io.engine.on('upgrade', (transport) => {
setTransport(transport.name);
});
}
function onDisconnect() {
setIsConnected(false);
setTransport('N/A');
}
socket.on('connect', onConnect);
socket.on('disconnect', onDisconnect);
return () => {
socket.off('connect', onConnect);
socket.off('disconnect', onDisconnect);
};
}, []);
return (
<View style={styles.container}>
<Text>Status: { isConnected ? 'connected' : 'disconnected' }</Text>
<Text>Transport: { transport }</Text>
</View>
);
}
const styles = StyleSheet.create({
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
},
highlight: {
fontWeight: '700',
},
});
export default App;
================================================
FILE: examples/ReactNativeExample/Gemfile
================================================
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
================================================
FILE: examples/ReactNativeExample/README.md
================================================
This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
# Getting Started
>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
## Step 1: Start the Metro Server
First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
To start Metro, run the following command from the _root_ of your React Native project:
```bash
# using npm
npm start
# OR using Yarn
yarn start
```
## Step 2: Start your Application
Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
### For Android
```bash
# using npm
npm run android
# OR using Yarn
yarn android
```
### For iOS
```bash
# using npm
npm run ios
# OR using Yarn
yarn ios
```
If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
## Step 3: Start the Socket.IO server
```bash
cd server
npm install
npm start
```
## Step 4: Modifying your App
Now that you have successfully run the app, let's modify it.
1. Open `App.tsx` in your text editor of choice and edit some lines.
2. For **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Developer Menu** (<kbd>Ctrl</kbd> + <kbd>M</kbd> (on Window and Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (on macOS)) to see your changes!
For **iOS**: Hit <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> in your iOS Simulator to reload the app and see your changes!
## Congratulations! :tada:
You've successfully run and modified your React Native App. :partying_face:
### Now what?
- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
# Troubleshooting
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
# Learn More
To learn more about React Native, take a look at the following resources:
- [React Native Website](https://reactnative.dev) - learn more about React Native.
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
================================================
FILE: examples/ReactNativeExample/__tests__/App.test.tsx
================================================
/**
* @format
*/
import 'react-native';
import React from 'react';
import App from '../App';
// Note: import explicitly to use the types shipped with jest.
import {it} from '@jest/globals';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
renderer.create(<App />);
});
================================================
FILE: examples/ReactNativeExample/android/app/build.gradle
================================================
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
/**
* This is the configuration block to customize your React Native Android app.
* By default you don't need to apply any configuration, just uncomment the lines you need.
*/
react {
/* Folders */
// The root of your project, i.e. where "package.json" lives. Default is '..'
// root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../node_modules/react-native")
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
// codegenDir = file("../node_modules/@react-native/codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
// cliFile = file("../node_modules/react-native/cli.js")
/* Variants */
// The list of variants to that are debuggable. For those we're going to
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
// debuggableVariants = ["liteDebug", "prodDebug"]
/* Bundling */
// A list containing the node command and its flags. Default is just 'node'.
// nodeExecutableAndArgs = ["node"]
//
// The command to run when bundling. By default is 'bundle'
// bundleCommand = "ram-bundle"
//
// The path to the CLI configuration file. Default is empty.
// bundleConfig = file(../rn-cli.config.js)
//
// The name of the generated asset file containing your JS bundle
// bundleAssetName = "MyApplication.android.bundle"
//
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
// entryFile = file("../js/MyApplication.android.js")
//
// A list of extra flags to pass to the 'bundle' commands.
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
// extraPackagerArgs = []
/* Hermes Commands */
// The hermes compiler command to run. By default it is 'hermesc'
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
//
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
// hermesFlags = ["-O", "-output-source-map"]
}
/**
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
*/
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore (JSC)
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
android {
ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
namespace "com.reactnativeexample"
defaultConfig {
applicationId "com.reactnativeexample"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
}
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("com.facebook.react:flipper-integration")
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
================================================
FILE: examples/ReactNativeExample/android/app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
================================================
FILE: examples/ReactNativeExample/android/app/src/debug/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:usesCleartextTraffic="true"
tools:targetApi="28"
tools:ignore="GoogleAppIndexingWarning"/>
</manifest>
================================================
FILE: examples/ReactNativeExample/android/app/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
================================================
FILE: examples/ReactNativeExample/android/app/src/main/java/com/reactnativeexample/MainActivity.kt
================================================
package com.reactnativeexample
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
class MainActivity : ReactActivity() {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
override fun getMainComponentName(): String = "ReactNativeExample"
/**
* Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
* which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
*/
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
================================================
FILE: examples/ReactNativeExample/android/app/src/main/java/com/reactnativeexample/MainApplication.kt
================================================
package com.reactnativeexample
import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.flipper.ReactNativeFlipper
import com.facebook.soloader.SoLoader
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
}
override fun getJSMainModuleName(): String = "index"
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override val reactHost: ReactHost
get() = getDefaultReactHost(this.applicationContext, reactNativeHost)
override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()
}
ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
}
}
================================================
FILE: examples/ReactNativeExample/android/app/src/main/res/drawable/rn_edit_text_material.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
android:insetTop="@dimen/abc_edit_text_inset_top_material"
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
<selector>
<!--
This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
-->
<item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
<item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
</selector>
</inset>
================================================
FILE: examples/ReactNativeExample/android/app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">ReactNativeExample</string>
</resources>
================================================
FILE: examples/ReactNativeExample/android/app/src/main/res/values/styles.xml
================================================
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
</style>
</resources>
================================================
FILE: examples/ReactNativeExample/android/build.gradle
================================================
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 21
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "25.1.8937393"
kotlinVersion = "1.8.0"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
}
}
apply plugin: "com.facebook.react.rootproject"
================================================
FILE: examples/ReactNativeExample/android/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: examples/ReactNativeExample/android/gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
# Use this property to enable support to the new architecture.
# This will allow you to use TurboModules and the Fabric render in
# your application. You should enable this flag either if you want
# to write custom TurboModules/Fabric components OR use libraries that
# are providing them.
newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
================================================
FILE: examples/ReactNativeExample/android/gradlew
================================================
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
================================================
FILE: examples/ReactNativeExample/android/gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: examples/ReactNativeExample/android/settings.gradle
================================================
rootProject.name = 'ReactNativeExample'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../node_modules/@react-native/gradle-plugin')
================================================
FILE: examples/ReactNativeExample/app.json
================================================
{
"name": "ReactNativeExample",
"displayName": "ReactNativeExample"
}
================================================
FILE: examples/ReactNativeExample/babel.config.js
================================================
module.exports = {
presets: ['module:@react-native/babel-preset'],
};
================================================
FILE: examples/ReactNativeExample/index.js
================================================
/**
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
================================================
FILE: examples/ReactNativeExample/ios/.xcode.env
================================================
# This `.xcode.env` file is versioned and is used to source the environment
# used when running script phases inside Xcode.
# To customize your local environment, you can create an `.xcode.env.local`
# file that is not versioned.
# NODE_BINARY variable contains the PATH to the node executable.
#
# Customize the NODE_BINARY variable here.
# For example, to use nvm with brew, add the following line
# . "$(brew --prefix nvm)/nvm.sh" --no-use
export NODE_BINARY=$(command -v node)
================================================
FILE: examples/ReactNativeExample/ios/Podfile
================================================
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, min_ios_version_supported
prepare_react_native_project!
# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
# ```js
# module.exports = {
# dependencies: {
# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
# ```
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'ReactNativeExample' do
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable the next line.
:flipper_configuration => flipper_config,
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
target 'ReactNativeExampleTests' do
inherit! :complete
# Pods for testing
end
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts
gitextract_cbdandz_/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── build-examples.yml
│ ├── ci-browser.yml
│ ├── ci.yml
│ └── publish.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── docs/
│ ├── README.md
│ ├── engine.io-protocol/
│ │ ├── v3-test-suite/
│ │ │ ├── .gitignore
│ │ │ ├── index.html
│ │ │ ├── node-imports.js
│ │ │ ├── package.json
│ │ │ └── test-suite.js
│ │ ├── v3.md
│ │ ├── v4-current.md
│ │ └── v4-test-suite/
│ │ ├── .gitignore
│ │ ├── index.html
│ │ ├── node-imports.js
│ │ ├── package.json
│ │ └── test-suite.js
│ └── socket.io-protocol/
│ ├── v3.md
│ ├── v4.md
│ ├── v5-current.md
│ └── v5-test-suite/
│ ├── .gitignore
│ ├── index.html
│ ├── node-imports.js
│ ├── package.json
│ └── test-suite.js
├── examples/
│ ├── .gitignore
│ ├── ReactNativeExample/
│ │ ├── .bundle/
│ │ │ └── config
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── .prettierrc.js
│ │ ├── .watchmanconfig
│ │ ├── App.tsx
│ │ ├── Gemfile
│ │ ├── README.md
│ │ ├── __tests__/
│ │ │ └── App.test.tsx
│ │ ├── android/
│ │ │ ├── app/
│ │ │ │ ├── build.gradle
│ │ │ │ ├── debug.keystore
│ │ │ │ ├── proguard-rules.pro
│ │ │ │ └── src/
│ │ │ │ ├── debug/
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ └── main/
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java/
│ │ │ │ │ └── com/
│ │ │ │ │ └── reactnativeexample/
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ └── MainApplication.kt
│ │ │ │ └── res/
│ │ │ │ ├── drawable/
│ │ │ │ │ └── rn_edit_text_material.xml
│ │ │ │ └── values/
│ │ │ │ ├── strings.xml
│ │ │ │ └── styles.xml
│ │ │ ├── build.gradle
│ │ │ ├── gradle/
│ │ │ │ └── wrapper/
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ │ ├── gradle.properties
│ │ │ ├── gradlew
│ │ │ ├── gradlew.bat
│ │ │ └── settings.gradle
│ │ ├── app.json
│ │ ├── babel.config.js
│ │ ├── index.js
│ │ ├── ios/
│ │ │ ├── .xcode.env
│ │ │ ├── Podfile
│ │ │ ├── ReactNativeExample/
│ │ │ │ ├── AppDelegate.h
│ │ │ │ ├── AppDelegate.mm
│ │ │ │ ├── Images.xcassets/
│ │ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ │ └── Contents.json
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Info.plist
│ │ │ │ ├── LaunchScreen.storyboard
│ │ │ │ └── main.m
│ │ │ ├── ReactNativeExample.xcodeproj/
│ │ │ │ ├── project.pbxproj
│ │ │ │ └── xcshareddata/
│ │ │ │ └── xcschemes/
│ │ │ │ └── ReactNativeExample.xcscheme
│ │ │ └── ReactNativeExampleTests/
│ │ │ ├── Info.plist
│ │ │ └── ReactNativeExampleTests.m
│ │ ├── jest.config.js
│ │ ├── metro.config.js
│ │ ├── package.json
│ │ ├── server/
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── socket.js
│ │ └── tsconfig.json
│ ├── angular-todomvc/
│ │ ├── .browserslistrc
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── angular.json
│ │ ├── e2e/
│ │ │ ├── protractor.conf.js
│ │ │ ├── src/
│ │ │ │ ├── app.e2e-spec.ts
│ │ │ │ └── app.po.ts
│ │ │ └── tsconfig.json
│ │ ├── karma.conf.js
│ │ ├── package.json
│ │ ├── server.ts
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── app.component.css
│ │ │ │ ├── app.component.html
│ │ │ │ ├── app.component.spec.ts
│ │ │ │ ├── app.component.ts
│ │ │ │ ├── app.module.ts
│ │ │ │ └── store.ts
│ │ │ ├── assets/
│ │ │ │ └── .gitkeep
│ │ │ ├── environments/
│ │ │ │ ├── environment.prod.ts
│ │ │ │ └── environment.ts
│ │ │ ├── index.html
│ │ │ ├── main.ts
│ │ │ ├── polyfills.ts
│ │ │ ├── styles.css
│ │ │ └── test.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.spec.json
│ │ └── tslint.json
│ ├── basic-crud-application/
│ │ ├── README.md
│ │ ├── angular-client/
│ │ │ ├── .editorconfig
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── angular.json
│ │ │ ├── package.json
│ │ │ ├── src/
│ │ │ │ ├── app/
│ │ │ │ │ ├── app.component.css
│ │ │ │ │ ├── app.component.html
│ │ │ │ │ ├── app.component.spec.ts
│ │ │ │ │ ├── app.component.ts
│ │ │ │ │ ├── app.config.ts
│ │ │ │ │ ├── app.routes.ts
│ │ │ │ │ └── store.ts
│ │ │ │ ├── assets/
│ │ │ │ │ └── .gitkeep
│ │ │ │ ├── environments/
│ │ │ │ │ ├── environment.development.ts
│ │ │ │ │ └── environment.ts
│ │ │ │ ├── index.html
│ │ │ │ ├── main.ts
│ │ │ │ └── styles.css
│ │ │ ├── tsconfig.app.json
│ │ │ ├── tsconfig.json
│ │ │ └── tsconfig.spec.json
│ │ ├── common/
│ │ │ └── events.ts
│ │ ├── server/
│ │ │ ├── lib/
│ │ │ │ ├── app.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── todo-management/
│ │ │ │ │ ├── todo.handlers.ts
│ │ │ │ │ └── todo.repository.ts
│ │ │ │ └── util.ts
│ │ │ ├── package.json
│ │ │ ├── test/
│ │ │ │ └── todo-management/
│ │ │ │ └── todo.tests.ts
│ │ │ └── tsconfig.json
│ │ ├── server-postgres-cluster/
│ │ │ ├── README.md
│ │ │ ├── docker-compose.yml
│ │ │ ├── lib/
│ │ │ │ ├── app.js
│ │ │ │ ├── cluster.js
│ │ │ │ ├── index.js
│ │ │ │ ├── todo-management/
│ │ │ │ │ ├── todo.handlers.js
│ │ │ │ │ └── todo.repository.js
│ │ │ │ └── util.js
│ │ │ └── package.json
│ │ └── vue-client/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── jsconfig.json
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── index.html
│ │ │ └── styles.css
│ │ ├── src/
│ │ │ ├── App.vue
│ │ │ ├── main.js
│ │ │ ├── socket.js
│ │ │ └── stores/
│ │ │ └── todo.js
│ │ └── vue.config.js
│ ├── basic-websocket-client/
│ │ ├── README.md
│ │ ├── check-bundle-size.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src/
│ │ │ └── index.js
│ │ └── test/
│ │ └── index.js
│ ├── chat/
│ │ ├── README.md
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-engine-node-cluster/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── package.json
│ │ └── server.js
│ ├── cluster-engine-redis/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── compose.yaml
│ │ ├── package.json
│ │ └── server.js
│ ├── cluster-haproxy/
│ │ ├── README.md
│ │ ├── docker-compose.yml
│ │ ├── haproxy.cfg
│ │ └── server/
│ │ ├── Dockerfile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-httpd/
│ │ ├── README.md
│ │ ├── docker-compose.yml
│ │ ├── httpd.conf
│ │ └── server/
│ │ ├── Dockerfile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-nginx/
│ │ ├── README.md
│ │ ├── client/
│ │ │ ├── Dockerfile
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── docker-compose.yml
│ │ ├── nginx.conf
│ │ └── server/
│ │ ├── Dockerfile
│ │ ├── index.js
│ │ ├── package.json
│ │ └── public/
│ │ ├── index.html
│ │ ├── main.js
│ │ └── style.css
│ ├── cluster-traefik/
│ │ ├── README.md
│ │ ├── docker-compose.yml
│ │ ├── server/
│ │ │ ├── Dockerfile
│ │ │ ├── index.js
│ │ │ ├── package.json
│ │ │ └── public/
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── style.css
│ │ └── traefik.yml
│ ├── connection-state-recovery-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── .codesandbox/
│ │ │ │ ├── Dockerfile
│ │ │ │ └── tasks.json
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── esm/
│ │ ├── .codesandbox/
│ │ │ ├── Dockerfile
│ │ │ └── tasks.json
│ │ ├── index.html
│ │ ├── index.js
│ │ └── package.json
│ ├── create-react-app-example/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ └── robots.txt
│ │ ├── server.js
│ │ └── src/
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── serviceWorker.js
│ │ └── setupTests.js
│ ├── custom-parsers/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── .gitignore
│ │ │ └── index.html
│ │ ├── src/
│ │ │ ├── client1.js
│ │ │ ├── client2.js
│ │ │ ├── client3.js
│ │ │ ├── client4.js
│ │ │ ├── custom-parser.js
│ │ │ └── server.js
│ │ └── support/
│ │ └── webpack.config.js
│ ├── es-modules/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── package.json
│ │ └── server.js
│ ├── expo-example/
│ │ ├── .gitignore
│ │ ├── App.js
│ │ ├── app.json
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── server/
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── socket.js
│ ├── express-session-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── esm/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── ts/
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── nestjs-example/
│ │ ├── .eslintrc.js
│ │ ├── .gitignore
│ │ ├── .prettierrc
│ │ ├── README.md
│ │ ├── nest-cli.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app.controller.spec.ts
│ │ │ ├── app.controller.ts
│ │ │ ├── app.module.ts
│ │ │ ├── app.service.ts
│ │ │ ├── events/
│ │ │ │ ├── events.gateway.ts
│ │ │ │ └── events.module.ts
│ │ │ └── main.ts
│ │ ├── test/
│ │ │ ├── app.e2e-spec.ts
│ │ │ └── jest-e2e.json
│ │ ├── tsconfig.build.json
│ │ ├── tsconfig.json
│ │ └── views/
│ │ └── index.hbs
│ ├── nextjs-app-router/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── jsconfig.json
│ │ ├── next.config.mjs
│ │ ├── package.json
│ │ ├── server.js
│ │ └── src/
│ │ ├── app/
│ │ │ ├── globals.css
│ │ │ ├── layout.js
│ │ │ ├── page.js
│ │ │ └── page.module.css
│ │ └── socket.js
│ ├── nextjs-pages-router/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── jsconfig.json
│ │ ├── next.config.mjs
│ │ ├── package.json
│ │ ├── server.js
│ │ └── src/
│ │ ├── pages/
│ │ │ ├── _app.js
│ │ │ ├── _document.js
│ │ │ ├── api/
│ │ │ │ └── hello.js
│ │ │ └── index.js
│ │ ├── socket.js
│ │ └── styles/
│ │ ├── Home.module.css
│ │ └── globals.css
│ ├── nuxt-example/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── app.vue
│ │ ├── components/
│ │ │ ├── Connection.client.vue
│ │ │ └── socket.ts
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ ├── server/
│ │ │ ├── plugins/
│ │ │ │ └── socket.io.ts
│ │ │ └── tsconfig.json
│ │ └── tsconfig.json
│ ├── nwjs-example/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── package.json
│ │ └── server/
│ │ ├── index.js
│ │ └── package.json
│ ├── passport-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── login.html
│ │ │ └── package.json
│ │ ├── esm/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── login.html
│ │ │ └── package.json
│ │ └── ts/
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── login.html
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── passport-jwt-example/
│ │ ├── README.md
│ │ ├── cjs/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── esm/
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── ts/
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── postgres-adapter-example/
│ │ ├── README.md
│ │ ├── client.js
│ │ ├── cluster.js
│ │ ├── compose.yaml
│ │ ├── package.json
│ │ └── server.js
│ ├── private-messaging/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── public/
│ │ │ └── index.html
│ │ ├── server/
│ │ │ ├── cluster.js
│ │ │ ├── docker-compose.yml
│ │ │ ├── index.js
│ │ │ ├── messageStore.js
│ │ │ ├── package.json
│ │ │ └── sessionStore.js
│ │ └── src/
│ │ ├── App.vue
│ │ ├── components/
│ │ │ ├── Chat.vue
│ │ │ ├── MessagePanel.vue
│ │ │ ├── SelectUsername.vue
│ │ │ ├── StatusIcon.vue
│ │ │ └── User.vue
│ │ ├── main.js
│ │ └── socket.js
│ ├── rollup-server-bundle/
│ │ ├── .gitignore
│ │ ├── index.js
│ │ ├── package.json
│ │ └── rollup.config.js
│ ├── tweet-stream/
│ │ ├── index.js
│ │ └── package.json
│ ├── typescript-client-example/
│ │ ├── cjs/
│ │ │ ├── client.ts
│ │ │ ├── package.json
│ │ │ └── tsconfig.json
│ │ └── esm/
│ │ ├── client.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── typescript-example/
│ │ ├── cjs/
│ │ │ ├── client.ts
│ │ │ ├── package.json
│ │ │ ├── server.ts
│ │ │ └── tsconfig.json
│ │ └── esm/
│ │ ├── client.ts
│ │ ├── package.json
│ │ ├── server.ts
│ │ └── tsconfig.json
│ ├── webpack-build/
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── package.json
│ │ └── webpack.config.js
│ ├── webpack-build-server/
│ │ ├── README.md
│ │ ├── index.js
│ │ ├── package.json
│ │ └── webpack.config.js
│ ├── webtransport/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── generate_cert.sh
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── open_chrome.sh
│ │ └── package.json
│ └── whiteboard/
│ ├── README.md
│ ├── index.js
│ ├── package.json
│ └── public/
│ ├── index.html
│ ├── main.js
│ └── style.css
├── package.json
└── packages/
├── engine.io/
│ ├── .eslintrc.json
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── examples/
│ │ ├── esm-import/
│ │ │ ├── README.md
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── latency/
│ │ │ ├── README.md
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── package.json
│ │ │ └── public/
│ │ │ ├── index.js
│ │ │ └── style.css
│ │ ├── memory-usage/
│ │ │ ├── .gitignore
│ │ │ ├── client.js
│ │ │ ├── package.json
│ │ │ └── server.js
│ │ └── memory-usage-webtransport/
│ │ ├── .gitignore
│ │ ├── client.js
│ │ ├── generate_cert.sh
│ │ ├── package.json
│ │ └── server.js
│ ├── lib/
│ │ ├── contrib/
│ │ │ └── types.cookie.ts
│ │ ├── engine.io.ts
│ │ ├── parser-v3/
│ │ │ ├── index.ts
│ │ │ └── utf8.ts
│ │ ├── server.ts
│ │ ├── socket.ts
│ │ ├── transport.ts
│ │ ├── transports/
│ │ │ ├── index.ts
│ │ │ ├── polling-jsonp.ts
│ │ │ ├── polling.ts
│ │ │ ├── websocket.ts
│ │ │ └── webtransport.ts
│ │ ├── transports-uws/
│ │ │ ├── index.ts
│ │ │ ├── polling.ts
│ │ │ └── websocket.ts
│ │ └── userver.ts
│ ├── package.json
│ ├── test/
│ │ ├── .eslintrc.json
│ │ ├── common.js
│ │ ├── engine.io.js
│ │ ├── fixtures/
│ │ │ ├── ca.crt
│ │ │ ├── ca.key
│ │ │ ├── client.crt
│ │ │ ├── client.csr
│ │ │ ├── client.key
│ │ │ ├── client.pfx
│ │ │ ├── generate_certs.sh
│ │ │ ├── server-close-upgraded.js
│ │ │ ├── server-close-upgrading.js
│ │ │ ├── server-close.js
│ │ │ ├── server.crt
│ │ │ ├── server.csr
│ │ │ └── server.key
│ │ ├── middlewares.js
│ │ ├── parser.js
│ │ ├── server.js
│ │ ├── util.mjs
│ │ └── webtransport.mjs
│ ├── tsconfig.json
│ └── wrapper.mjs
├── engine.io-client/
│ ├── .gitignore
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── lib/
│ │ ├── browser-entrypoint.ts
│ │ ├── contrib/
│ │ │ ├── has-cors.ts
│ │ │ ├── parseqs.ts
│ │ │ └── parseuri.ts
│ │ ├── globals.node.ts
│ │ ├── globals.ts
│ │ ├── index.ts
│ │ ├── socket.ts
│ │ ├── transport.ts
│ │ ├── transports/
│ │ │ ├── index.ts
│ │ │ ├── polling-fetch.ts
│ │ │ ├── polling-xhr.node.ts
│ │ │ ├── polling-xhr.ts
│ │ │ ├── polling.ts
│ │ │ ├── websocket.node.ts
│ │ │ ├── websocket.ts
│ │ │ └── webtransport.ts
│ │ └── util.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── bundle-size.js
│ │ ├── package.cjs.json
│ │ ├── package.esm.json
│ │ ├── prod.config.js
│ │ ├── rollup.config.esm.js
│ │ ├── rollup.config.umd.js
│ │ └── webpack.config.js
│ ├── test/
│ │ ├── arraybuffer/
│ │ │ ├── index.js
│ │ │ ├── polling.js
│ │ │ └── ws.js
│ │ ├── binary-fallback.js
│ │ ├── blob/
│ │ │ ├── index.js
│ │ │ ├── polling.js
│ │ │ └── ws.js
│ │ ├── connection.js
│ │ ├── engine.io-client.js
│ │ ├── fixtures/
│ │ │ ├── no-unref.js
│ │ │ ├── unref-polling-only.js
│ │ │ ├── unref-websocket-only.js
│ │ │ └── unref.js
│ │ ├── index.js
│ │ ├── node.js
│ │ ├── parseuri.js
│ │ ├── socket.js
│ │ ├── support/
│ │ │ ├── env.js
│ │ │ ├── hooks.js
│ │ │ ├── public/
│ │ │ │ └── worker.js
│ │ │ └── server.js
│ │ ├── transport.js
│ │ ├── util-wt.mjs
│ │ ├── util.js
│ │ ├── webtransport.mjs
│ │ └── xmlhttprequest.js
│ ├── tsconfig.esm.json
│ └── tsconfig.json
├── engine.io-parser/
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── benchmarks/
│ │ ├── index.js
│ │ └── results.md
│ ├── lib/
│ │ ├── commons.ts
│ │ ├── contrib/
│ │ │ └── base64-arraybuffer.ts
│ │ ├── decodePacket.browser.ts
│ │ ├── decodePacket.ts
│ │ ├── encodePacket.browser.ts
│ │ ├── encodePacket.ts
│ │ └── index.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── package.cjs.json
│ │ └── package.esm.json
│ ├── test/
│ │ ├── browser.ts
│ │ ├── index.ts
│ │ ├── node.ts
│ │ └── util.ts
│ ├── tsconfig.esm.json
│ └── tsconfig.json
├── socket.io/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── RELEASING.md
│ ├── Readme.md
│ ├── client-dist/
│ │ └── socket.io.js
│ ├── lib/
│ │ ├── broadcast-operator.ts
│ │ ├── client.ts
│ │ ├── index.ts
│ │ ├── namespace.ts
│ │ ├── parent-namespace.ts
│ │ ├── socket-types.ts
│ │ ├── socket.ts
│ │ ├── typed-events.ts
│ │ └── uws.ts
│ ├── package.json
│ ├── test/
│ │ ├── close.ts
│ │ ├── connection-state-recovery.ts
│ │ ├── fixtures/
│ │ │ ├── big.json
│ │ │ └── server-close.ts
│ │ ├── handshake.ts
│ │ ├── index.ts
│ │ ├── messaging-many.ts
│ │ ├── middleware.ts
│ │ ├── namespaces.ts
│ │ ├── server-attachment.ts
│ │ ├── socket-middleware.ts
│ │ ├── socket-timeout.ts
│ │ ├── socket.io.test-d.ts
│ │ ├── socket.ts
│ │ ├── support/
│ │ │ ├── expectjs.d.ts
│ │ │ └── util.ts
│ │ ├── utility-methods.ts
│ │ ├── uws.ts
│ │ └── v2-compatibility.ts
│ ├── tsconfig.json
│ └── wrapper.mjs
├── socket.io-adapter/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── lib/
│ │ ├── cluster-adapter.ts
│ │ ├── contrib/
│ │ │ └── yeast.ts
│ │ ├── in-memory-adapter.ts
│ │ └── index.ts
│ ├── package.json
│ ├── test/
│ │ ├── cluster-adapter.ts
│ │ ├── index.ts
│ │ └── util.ts
│ └── tsconfig.json
├── socket.io-client/
│ ├── .prettierignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── RELEASING.md
│ ├── babel.config.js
│ ├── docs/
│ │ └── README.md
│ ├── lib/
│ │ ├── browser-entrypoint.ts
│ │ ├── contrib/
│ │ │ └── backo2.ts
│ │ ├── index.ts
│ │ ├── manager.ts
│ │ ├── on.ts
│ │ ├── socket.ts
│ │ └── url.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── bundle-size.js
│ │ ├── package.esm.json
│ │ ├── rollup.config.esm.js
│ │ ├── rollup.config.umd.js
│ │ └── rollup.config.umd.msgpack.js
│ ├── test/
│ │ ├── .eslintrc.json
│ │ ├── browser-runner.ts
│ │ ├── connection-state-recovery.ts
│ │ ├── connection.ts
│ │ ├── fixtures/
│ │ │ ├── no-unref.ts
│ │ │ ├── unref-during-reconnection.ts
│ │ │ ├── unref-polling-only.ts
│ │ │ ├── unref-websocket-only.ts
│ │ │ └── unref.ts
│ │ ├── index.ts
│ │ ├── node.ts
│ │ ├── retry.ts
│ │ ├── socket.ts
│ │ ├── support/
│ │ │ ├── hooks.ts
│ │ │ ├── server.ts
│ │ │ └── util.ts
│ │ ├── typed-events.test-d.ts
│ │ └── url.ts
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── wdio.conf.js
├── socket.io-cluster-adapter/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── assets/
│ │ └── adapter.excalidraw
│ ├── lib/
│ │ └── index.ts
│ ├── package.json
│ ├── test/
│ │ ├── index.ts
│ │ ├── util.ts
│ │ └── worker.js
│ └── tsconfig.json
├── socket.io-cluster-engine/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── compose.yaml
│ ├── lib/
│ │ ├── cluster.ts
│ │ ├── engine.ts
│ │ ├── index.ts
│ │ └── redis.ts
│ ├── package.json
│ ├── test/
│ │ ├── cluster.ts
│ │ ├── in-memory.ts
│ │ ├── redis.ts
│ │ ├── util.ts
│ │ └── worker.js
│ └── tsconfig.json
├── socket.io-component-emitter/
│ ├── History.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── component.json
│ ├── lib/
│ │ ├── cjs/
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ └── esm/
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ └── package.json
│ ├── package.json
│ └── test/
│ └── emitter.js
├── socket.io-parser/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── Readme.md
│ ├── babel.config.js
│ ├── bench/
│ │ ├── index.js
│ │ └── results.md
│ ├── lib/
│ │ ├── binary.ts
│ │ ├── index.ts
│ │ └── is-binary.ts
│ ├── package.json
│ ├── postcompile.sh
│ ├── support/
│ │ ├── package.cjs.json
│ │ └── package.esm.json
│ ├── test/
│ │ ├── arraybuffer.js
│ │ ├── blob.js
│ │ ├── buffer.js
│ │ ├── helpers.js
│ │ ├── index.js
│ │ ├── parser.js
│ │ └── support/
│ │ └── env.js
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── wdio.conf.js
├── socket.io-postgres-emitter/
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── assets/
│ │ └── emitter.excalidraw
│ ├── compose.yaml
│ ├── lib/
│ │ ├── index.ts
│ │ └── typed-events.ts
│ ├── package.json
│ ├── test/
│ │ ├── index.ts
│ │ └── util.ts
│ └── tsconfig.json
└── socket.io-redis-streams-emitter/
├── CHANGELOG.md
├── LICENSE
├── README.md
├── compose.yaml
├── lib/
│ ├── adapter-types.ts
│ ├── index.ts
│ ├── typed-events.ts
│ └── util.ts
├── package.json
├── test/
│ ├── index.ts
│ └── util.ts
└── tsconfig.json
SYMBOL INDEX (1447 symbols across 180 files)
FILE: docs/engine.io-protocol/v3-test-suite/test-suite.js
constant URL (line 10) | const URL = "http://localhost:3000";
constant WS_URL (line 11) | const WS_URL = URL.replace("http", "ws");
constant PING_INTERVAL (line 13) | const PING_INTERVAL = 300;
constant PING_TIMEOUT (line 14) | const PING_TIMEOUT = 200;
function sleep (line 16) | function sleep(delay) {
function waitFor (line 20) | function waitFor(socket, eventType) {
function decodePayload (line 32) | function decodePayload(payload) {
function initLongPollingSession (line 39) | async function initLongPollingSession(supportsBinary = false) {
FILE: docs/engine.io-protocol/v4-test-suite/test-suite.js
constant URL (line 10) | const URL = "http://localhost:3000";
constant WS_URL (line 11) | const WS_URL = URL.replace("http", "ws");
constant PING_INTERVAL (line 13) | const PING_INTERVAL = 300;
constant PING_TIMEOUT (line 14) | const PING_TIMEOUT = 200;
function sleep (line 16) | function sleep(delay) {
function createWebSocket (line 20) | function createWebSocket(url) {
function waitFor (line 41) | function waitFor(socket, eventType) {
function initLongPollingSession (line 51) | async function initLongPollingSession() {
FILE: docs/socket.io-protocol/v5-test-suite/test-suite.js
constant URL (line 10) | const URL = "http://localhost:3000";
constant WS_URL (line 11) | const WS_URL = URL.replace("http", "ws");
constant PING_INTERVAL (line 13) | const PING_INTERVAL = 300;
constant PING_TIMEOUT (line 14) | const PING_TIMEOUT = 200;
function sleep (line 16) | function sleep(delay) {
function createWebSocket (line 20) | function createWebSocket(url) {
function waitFor (line 41) | function waitFor(socket, eventType) {
function waitForPackets (line 51) | function waitForPackets(socket, count) {
function initLongPollingSession (line 70) | async function initLongPollingSession() {
function initSocketIOConnection (line 76) | async function initSocketIOConnection() {
FILE: examples/ReactNativeExample/App.tsx
type SectionProps (line 30) | type SectionProps = PropsWithChildren<{
function Section (line 34) | function Section({children, title}: SectionProps): React.JSX.Element {
function App (line 60) | function App(): React.JSX.Element {
FILE: examples/angular-todomvc/e2e/protractor.conf.js
method onPrepare (line 27) | onPrepare() {
FILE: examples/angular-todomvc/e2e/src/app.po.ts
class AppPage (line 3) | class AppPage {
method navigateTo (line 4) | async navigateTo(): Promise<unknown> {
method getTitleText (line 8) | async getTitleText(): Promise<string> {
FILE: examples/angular-todomvc/server.ts
type Todo (line 10) | interface Todo {
FILE: examples/angular-todomvc/src/app/app.component.ts
class AppComponent (line 9) | class AppComponent {
method constructor (line 13) | constructor(todoStore: RemoteTodoStore) {
method stopEditing (line 17) | stopEditing(todo: Todo, editedTitle: string) {
method cancelEditingTodo (line 22) | cancelEditingTodo(todo: Todo) {
method updateEditingTodo (line 26) | updateEditingTodo(todo: Todo, editedTitle: string) {
method editTodo (line 37) | editTodo(todo: Todo) {
method removeCompleted (line 41) | removeCompleted() {
method toggleCompletion (line 45) | toggleCompletion(todo: Todo) {
method remove (line 49) | remove(todo: Todo){
method addTodo (line 53) | addTodo() {
FILE: examples/angular-todomvc/src/app/app.module.ts
class AppModule (line 19) | class AppModule { }
FILE: examples/angular-todomvc/src/app/store.ts
class Todo (line 3) | class Todo {
method title (line 8) | get title() {
method title (line 11) | set title(value: String) {
method constructor (line 15) | constructor(title: String) {
class TodoStore (line 22) | class TodoStore {
method constructor (line 25) | constructor() {
method updateStore (line 35) | protected updateStore() {
method getWithCompleted (line 39) | private getWithCompleted(completed: boolean) {
method allCompleted (line 43) | allCompleted() {
method setAllTo (line 47) | setAllTo(completed: boolean) {
method removeCompleted (line 52) | removeCompleted() {
method getRemaining (line 57) | getRemaining() {
method getCompleted (line 61) | getCompleted() {
method toggleCompletion (line 65) | toggleCompletion(todo: Todo) {
method remove (line 70) | remove(todo: Todo) {
method add (line 75) | add(title: String) {
class RemoteTodoStore (line 81) | class RemoteTodoStore extends TodoStore {
method constructor (line 84) | constructor() {
method updateStore (line 92) | protected updateStore() {
FILE: examples/basic-crud-application/angular-client/src/app/app.component.ts
class AppComponent (line 15) | class AppComponent {
method constructor (line 18) | constructor(readonly todoStore: TodoStore) {
method stopEditing (line 21) | stopEditing(todo: Todo, editedTitle: string) {
method cancelEditingTodo (line 26) | cancelEditingTodo(todo: Todo) {
method updateEditingTodo (line 30) | updateEditingTodo(todo: Todo, editedTitle: string) {
method editTodo (line 41) | editTodo(todo: Todo) {
method removeCompleted (line 45) | removeCompleted() {
method toggleCompletion (line 49) | toggleCompletion(todo: Todo) {
method remove (line 53) | remove(todo: Todo){
method addTodo (line 57) | addTodo() {
FILE: examples/basic-crud-application/angular-client/src/app/store.ts
type Todo (line 6) | interface Todo {
class TodoStore (line 23) | class TodoStore {
method constructor (line 27) | constructor() {
method getWithCompleted (line 64) | private getWithCompleted(completed: boolean) {
method allCompleted (line 68) | allCompleted() {
method setAllTo (line 72) | setAllTo(completed: boolean) {
method removeCompleted (line 86) | removeCompleted() {
method getRemaining (line 97) | getRemaining() {
method getCompleted (line 101) | getCompleted() {
method toggleCompletion (line 105) | toggleCompletion(todo: Todo) {
method remove (line 117) | remove(todo: Todo) {
method add (line 126) | add(title: string) {
FILE: examples/basic-crud-application/common/events.ts
type TodoID (line 1) | type TodoID = string;
type Todo (line 3) | interface Todo {
type Error (line 9) | interface Error {
type Success (line 18) | interface Success<T> {
type Response (line 22) | type Response<T> = Error | Success<T>;
type ServerEvents (line 24) | interface ServerEvents {
type ClientEvents (line 30) | interface ClientEvents {
FILE: examples/basic-crud-application/server-postgres-cluster/lib/app.js
function createApplication (line 6) | function createApplication(httpServer, components, serverOptions = {}) {
FILE: examples/basic-crud-application/server-postgres-cluster/lib/todo-management/todo.repository.js
class CrudRepository (line 4) | class CrudRepository {
method findAll (line 5) | findAll() {}
method findById (line 6) | findById(id) {}
method save (line 7) | save(entity) {}
method deleteById (line 8) | deleteById(id) {}
class TodoRepository (line 11) | class TodoRepository extends CrudRepository {}
class Todo (line 13) | class Todo extends Model {}
class PostgresTodoRepository (line 15) | class PostgresTodoRepository extends TodoRepository {
method constructor (line 16) | constructor(sequelize) {
method findAll (line 41) | findAll() {
method findById (line 47) | async findById(id) {
method save (line 59) | save(entity) {
method deleteById (line 65) | async deleteById(id) {
FILE: examples/basic-crud-application/server-postgres-cluster/lib/util.js
function sanitizeErrorMessage (line 8) | function sanitizeErrorMessage(message) {
function mapErrorDetails (line 16) | function mapErrorDetails(details) {
FILE: examples/basic-crud-application/server/lib/app.ts
type Components (line 7) | interface Components {
function createApplication (line 11) | function createApplication(
FILE: examples/basic-crud-application/server/lib/todo-management/todo.repository.ts
class InMemoryTodoRepository (line 13) | class InMemoryTodoRepository extends TodoRepository {
method findAll (line 16) | findAll(): Promise<Todo[]> {
method findById (line 21) | findById(id: TodoID): Promise<Todo> {
method save (line 29) | save(entity: Todo): Promise<void> {
method deleteById (line 34) | deleteById(id: TodoID): Promise<void> {
FILE: examples/basic-crud-application/server/lib/util.ts
type Errors (line 3) | enum Errors {
function sanitizeErrorMessage (line 10) | function sanitizeErrorMessage(message: any) {
function mapErrorDetails (line 18) | function mapErrorDetails(details: ValidationErrorItem[]) {
FILE: examples/basic-crud-application/vue-client/src/socket.js
constant URL (line 4) | const URL =
FILE: examples/basic-crud-application/vue-client/src/stores/todo.js
method remaining (line 10) | remaining(state) {
method bindEvents (line 22) | bindEvents() {
method add (line 53) | add(title) {
method setTitle (line 65) | setTitle(todo, title) {
method delete (line 70) | delete(todo) {
method deleteCompleted (line 81) | deleteCompleted() {
method toggleOne (line 93) | toggleOne(todo) {
method toggleAll (line 98) | toggleAll(onlyActive) {
FILE: examples/basic-websocket-client/src/index.js
class EventEmitter (line 1) | class EventEmitter {
method on (line 4) | on(event, listener) {
method emit (line 12) | emit(event, ...args) {
function noop (line 36) | function noop() {}
class Socket (line 38) | class Socket extends EventEmitter {
method constructor (line 51) | constructor(uri, opts) {
method #open (line 64) | #open() {
method #createUrl (line 72) | #createUrl() {
method #onMessage (line 78) | #onMessage(data) {
method #onOpen (line 114) | #onOpen(data) {
method #onPacket (line 126) | #onPacket(packet) {
method #onConnect (line 147) | #onConnect(packet) {
method #onClose (line 157) | #onClose(reason) {
method #resetPingTimeout (line 182) | #resetPingTimeout() {
method #send (line 189) | #send(data) {
method #sendPacket (line 195) | #sendPacket(packet) {
method #doConnect (line 199) | #doConnect() {
method emit (line 203) | emit(...args) {
method disconnect (line 216) | disconnect() {
function encode (line 222) | function encode(packet) {
function decode (line 232) | function decode(data) {
function isPacketValid (line 250) | function isPacketValid(packet) {
function io (line 267) | function io(uri, opts) {
FILE: examples/basic-websocket-client/test/index.js
function waitFor (line 10) | function waitFor(emitter, eventName) {
function sleep (line 16) | function sleep(delay) {
FILE: examples/cluster-engine-node-cluster/client.js
constant CLIENTS_COUNT (line 3) | const CLIENTS_COUNT = 3;
FILE: examples/cluster-engine-redis/client.js
constant CLIENTS_COUNT (line 3) | const CLIENTS_COUNT = 3;
FILE: examples/cluster-engine-redis/server.js
function initServer (line 10) | async function initServer(port) {
function initProxy (line 41) | function initProxy() {
FILE: examples/cluster-haproxy/server/public/main.js
function addParticipantsMessage (line 28) | function addParticipantsMessage (data) {
function setUsername (line 39) | function setUsername () {
function sendMessage (line 55) | function sendMessage () {
function log (line 72) | function log (message, options) {
function addChatMessage (line 78) | function addChatMessage (data, options) {
function addChatTyping (line 103) | function addChatTyping (data) {
function removeChatTyping (line 110) | function removeChatTyping (data) {
function addMessageElement (line 121) | function addMessageElement (el, options) {
function cleanInput (line 148) | function cleanInput (input) {
function updateTyping (line 153) | function updateTyping () {
function getTypingMessages (line 173) | function getTypingMessages (data) {
function getUsernameColor (line 180) | function getUsernameColor (username) {
FILE: examples/cluster-httpd/server/public/main.js
function addParticipantsMessage (line 28) | function addParticipantsMessage (data) {
function setUsername (line 39) | function setUsername () {
function sendMessage (line 55) | function sendMessage () {
function log (line 72) | function log (message, options) {
function addChatMessage (line 78) | function addChatMessage (data, options) {
function addChatTyping (line 103) | function addChatTyping (data) {
function removeChatTyping (line 110) | function removeChatTyping (data) {
function addMessageElement (line 121) | function addMessageElement (el, options) {
function cleanInput (line 148) | function cleanInput (input) {
function updateTyping (line 153) | function updateTyping () {
function getTypingMessages (line 173) | function getTypingMessages (data) {
function getUsernameColor (line 180) | function getUsernameColor (username) {
FILE: examples/cluster-nginx/server/public/main.js
function addParticipantsMessage (line 28) | function addParticipantsMessage (data) {
function setUsername (line 39) | function setUsername () {
function sendMessage (line 55) | function sendMessage () {
function log (line 72) | function log (message, options) {
function addChatMessage (line 78) | function addChatMessage (data, options) {
function addChatTyping (line 103) | function addChatTyping (data) {
function removeChatTyping (line 110) | function removeChatTyping (data) {
function addMessageElement (line 121) | function addMessageElement (el, options) {
function cleanInput (line 148) | function cleanInput (input) {
function updateTyping (line 153) | function updateTyping () {
function getTypingMessages (line 173) | function getTypingMessages (data) {
function getUsernameColor (line 180) | function getUsernameColor (username) {
FILE: examples/cluster-traefik/server/public/main.js
function addParticipantsMessage (line 28) | function addParticipantsMessage (data) {
function setUsername (line 39) | function setUsername () {
function sendMessage (line 55) | function sendMessage () {
function log (line 72) | function log (message, options) {
function addChatMessage (line 78) | function addChatMessage (data, options) {
function addChatTyping (line 103) | function addChatTyping (data) {
function removeChatTyping (line 110) | function removeChatTyping (data) {
function addMessageElement (line 121) | function addMessageElement (el, options) {
function cleanInput (line 148) | function cleanInput (input) {
function updateTyping (line 153) | function updateTyping () {
function getTypingMessages (line 173) | function getTypingMessages (data) {
function getUsernameColor (line 180) | function getUsernameColor (username) {
FILE: examples/create-react-app-example/src/App.js
function App (line 8) | function App() {
FILE: examples/create-react-app-example/src/serviceWorker.js
function register (line 23) | function register(config) {
function registerValidSW (line 57) | function registerValidSW(swUrl, config) {
function checkValidServiceWorker (line 101) | function checkValidServiceWorker(swUrl, config) {
function unregister (line 131) | function unregister() {
FILE: examples/custom-parsers/src/custom-parser.js
constant TYPES (line 9) | const TYPES = {
class Encoder (line 42) | class Encoder {
method encode (line 43) | encode (packet) {
method pack (line 51) | pack (packet) {
class Decoder (line 73) | class Decoder extends Emitter {
method add (line 74) | add (obj) {
method parseJSON (line 81) | parseJSON (obj) {
method parseBinary (line 89) | parseBinary (obj) {
method destroy (line 121) | destroy () {}
FILE: examples/custom-parsers/src/server.js
function onConnect (line 49) | function onConnect (delay) {
FILE: examples/expo-example/App.js
function App (line 5) | function App() {
FILE: examples/express-session-example/ts/index.ts
type SessionData (line 8) | interface SessionData {
FILE: examples/nestjs-example/src/app.controller.ts
class AppController (line 5) | class AppController {
method constructor (line 6) | constructor(private readonly appService: AppService) {}
method root (line 10) | root() {
FILE: examples/nestjs-example/src/app.module.ts
class AppModule (line 11) | class AppModule {}
FILE: examples/nestjs-example/src/app.service.ts
class AppService (line 4) | class AppService {
method getHello (line 5) | getHello(): string {
FILE: examples/nestjs-example/src/events/events.gateway.ts
class EventsGateway (line 10) | class EventsGateway {
method handleEvent (line 15) | handleEvent(@MessageBody() data: string): string {
FILE: examples/nestjs-example/src/events/events.module.ts
class EventsModule (line 7) | class EventsModule {}
FILE: examples/nestjs-example/src/main.ts
function bootstrap (line 6) | async function bootstrap() {
FILE: examples/nextjs-app-router/src/app/layout.js
function RootLayout (line 11) | function RootLayout({ children }) {
FILE: examples/nextjs-app-router/src/app/page.js
function Home (line 8) | function Home() {
FILE: examples/nextjs-pages-router/src/pages/_app.js
function App (line 3) | function App({ Component, pageProps }) {
FILE: examples/nextjs-pages-router/src/pages/_document.js
function Document (line 3) | function Document() {
FILE: examples/nextjs-pages-router/src/pages/api/hello.js
function handler (line 3) | function handler(req, res) {
FILE: examples/nextjs-pages-router/src/pages/index.js
function Home (line 10) | function Home() {
FILE: examples/nuxt-example/server/plugins/socket.io.ts
method handler (line 17) | handler(event) {
method open (line 22) | open(peer) {
FILE: examples/nwjs-example/index.js
function onConnect (line 6) | function onConnect() {
FILE: examples/passport-example/cjs/index.js
function onlyForHandshake (line 80) | function onlyForHandshake(middleware) {
FILE: examples/passport-example/esm/index.js
function onlyForHandshake (line 83) | function onlyForHandshake(middleware) {
FILE: examples/passport-example/ts/index.ts
type User (line 14) | interface User {
function onlyForHandshake (line 94) | function onlyForHandshake(
FILE: examples/passport-jwt-example/ts/index.ts
type User (line 14) | interface User {
FILE: examples/postgres-adapter-example/client.js
constant CLIENTS_COUNT (line 3) | const CLIENTS_COUNT = 3;
constant PORTS (line 4) | const PORTS = [3000, 3001, 3002];
FILE: examples/postgres-adapter-example/cluster.js
constant SERVERS_COUNT (line 3) | const SERVERS_COUNT = 3;
FILE: examples/postgres-adapter-example/server.js
constant PORT (line 6) | const PORT = process.env.PORT || 3000;
FILE: examples/private-messaging/server/cluster.js
constant WORKERS_COUNT (line 5) | const WORKERS_COUNT = 4;
FILE: examples/private-messaging/server/messageStore.js
class MessageStore (line 1) | class MessageStore {
method saveMessage (line 2) | saveMessage(message) {}
method findMessagesForUser (line 3) | findMessagesForUser(userID) {}
class InMemoryMessageStore (line 6) | class InMemoryMessageStore extends MessageStore {
method constructor (line 7) | constructor() {
method saveMessage (line 12) | saveMessage(message) {
method findMessagesForUser (line 16) | findMessagesForUser(userID) {
constant CONVERSATION_TTL (line 23) | const CONVERSATION_TTL = 24 * 60 * 60;
class RedisMessageStore (line 25) | class RedisMessageStore extends MessageStore {
method constructor (line 26) | constructor(redisClient) {
method saveMessage (line 31) | saveMessage(message) {
method findMessagesForUser (line 42) | findMessagesForUser(userID) {
FILE: examples/private-messaging/server/sessionStore.js
class SessionStore (line 1) | class SessionStore {
method findSession (line 2) | findSession(id) {}
method saveSession (line 3) | saveSession(id, session) {}
method findAllSessions (line 4) | findAllSessions() {}
class InMemorySessionStore (line 7) | class InMemorySessionStore extends SessionStore {
method constructor (line 8) | constructor() {
method findSession (line 13) | findSession(id) {
method saveSession (line 17) | saveSession(id, session) {
method findAllSessions (line 21) | findAllSessions() {
constant SESSION_TTL (line 26) | const SESSION_TTL = 24 * 60 * 60;
class RedisSessionStore (line 30) | class RedisSessionStore extends SessionStore {
method constructor (line 31) | constructor(redisClient) {
method findSession (line 36) | findSession(id) {
method saveSession (line 42) | saveSession(id, { userID, username, connected }) {
method findAllSessions (line 58) | async findAllSessions() {
FILE: examples/private-messaging/src/socket.js
constant URL (line 3) | const URL = "http://localhost:3000";
FILE: examples/tweet-stream/index.js
constant MAX_TWEETS (line 20) | const MAX_TWEETS = 10;
FILE: examples/typescript-client-example/cjs/client.ts
type ServerToClientEvents (line 3) | interface ServerToClientEvents {
type ClientToServerEvents (line 7) | interface ClientToServerEvents {
FILE: examples/typescript-client-example/esm/client.ts
type ServerToClientEvents (line 3) | interface ServerToClientEvents {
type ClientToServerEvents (line 7) | interface ClientToServerEvents {
FILE: examples/whiteboard/index.js
function onConnection (line 10) | function onConnection(socket){
FILE: examples/whiteboard/public/main.js
function drawLine (line 36) | function drawLine(x0, y0, x1, y1, color, emit){
function onMouseDown (line 58) | function onMouseDown(e){
function onMouseUp (line 64) | function onMouseUp(e){
function onMouseMove (line 70) | function onMouseMove(e){
function onColorUpdate (line 77) | function onColorUpdate(e){
function throttle (line 82) | function throttle(callback, delay) {
function onDrawingEvent (line 94) | function onDrawingEvent(data){
function onResize (line 101) | function onResize() {
FILE: packages/engine.io-client/lib/contrib/parseqs.ts
function encode (line 10) | function encode (obj) {
function decode (line 30) | function decode (qs) {
FILE: packages/engine.io-client/lib/contrib/parseuri.ts
function parse (line 26) | function parse(str: string) {
function pathNames (line 60) | function pathNames(obj, path) {
function queryKey (line 74) | function queryKey(uri, query) {
FILE: packages/engine.io-client/lib/globals.node.ts
function createCookieJar (line 5) | function createCookieJar() {
type Cookie (line 9) | interface Cookie {
function parse (line 18) | function parse(setCookieString: string): Cookie {
class CookieJar (line 70) | class CookieJar {
method parseCookies (line 73) | public parseCookies(values: string[]) {
method cookies (line 85) | get cookies() {
method addCookies (line 95) | public addCookies(xhr: any) {
method appendCookies (line 108) | public appendCookies(headers: Headers) {
FILE: packages/engine.io-client/lib/globals.ts
function createCookieJar (line 23) | function createCookieJar() {}
FILE: packages/engine.io-client/lib/socket.ts
constant OFFLINE_EVENT_LISTENERS (line 23) | const OFFLINE_EVENT_LISTENERS = [];
type SocketOptions (line 41) | interface SocketOptions {
type TransportCtor (line 263) | type TransportCtor = { new (o: any): Transport };
type BaseSocketOptions (line 265) | type BaseSocketOptions = Omit<SocketOptions, "transports"> & {
type HandshakeData (line 269) | interface HandshakeData {
type SocketReservedEvents (line 277) | interface SocketReservedEvents {
type SocketState (line 296) | type SocketState = "opening" | "open" | "closing" | "closed";
type WriteOptions (line 298) | interface WriteOptions {
class SocketWithoutUpgrade (line 325) | class SocketWithoutUpgrade extends Emitter<
method constructor (line 373) | constructor(uri: string | BaseSocketOptions, opts: BaseSocketOptions) {
method createTransport (line 493) | protected createTransport(name: string) {
method _open (line 529) | private _open() {
method setTransport (line 556) | protected setTransport(transport: Transport) {
method onOpen (line 580) | protected onOpen() {
method _onPacket (line 594) | private _onPacket(packet: Packet) {
method onHandshake (line 642) | protected onHandshake(data: HandshakeData) {
method _resetPingTimeout (line 660) | private _resetPingTimeout() {
method _onDrain (line 677) | private _onDrain() {
method flush (line 697) | protected flush() {
method _getWritablePackets (line 720) | private _getWritablePackets() {
method _hasPingExpired (line 753) | _hasPingExpired() {
method write (line 777) | public write(msg: RawData, options?: WriteOptions, fn?: () => void) {
method send (line 790) | public send(msg: RawData, options?: WriteOptions, fn?: () => void) {
method _sendPacket (line 804) | private _sendPacket(
method close (line 841) | public close() {
method _onError (line 886) | private _onError(err: Error) {
method _onClose (line 909) | private _onClose(reason: string, description?: CloseDetails | Error) {
class SocketWithUpgrade (line 986) | class SocketWithUpgrade extends SocketWithoutUpgrade {
method onOpen (line 989) | override onOpen() {
method _probe (line 1006) | private _probe(name: string) {
method onHandshake (line 1126) | override onHandshake(data: HandshakeData) {
method _filterUpgrades (line 1137) | private _filterUpgrades(upgrades: string[]) {
class Socket (line 1166) | class Socket extends SocketWithUpgrade {
method constructor (line 1169) | constructor(uri?: string | SocketOptions, opts: SocketOptions = {}) {
FILE: packages/engine.io-client/lib/transport.ts
class TransportError (line 11) | class TransportError extends Error {
method constructor (line 14) | constructor(
type CloseDetails (line 23) | interface CloseDetails {
type TransportReservedEvents (line 28) | interface TransportReservedEvents {
type TransportState (line 38) | type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
method constructor (line 60) | constructor(opts) {
method onError (line 79) | protected onError(reason: string, description: any, context?: any) {
method open (line 90) | public open() {
method close (line 100) | public close() {
method send (line 114) | public send(packets) {
method onOpen (line 128) | protected onOpen() {
method onData (line 140) | protected onData(data: RawData) {
method onPacket (line 150) | protected onPacket(packet: Packet) {
method onClose (line 159) | protected onClose(details?: CloseDetails) {
method pause (line 174) | public pause(onPause: () => void) {}
method createUri (line 176) | protected createUri(schema: string, query: Record<string, unknown> = {}) {
method _hostname (line 187) | private _hostname() {
method _port (line 192) | private _port() {
method _query (line 204) | private _query(query: Record<string, unknown>) {
FILE: packages/engine.io-client/lib/transports/polling-fetch.ts
class Fetch (line 13) | class Fetch extends Polling {
method doPoll (line 14) | override doPoll() {
method doWrite (line 28) | override doWrite(data: string, callback: () => void) {
method _fetch (line 42) | private _fetch(data?: string) {
FILE: packages/engine.io-client/lib/transports/polling-xhr.node.ts
class XHR (line 13) | class XHR extends BaseXHR {
method request (line 14) | request(opts: Record<string, any> = {}) {
FILE: packages/engine.io-client/lib/transports/polling-xhr.ts
function empty (line 13) | function empty() {}
method constructor (line 26) | constructor(opts) {
method doWrite (line 59) | override doWrite(data, fn) {
method doPoll (line 75) | override doPoll() {
type RequestReservedEvents (line 86) | interface RequestReservedEvents {
type RequestOptions (line 92) | type RequestOptions = SocketOptions & {
class Request (line 99) | class Request extends Emitter<
method constructor (line 122) | constructor(
method _create (line 143) | private _create() {
method _onError (line 239) | private _onError(err: number | Error) {
method _cleanup (line 249) | private _cleanup(fromError?) {
method _onLoad (line 273) | private _onLoad() {
method abort (line 287) | public abort() {
function unloadHandler (line 309) | function unloadHandler() {
class XHR (line 331) | class XHR extends BaseXHR {
method constructor (line 332) | constructor(opts) {
method request (line 338) | request(opts: Record<string, any> = {}) {
function newRequest (line 344) | function newRequest(opts) {
FILE: packages/engine.io-client/lib/transports/polling.ts
method name (line 11) | override get name() {
method doOpen (line 21) | override doOpen() {
method pause (line 31) | override pause(onPause) {
method _poll (line 70) | private _poll() {
method onData (line 82) | override onData(data) {
method doClose (line 122) | override doClose() {
method write (line 145) | override write(packets) {
method uri (line 161) | protected uri() {
FILE: packages/engine.io-client/lib/transports/websocket.node.ts
class WS (line 13) | class WS extends BaseWS {
method createSocket (line 14) | createSocket(
method doWrite (line 33) | doWrite(packet: Packet, data: RawData) {
FILE: packages/engine.io-client/lib/transports/websocket.ts
method name (line 19) | override get name() {
method doOpen (line 23) | override doOpen() {
method addEventListeners (line 75) | private addEventListeners() {
method write (line 91) | override write(packets) {
method doClose (line 124) | override doClose() {
method uri (line 137) | private uri() {
class WS (line 166) | class WS extends BaseWS {
method createSocket (line 167) | createSocket(
method doWrite (line 179) | doWrite(_packet: Packet, data: RawData) {
FILE: packages/engine.io-client/lib/transports/webtransport.ts
class WT (line 20) | class WT extends Transport {
method name (line 24) | get name() {
method doOpen (line 28) | protected doOpen() {
method write (line 90) | protected write(packets: Packet[]) {
method doClose (line 108) | protected doClose() {
FILE: packages/engine.io-client/lib/util.ts
function pick (line 3) | function pick(obj, ...attr) {
constant NATIVE_SET_TIMEOUT (line 13) | const NATIVE_SET_TIMEOUT = globalThis.setTimeout;
constant NATIVE_CLEAR_TIMEOUT (line 14) | const NATIVE_CLEAR_TIMEOUT = globalThis.clearTimeout;
function installTimerFunctions (line 16) | function installTimerFunctions(obj, opts) {
constant BASE64_OVERHEAD (line 27) | const BASE64_OVERHEAD = 1.33;
function byteLength (line 30) | function byteLength(obj) {
function utf8Length (line 38) | function utf8Length(str) {
function randomString (line 60) | function randomString() {
FILE: packages/engine.io-client/support/bundle-size.js
function format (line 16) | function format(size) {
function main (line 20) | async function main() {
FILE: packages/engine.io-client/test/connection.js
function testBinary (line 132) | function testBinary(data) {
FILE: packages/engine.io-client/test/support/hooks.js
method beforeAll (line 15) | beforeAll() {
method afterAll (line 84) | afterAll() {
FILE: packages/engine.io-client/test/util-wt.mjs
function _dnToAsn1 (line 16) | function _dnToAsn1(obj) {
function _dateToAsn1 (line 71) | function _dateToAsn1(date) {
function _signatureParametersToAsn1 (line 98) | function _signatureParametersToAsn1(oid, params) {
function getTBSCertificate (line 171) | function getTBSCertificate(cert) {
function toPositiveHex (line 273) | function toPositiveHex(hexString) {
function generateWebTransportCertificate (line 296) | async function generateWebTransportCertificate(attrs, options) {
FILE: packages/engine.io-client/test/webtransport.mjs
function setup (line 14) | async function setup(opts, cb) {
function createHttpServer (line 56) | function createHttpServer(port) {
function success (line 76) | function success(engine, h3server, done) {
function createSocket (line 82) | function createSocket(port, certificate, opts) {
FILE: packages/engine.io-parser/lib/commons.ts
constant PACKET_TYPES (line 1) | const PACKET_TYPES = Object.create(null);
constant PACKET_TYPES_REVERSE (line 10) | const PACKET_TYPES_REVERSE = Object.create(null);
constant ERROR_PACKET (line 15) | const ERROR_PACKET: Packet = { type: "error", data: "parser error" };
type PacketType (line 19) | type PacketType =
type RawData (line 31) | type RawData = any;
type Packet (line 33) | interface Packet {
type BinaryType (line 43) | type BinaryType = "nodebuffer" | "arraybuffer" | "blob";
FILE: packages/engine.io-parser/lib/encodePacket.browser.ts
function toArray (line 53) | function toArray(data: BufferSource) {
constant TEXT_ENCODER (line 63) | let TEXT_ENCODER;
function encodePacketToBinary (line 65) | function encodePacketToBinary(
FILE: packages/engine.io-parser/lib/encodePacket.ts
constant TEXT_ENCODER (line 30) | let TEXT_ENCODER;
function encodePacketToBinary (line 32) | function encodePacketToBinary(
FILE: packages/engine.io-parser/lib/index.ts
constant SEPARATOR (line 11) | const SEPARATOR = String.fromCharCode(30);
function createPacketEncoderStream (line 49) | function createPacketEncoderStream(): any {
constant TEXT_DECODER (line 81) | let TEXT_DECODER;
function totalLength (line 83) | function totalLength(chunks: Uint8Array[]) {
function concatChunks (line 87) | function concatChunks(chunks: Uint8Array[], size: number) {
type State (line 106) | const enum State {
function createPacketDecoderStream (line 113) | function createPacketDecoderStream(
FILE: packages/engine.io/examples/latency/public/index.js
function $ (line 11) | function $ (id) { return document.getElementById(id); }
function render (line 18) | function render () {
function send (line 34) | function send () {
FILE: packages/engine.io/examples/memory-usage-webtransport/client.js
constant CLIENTS_COUNT (line 7) | const CLIENTS_COUNT = 100;
FILE: packages/engine.io/examples/memory-usage-webtransport/server.js
constant PACKETS_COUNT (line 8) | const PACKETS_COUNT = 100;
constant PACKET_SIZE (line 9) | const PACKET_SIZE = 100;
function formatSize (line 38) | function formatSize(val) {
FILE: packages/engine.io/examples/memory-usage/client.js
constant CLIENTS_COUNT (line 3) | const CLIENTS_COUNT = 100;
FILE: packages/engine.io/examples/memory-usage/server.js
constant EMIT_INTERVAL_MS (line 4) | const EMIT_INTERVAL_MS = 10_000;
constant PACKETS_COUNT (line 5) | const PACKETS_COUNT = 100;
constant PACKET_SIZE (line 6) | const PACKET_SIZE = 100;
function formatSize (line 28) | function formatSize(val) {
FILE: packages/engine.io/lib/contrib/types.cookie.ts
type CookieSerializeOptions (line 9) | interface CookieSerializeOptions {
FILE: packages/engine.io/lib/engine.io.ts
function listen (line 27) | function listen(
function attach (line 59) | function attach(
FILE: packages/engine.io/lib/parser-v3/index.ts
constant EMPTY_BUFFER (line 45) | const EMPTY_BUFFER = Buffer.concat([]);
function encodePacket (line 62) | function encodePacket (packet: any, supportsBinary?: any, utf8encode?: a...
function encodeBuffer (line 94) | function encodeBuffer(packet, supportsBinary, callback) {
function encodeBase64Packet (line 112) | function encodeBase64Packet (packet, callback){
function decodePacket (line 126) | function decodePacket (data: any, binaryType?: any, utf8decode?: any): a...
function tryDecode (line 176) | function tryDecode(data) {
function decodeBase64Packet (line 192) | function decodeBase64Packet (msg, binaryType) {
function encodePayload (line 222) | function encodePayload (packets, supportsBinary, callback) {
function setLengthHeader (line 247) | function setLengthHeader(message) {
function map (line 255) | function map(ary, each, done) {
function decodePayload (line 277) | function decodePayload (data: any, binaryType?: any, callback?: any) {
function bufferToString (line 346) | function bufferToString(buffer) {
function stringToBuffer (line 361) | function stringToBuffer(string) {
function arrayBufferToBuffer (line 376) | function arrayBufferToBuffer(data) {
function encodePayloadAsBinary (line 398) | function encodePayloadAsBinary (packets, callback) {
function encodeOneBinaryPacket (line 408) | function encodeOneBinaryPacket(p, doneCallback) {
function decodePayloadAsBinary (line 449) | function decodePayloadAsBinary (data, binaryType, callback) {
FILE: packages/engine.io/lib/parser-v3/utf8.ts
function ucs2decode (line 6) | function ucs2decode(string) {
function ucs2encode (line 33) | function ucs2encode(array) {
function checkScalarValue (line 50) | function checkScalarValue(codePoint, strict) {
function createByte (line 64) | function createByte(codePoint, shift) {
function encodeCodePoint (line 68) | function encodeCodePoint(codePoint, strict) {
function utf8encode (line 92) | function utf8encode(string, opts) {
function readContinuationByte (line 110) | function readContinuationByte() {
function decodeSymbol (line 126) | function decodeSymbol(strict) {
function utf8decode (line 191) | function utf8decode(byteString, opts) {
FILE: packages/engine.io/lib/server.ts
type TransportName (line 29) | type TransportName = "polling" | "websocket" | "webtransport";
type ErrorCallback (line 31) | type ErrorCallback = (
type AttachOptions (line 36) | interface AttachOptions {
type ServerOptions (line 60) | interface ServerOptions {
type Middleware (line 154) | type Middleware = (
function parseSessionId (line 160) | function parseSessionId(data: string): string | undefined {
method constructor (line 182) | constructor(opts: ServerOptions = {}) {
method _computePath (line 242) | protected _computePath(options: AttachOptions) {
method upgrades (line 256) | public upgrades(transport: TransportName): string[] {
method verify (line 270) | protected verify(
method use (line 356) | public use(fn: any) {
method _applyMiddlewares (line 368) | protected _applyMiddlewares(
method close (line 399) | public close() {
method generateId (line 418) | public generateId(req: IncomingMessage): string | PromiseLike<string> {
method handshake (line 431) | protected async handshake(
method onWebTransportSession (line 526) | public async onWebTransportSession(session: any) {
class WebSocketResponse (line 644) | class WebSocketResponse {
method constructor (line 645) | constructor(
method setHeader (line 653) | public setHeader(name: string, value: any) {
method getHeader (line 657) | public getHeader(name: string) {
method removeHeader (line 661) | public removeHeader(name: string) {
method write (line 665) | public write() {}
method writeHead (line 667) | public writeHead() {}
method end (line 669) | public end() {
class Server (line 678) | class Server extends BaseServer {
method init (line 687) | protected init() {
method cleanup (line 721) | protected cleanup() {
method prepare (line 734) | private prepare(req: EngineRequest) {
method createTransport (line 742) | protected createTransport(
method handleRequest (line 756) | public handleRequest(req: EngineRequest, res: ServerResponse) {
method handleUpgrade (line 799) | public handleUpgrade(
method onWebSocket (line 848) | private onWebSocket(
method attach (line 917) | public attach(server: HttpServer, options: AttachOptions = {}) {
function abortRequest (line 980) | function abortRequest(
function abortUpgrade (line 1008) | function abortUpgrade(
function checkInvalidHeaderChar (line 1067) | function checkInvalidHeaderChar(val?: string) {
FILE: packages/engine.io/lib/socket.ts
type SendOptions (line 12) | interface SendOptions {
type ReadyState (line 16) | type ReadyState = "opening" | "open" | "closing" | "closed";
type SendCallback (line 18) | type SendCallback = (transport: Transport) => void;
class Socket (line 20) | class Socket extends EventEmitter {
method readyState (line 70) | get readyState() {
method readyState (line 74) | set readyState(state: ReadyState) {
method constructor (line 79) | constructor(
method onOpen (line 116) | private onOpen() {
method onPacket (line 153) | private onPacket(packet: Packet) {
method onError (line 201) | private onError(err: Error) {
method schedulePing (line 212) | private schedulePing() {
method resetPingTimeout (line 228) | private resetPingTimeout() {
method setTransport (line 247) | private setTransport(transport: Transport) {
method onDrain (line 275) | private onDrain() {
method _maybeUpgrade (line 293) | _maybeUpgrade(transport: Transport) {
method clearTransport (line 387) | private clearTransport() {
method onClose (line 413) | private onClose(reason: string, description?) {
method send (line 441) | public send(data: RawData, options?: SendOptions, callback?: SendCallb...
method write (line 453) | public write(data: RawData, options?: SendOptions, callback?: SendCall...
method sendPacket (line 468) | private sendPacket(
method flush (line 509) | private flush() {
method getAvailableUpgrades (line 539) | private getAvailableUpgrades() {
method close (line 559) | public close(discard?: boolean) {
method closeTransport (line 593) | private closeTransport(discard: boolean) {
FILE: packages/engine.io/lib/transport.ts
function noop (line 11) | function noop() {}
type ReadyState (line 13) | type ReadyState = "open" | "closing" | "closed";
type EngineRequest (line 15) | type EngineRequest = IncomingMessage & {
method readyState (line 68) | get readyState() {
method readyState (line 72) | set readyState(state: ReadyState) {
method constructor (line 92) | constructor(req: { _query: Record<string, string> }) {
method discard (line 104) | discard() {
method onRequest (line 114) | onRequest(req: any) {}
method close (line 121) | close(fn?: () => void) {
method onError (line 135) | protected onError(msg: string, desc?) {
method onPacket (line 154) | protected onPacket(packet: Packet) {
method onData (line 164) | protected onData(data: RawData) {
method onClose (line 173) | protected onClose() {
FILE: packages/engine.io/lib/transports-uws/polling.ts
class Polling (line 16) | class Polling extends Transport {
method constructor (line 31) | constructor(req) {
method name (line 40) | get name() {
method onRequest (line 51) | onRequest(req) {
method onPollRequest (line 71) | onPollRequest(req, res) {
method onDataRequest (line 113) | onDataRequest(req, res) {
method onDataRequestCleanup (line 210) | private onDataRequestCleanup() {
method onData (line 220) | onData(data) {
method onClose (line 244) | onClose() {
method send (line 258) | send(packets) {
method write (line 293) | write(data, options) {
method doWrite (line 306) | doWrite(data, options, callback) {
method compress (line 363) | compress(data, encoding, callback) {
method doClose (line 386) | doClose(fn) {
method headers (line 418) | headers(req, headers) {
FILE: packages/engine.io/lib/transports-uws/websocket.ts
class WebSocket (line 6) | class WebSocket extends Transport {
method constructor (line 15) | constructor(req) {
method name (line 24) | get name() {
method handlesUpgrades (line 31) | get handlesUpgrades() {
method send (line 41) | send(packets) {
method doClose (line 77) | doClose(fn) {
FILE: packages/engine.io/lib/transports/index.ts
function polling (line 16) | function polling(req: EngineRequest) {
FILE: packages/engine.io/lib/transports/polling-jsonp.ts
class JSONP (line 8) | class JSONP extends Polling {
method constructor (line 15) | constructor(req) {
method onData (line 22) | override onData(data: RawData) {
method doWrite (line 36) | override doWrite(data, options, callback) {
FILE: packages/engine.io/lib/transports/polling.ts
class Polling (line 17) | class Polling extends Transport {
method constructor (line 32) | constructor(req) {
method name (line 41) | get name() {
method onRequest (line 51) | onRequest(req: EngineRequest) {
method onPollRequest (line 71) | private onPollRequest(req: EngineRequest, res: ServerResponse) {
method onDataRequest (line 113) | private onDataRequest(req: IncomingMessage, res: ServerResponse) {
method onData (line 188) | override onData(data: RawData) {
method onClose (line 212) | onClose() {
method send (line 220) | send(packets: Packet[]) {
method write (line 255) | private write(data, options) {
method doWrite (line 268) | protected doWrite(data, options, callback) {
method compress (line 322) | private compress(data, encoding, callback) {
method doClose (line 345) | override doClose(fn: () => void) {
method headers (line 382) | private headers(req: IncomingMessage, headers: Record<string, string> ...
FILE: packages/engine.io/lib/transports/websocket.ts
class WebSocket (line 8) | class WebSocket extends Transport {
method constructor (line 17) | constructor(req: EngineRequest) {
method name (line 34) | get name() {
method handlesUpgrades (line 41) | get handlesUpgrades() {
method send (line 45) | send(packets: Packet[]) {
method _canSendPreEncodedFrame (line 75) | private _canSendPreEncodedFrame(packet: Packet) {
method doClose (line 108) | doClose(fn?: () => void) {
FILE: packages/engine.io/lib/transports/webtransport.ts
class WebTransport (line 10) | class WebTransport extends Transport {
method constructor (line 13) | constructor(
method name (line 47) | get name() {
method send (line 51) | async send(packets) {
method doClose (line 68) | doClose(fn) {
FILE: packages/engine.io/lib/userver.ts
type uOptions (line 9) | interface uOptions {
class uServer (line 31) | class uServer extends BaseServer {
method init (line 32) | protected init() {}
method cleanup (line 33) | protected cleanup() {}
method prepare (line 40) | private prepare(req: HttpRequest & EngineRequest, res: HttpResponse) {
method createTransport (line 62) | protected createTransport(transportName: string, req: EngineRequest) {
method attach (line 71) | public attach(
method _applyMiddlewares (line 102) | override _applyMiddlewares(
method handleRequest (line 123) | private handleRequest(
method handleUpgrade (line 172) | private handleUpgrade(
method abortRequest (line 266) | private abortRequest(
class ResponseWrapper (line 291) | class ResponseWrapper {
method constructor (line 296) | constructor(readonly res: HttpResponse) {}
method statusCode (line 298) | public set statusCode(status: number) {
method writeHead (line 306) | public writeHead(status: number) {
method setHeader (line 310) | public setHeader(key, value) {
method removeHeader (line 320) | public removeHeader() {
method getHeader (line 325) | public getHeader() {}
method writeStatus (line 327) | public writeStatus(status: string) {
method writeHeader (line 336) | public writeHeader(key: string, value: string) {
method writeBufferedHeaders (line 350) | private writeBufferedHeaders() {
method end (line 356) | public end(data) {
method onData (line 368) | public onData(fn) {
method onAborted (line 374) | public onAborted(fn) {
method cork (line 384) | public cork(fn) {
FILE: packages/engine.io/test/engine.io.js
function onEnd (line 133) | function onEnd() {
function onEnd (line 167) | function onEnd() {
FILE: packages/engine.io/test/server.js
constant IS_CLIENT_V3 (line 16) | const IS_CLIENT_V3 = process.env.EIO_CLIENT === "3";
function onClose (line 948) | function onClose(reason, err) {
function done (line 1176) | function done() {
function done (line 1231) | function done() {
function fixture (line 1725) | function fixture(filename) {
function sendFn (line 2625) | function sendFn() {
function sendFn (line 2664) | function sendFn() {
function cb (line 2698) | function cb(value) {
function cb (line 2743) | function cb(value) {
function finish (line 3127) | function finish() {
function getSidFromResponse (line 3223) | function getSidFromResponse(res) {
function testForTransport (line 3454) | function testForTransport(transport, done) {
function testForHeaders (line 3480) | function testForHeaders(headers, callback) {
FILE: packages/engine.io/test/util.mjs
function _dnToAsn1 (line 16) | function _dnToAsn1(obj) {
function _dateToAsn1 (line 71) | function _dateToAsn1(date) {
function _signatureParametersToAsn1 (line 98) | function _signatureParametersToAsn1(oid, params) {
function getTBSCertificate (line 171) | function getTBSCertificate(cert) {
function toPositiveHex (line 273) | function toPositiveHex(hexString) {
function generateWebTransportCertificate (line 296) | async function generateWebTransportCertificate(attrs, options) {
FILE: packages/engine.io/test/webtransport.mjs
constant TEXT_ENCODER (line 8) | const TEXT_ENCODER = new TextEncoder();
constant TEXT_DECODER (line 9) | const TEXT_DECODER = new TextDecoder();
function success (line 11) | function success(engine, h3server, done) {
function createPartialDone (line 17) | function createPartialDone(done, count) {
function setupServer (line 28) | async function setupServer(opts, cb) {
function setup (line 70) | function setup(opts, cb) {
function createHttpServer (line 102) | function createHttpServer(port) {
FILE: packages/socket.io-adapter/lib/cluster-adapter.ts
constant EMITTER_UID (line 11) | const EMITTER_UID = "emitter";
constant DEFAULT_TIMEOUT (line 12) | const DEFAULT_TIMEOUT = 5000;
function randomId (line 14) | function randomId() {
type DistributiveOmit (line 18) | type DistributiveOmit<T, K extends keyof any> = T extends any
type ServerId (line 25) | type ServerId = string;
type Offset (line 30) | type Offset = string;
type ClusterAdapterOptions (line 32) | interface ClusterAdapterOptions {
type MessageType (line 45) | enum MessageType {
type ClusterMessage (line 61) | type ClusterMessage = {
type ClusterRequest (line 109) | interface ClusterRequest {
type ClusterResponse (line 118) | type ClusterResponse = {
type ClusterAckRequest (line 152) | interface ClusterAckRequest {
function encodeOptions (line 157) | function encodeOptions(opts: BroadcastOptions) {
function decodeOptions (line 165) | function decodeOptions(opts): BroadcastOptions {
method constructor (line 185) | protected constructor(nsp) {
method onMessage (line 197) | protected onMessage(message: ClusterMessage, offset?: string) {
method onResponse (line 360) | protected onResponse(response: ClusterResponse) {
method broadcast (line 427) | override async broadcast(packet: any, opts: BroadcastOptions) {
method addOffsetIfNecessary (line 457) | private addOffsetIfNecessary(
method broadcastWithAck (line 476) | override broadcastWithAck(
method addSockets (line 510) | override async addSockets(opts: BroadcastOptions, rooms: Room[]) {
method delSockets (line 530) | override async delSockets(opts: BroadcastOptions, rooms: Room[]) {
method disconnectSockets (line 550) | override async disconnectSockets(opts: BroadcastOptions, close: boolean) {
method fetchSockets (line 570) | async fetchSockets(opts: BroadcastOptions): Promise<any[]> {
method serverSideEmit (line 616) | override async serverSideEmit(packet: any[]) {
method publish (line 675) | protected publish(
method publishAndReturnOffset (line 685) | protected publishAndReturnOffset(
method publishResponse (line 702) | protected publishResponse(
type CustomClusterRequest (line 736) | interface CustomClusterRequest {
method constructor (line 752) | protected constructor(nsp, opts: ClusterAdapterOptions) {
method init (line 773) | override init() {
method scheduleHeartbeat (line 779) | private scheduleHeartbeat() {
method close (line 791) | override close() {
method onMessage (line 801) | override onMessage(message: ClusterMessage, offset?: string) {
method serverCount (line 828) | override serverCount(): Promise<number> {
method publish (line 832) | override publish(message: DistributiveOmit<ClusterMessage, "nsp" | "uid"...
method serverSideEmit (line 838) | override async serverSideEmit(packet: any[]) {
method fetchSockets (line 896) | override async fetchSockets(opts: BroadcastOptions): Promise<any[]> {
method onResponse (line 947) | override onResponse(response: ClusterResponse) {
method removeNode (line 1001) | private removeNode(uid: ServerId) {
FILE: packages/socket.io-adapter/lib/contrib/yeast.ts
function encode (line 21) | function encode(num) {
function decode (line 39) | function decode(str) {
function yeast (line 55) | function yeast() {
FILE: packages/socket.io-adapter/lib/in-memory-adapter.ts
type SocketId (line 11) | type SocketId = string;
type PrivateSessionId (line 16) | type PrivateSessionId = string;
type Room (line 20) | type Room = string;
type BroadcastFlags (line 22) | interface BroadcastFlags {
type BroadcastOptions (line 31) | interface BroadcastOptions {
type SessionToPersist (line 37) | interface SessionToPersist {
type Session (line 44) | type Session = SessionToPersist & { missedPackets: unknown[][] };
class Adapter (line 46) | class Adapter extends EventEmitter {
method constructor (line 56) | constructor(readonly nsp: any) {
method init (line 64) | public init(): Promise<void> | void {}
method close (line 69) | public close(): Promise<void> | void {}
method serverCount (line 76) | public serverCount(): Promise<number> {
method addAll (line 87) | public addAll(id: SocketId, rooms: Set<Room>): Promise<void> | void {
method del (line 112) | public del(id: SocketId, room: Room): Promise<void> | void {
method _del (line 120) | private _del(room: Room, id: SocketId) {
method delAll (line 138) | public delAll(id: SocketId): void {
method broadcast (line 162) | public broadcast(packet: any, opts: BroadcastOptions): void {
method broadcastWithAck (line 197) | public broadcastWithAck(
method _encode (line 234) | private _encode(packet: unknown, packetOpts: Record<string, unknown>) {
method sockets (line 263) | public sockets(rooms: Set<Room>): Promise<Set<SocketId>> {
method socketRooms (line 278) | public socketRooms(id: SocketId): Set<Room> | undefined {
method fetchSockets (line 287) | public fetchSockets(opts: BroadcastOptions): Promise<any[]> {
method addSockets (line 303) | public addSockets(opts: BroadcastOptions, rooms: Room[]): void {
method delSockets (line 315) | public delSockets(opts: BroadcastOptions, rooms: Room[]): void {
method disconnectSockets (line 327) | public disconnectSockets(opts: BroadcastOptions, close: boolean): void {
method apply (line 333) | private apply(opts: BroadcastOptions, callback: (socket) => void): void {
method computeExceptSids (line 360) | private computeExceptSids(exceptRooms?: Set<Room>) {
method serverSideEmit (line 376) | public serverSideEmit(packet: any[]): void {
method persistSession (line 385) | public persistSession(session: SessionToPersist) {}
method restoreSession (line 392) | public restoreSession(
type PersistedPacket (line 400) | interface PersistedPacket {
type SessionWithTimestamp (line 407) | type SessionWithTimestamp = SessionToPersist & { disconnectedAt: number };
class SessionAwareAdapter (line 409) | class SessionAwareAdapter extends Adapter {
method constructor (line 415) | constructor(readonly nsp: any) {
method persistSession (line 440) | override persistSession(session: SessionToPersist) {
method restoreSession (line 445) | override restoreSession(
method broadcast (line 479) | override broadcast(packet: any, opts: BroadcastOptions) {
function shouldIncludePacket (line 501) | function shouldIncludePacket(
FILE: packages/socket.io-adapter/test/cluster-adapter.ts
constant NODES_COUNT (line 14) | const NODES_COUNT = 3;
class EventEmitterAdapter (line 16) | class EventEmitterAdapter extends ClusterAdapterWithHeartbeat {
method constructor (line 20) | constructor(
method doPublish (line 30) | protected doPublish(message: ClusterMessage): Promise<string> {
method doPublishResponse (line 38) | protected doPublishResponse(
FILE: packages/socket.io-adapter/test/index.ts
function socket (line 63) | function socket(id) {
method encode (line 81) | encode() {
function socket (line 103) | function socket(id) {
method encode (line 123) | encode() {
function socket (line 144) | function socket(id) {
method encode (line 166) | encode() {
method encode (line 325) | encode(packet) {
method encode (line 371) | encode(packet) {
method encode (line 510) | encode(packet) {
method encode (line 531) | encode(packet) {
FILE: packages/socket.io-adapter/test/util.ts
function times (line 1) | function times(count: number, fn: () => void) {
function shouldNotHappen (line 13) | function shouldNotHappen(done) {
function sleep (line 17) | function sleep() {
FILE: packages/socket.io-client/lib/contrib/backo2.ts
function Backoff (line 13) | function Backoff(opts) {
FILE: packages/socket.io-client/lib/index.ts
function lookup (line 30) | function lookup(
FILE: packages/socket.io-client/lib/manager.ts
type ManagerOptions (line 21) | interface ManagerOptions extends EngineOptions {
type ManagerReservedEvents (line 89) | interface ManagerReservedEvents {
class Manager (line 101) | class Manager<
method constructor (line 157) | constructor(
method reconnection (line 201) | public reconnection(v?: boolean): this | boolean {
method reconnectionAttempts (line 220) | public reconnectionAttempts(v?: number): this | number {
method reconnectionDelay (line 236) | public reconnectionDelay(v?: number): this | number {
method randomizationFactor (line 253) | public randomizationFactor(v?: number): this | number {
method reconnectionDelayMax (line 270) | public reconnectionDelayMax(v?: number): this | number {
method timeout (line 287) | public timeout(v?: number | boolean): this | number | boolean {
method maybeReconnectOnOpen (line 299) | private maybeReconnectOnOpen() {
method open (line 318) | public open(fn?: (err?: Error) => void): this {
method connect (line 384) | public connect(fn?: (err?: Error) => void): this {
method onopen (line 393) | private onopen(): void {
method onping (line 420) | private onping(): void {
method ondata (line 429) | private ondata(data): void {
method ondecoded (line 442) | private ondecoded(packet): void {
method onerror (line 454) | private onerror(err): void {
method socket (line 465) | public socket(nsp: string, opts?: Partial<SocketOptions>): Socket {
method _destroy (line 483) | _destroy(socket: Socket): void {
method _packet (line 504) | _packet(packet: Partial<Packet & { query: string; options: any }>): vo...
method cleanup (line 518) | private cleanup(): void {
method _close (line 532) | _close(): void {
method disconnect (line 544) | private disconnect(): void {
method onclose (line 557) | private onclose(reason: string, description?: DisconnectDescription): ...
method reconnect (line 576) | private reconnect(): this | void {
method onreconnect (line 628) | private onreconnect(): void {
FILE: packages/socket.io-client/lib/on.ts
function on (line 3) | function on(
FILE: packages/socket.io-client/lib/socket.ts
type PrependTimeoutError (line 15) | type PrependTimeoutError<T extends any[]> = {
type DecorateAcknowledgements (line 40) | type DecorateAcknowledgements<E> = {
type Last (line 46) | type Last<T extends any[]> = T extends [...infer H, infer L] ? L : any;
type AllButLast (line 47) | type AllButLast<T extends any[]> = T extends [...infer H, infer L]
type FirstArg (line 50) | type FirstArg<T> = T extends (arg: infer Param) => infer Result
type SocketOptions (line 54) | interface SocketOptions {
type QueuedPacket (line 72) | type QueuedPacket = {
constant RESERVED_EVENTS (line 90) | const RESERVED_EVENTS = Object.freeze({
type Flags (line 100) | interface Flags {
type DisconnectDescription (line 107) | type DisconnectDescription =
type SocketReservedEvents (line 114) | interface SocketReservedEvents {
class Socket (line 147) | class Socket<
method constructor (line 279) | constructor(io: Manager, nsp: string, opts?: Partial<SocketOptions>) {
method disconnected (line 304) | public get disconnected(): boolean {
method subEvents (line 313) | private subEvents(): void {
method active (line 342) | public get active(): boolean {
method connect (line 356) | public connect(): this {
method open (line 368) | public open(): this {
method send (line 387) | public send(...args: any[]): this {
method emit (line 410) | public emit<Ev extends EventNames<EmitEvents>>(
method _registerAckCallback (line 464) | private _registerAckCallback(id: number, ack: (...args: any[]) => void) {
method emitWithAck (line 510) | public emitWithAck<Ev extends EventNames<EmitEvents>>(
method _addToQueue (line 529) | private _addToQueue(args: unknown[]) {
method _drainQueue (line 581) | private _drainQueue(force = false) {
method packet (line 607) | private packet(packet: Partial<Packet>): void {
method onopen (line 617) | private onopen(): void {
method _sendConnectPacket (line 634) | private _sendConnectPacket(data: Record<string, unknown>) {
method onerror (line 649) | private onerror(err: Error): void {
method onclose (line 662) | private onclose(
method _clearAcks (line 679) | private _clearAcks() {
method onpacket (line 702) | private onpacket(packet: Packet): void {
method onevent (line 751) | private onevent(packet: Packet): void {
method emitEvent (line 767) | private emitEvent(args: ReadonlyArray<any>): void {
method ack (line 785) | private ack(id: number): (...args: any[]) => void {
method onack (line 808) | private onack(packet: Packet): void {
method onconnect (line 829) | private onconnect(id: string, pid: string) {
method emitBuffered (line 845) | private emitBuffered(): void {
method ondisconnect (line 861) | private ondisconnect(): void {
method destroy (line 874) | private destroy(): void {
method disconnect (line 899) | public disconnect(): this {
method close (line 920) | public close(): this {
method compress (line 933) | public compress(compress: boolean): this {
method volatile (line 947) | public get volatile(): this {
method timeout (line 965) | public timeout(
method onAny (line 983) | public onAny(listener: (...args: any[]) => void): this {
method prependAny (line 1000) | public prependAny(listener: (...args: any[]) => void): this {
method offAny (line 1024) | public offAny(listener?: (...args: any[]) => void): this {
method listenersAny (line 1046) | public listenersAny() {
method onAnyOutgoing (line 1063) | public onAnyOutgoing(listener: (...args: any[]) => void): this {
method prependAnyOutgoing (line 1082) | public prependAnyOutgoing(listener: (...args: any[]) => void): this {
method offAnyOutgoing (line 1106) | public offAnyOutgoing(listener?: (...args: any[]) => void): this {
method listenersAnyOutgoing (line 1128) | public listenersAnyOutgoing() {
method notifyOutgoingListeners (line 1139) | private notifyOutgoingListeners(packet: Packet) {
type DisconnectReason (line 1150) | type DisconnectReason =
FILE: packages/socket.io-client/lib/url.ts
type ParsedUrl (line 6) | type ParsedUrl = {
function url (line 39) | function url(
FILE: packages/socket.io-client/support/bundle-size.js
function format (line 16) | function format(size) {
function main (line 20) | async function main() {
FILE: packages/socket.io-client/test/browser-runner.ts
function run (line 6) | async function run() {
FILE: packages/socket.io-client/test/support/hooks.ts
method beforeAll (line 6) | beforeAll() {
method afterAll (line 9) | afterAll() {
FILE: packages/socket.io-client/test/support/server.ts
function createServer (line 4) | function createServer() {
FILE: packages/socket.io-client/test/support/util.ts
function wrap (line 13) | function wrap(fn: (done: (err?: Error) => void) => void) {
function success (line 29) | function success(done, socket) {
constant BASE_URL (line 37) | const BASE_URL = "http://localhost:3210";
FILE: packages/socket.io-client/test/typed-events.test-d.ts
type Events (line 50) | enum Events {
type BidirectionalEvents (line 108) | interface BidirectionalEvents {
type ClientToServerEvents (line 153) | interface ClientToServerEvents {
type ServerToClientEvents (line 168) | interface ServerToClientEvents {
FILE: packages/socket.io-client/wdio.conf.js
constant BASE_SAUCE_OPTIONS (line 1) | const BASE_SAUCE_OPTIONS = {
FILE: packages/socket.io-cluster-adapter/lib/index.ts
constant MESSAGE_SOURCE (line 13) | const MESSAGE_SOURCE = "_sio_adapter";
function ignoreError (line 16) | function ignoreError() {}
function createAdapter (line 26) | function createAdapter(opts: Partial<ClusterAdapterOptions> = {}) {
class NodeClusterAdapter (line 32) | class NodeClusterAdapter extends ClusterAdapterWithHeartbeat {
method constructor (line 33) | constructor(nsp: any, opts: ClusterAdapterOptions = {}) {
method doPublish (line 55) | protected override doPublish(message: ClusterMessage & { source: strin...
method doPublishResponse (line 63) | protected override doPublishResponse(
constant UIDS (line 76) | const UIDS = Symbol("uids");
function setupPrimary (line 78) | function setupPrimary() {
FILE: packages/socket.io-cluster-adapter/test/index.ts
constant NODES_COUNT (line 7) | const NODES_COUNT = 3;
FILE: packages/socket.io-cluster-adapter/test/util.ts
function times (line 1) | function times(count: number, fn: () => void) {
function sleep (line 11) | function sleep(duration: number) {
FILE: packages/socket.io-cluster-engine/lib/cluster.ts
constant MESSAGE_SOURCE (line 7) | const MESSAGE_SOURCE = "_eio";
function ignoreError (line 10) | function ignoreError() {}
function setupPrimary (line 12) | function setupPrimary() {
class NodeClusterEngine (line 44) | class NodeClusterEngine extends ClusterEngine {
method constructor (line 45) | constructor(opts?: ServerOptions) {
method publishMessage (line 59) | override publishMessage(message: Message & { _source?: string }) {
FILE: packages/socket.io-cluster-engine/lib/engine.ts
type Brand (line 23) | type Brand<K, T> = K & { __brand: T };
type NodeId (line 25) | type NodeId = Brand<string, "NodeId">;
type SessionId (line 26) | type SessionId = Brand<string, "SessionId">;
type RequestId (line 27) | type RequestId = Brand<number, "RequestId">;
function randomId (line 29) | function randomId() {
type MessageType (line 33) | enum MessageType {
type Message (line 43) | type Message = {
type ClusterRequest (line 107) | type ClusterRequest = {
function isClientLockable (line 113) | function isClientLockable(
function isValidSessionId (line 134) | function isValidSessionId(str: string) {
type ClusterEngineOptions (line 138) | interface ClusterEngineOptions {
method constructor (line 167) | constructor(opts?: ServerOptions & ClusterEngineOptions) {
method onMessage (line 179) | protected onMessage(message: Message) {
method _forwardFlushWhenPolling (line 346) | private _forwardFlushWhenPolling(
method _forwardFlushWhenWebSocket (line 376) | private _forwardFlushWhenWebSocket(
method verify (line 398) | override verify(
method _acquireLock (line 433) | private _acquireLock(
method _hookTransport (line 465) | private _hookTransport(
method _tryUpgrade (line 486) | private _tryUpgrade(
method _onPacket (line 526) | private _onPacket(sid: SessionId, senderId: NodeId, packet: Packet) {
method _onClose (line 538) | private _onClose(
method onWebSocket (line 554) | override onWebSocket(req: any, socket: any, websocket: any) {
method _onUpgradeSuccess (line 576) | private _onUpgradeSuccess(
method emit (line 640) | override emit(ev: string, ...args: any[]): boolean {
method _doConnect (line 668) | private _doConnect(socket: Socket) {
FILE: packages/socket.io-cluster-engine/lib/redis.ts
constant MESSAGE_SOURCE (line 9) | const MESSAGE_SOURCE = "_eio";
function ignoreError (line 12) | function ignoreError() {}
type PrimaryWithRedisOptions (line 14) | interface PrimaryWithRedisOptions {
function channelName (line 23) | function channelName(prefix: string, nodeId?: string) {
function setupPrimaryWithRedis (line 31) | function setupPrimaryWithRedis(
type RedisEngineOptions (line 124) | interface RedisEngineOptions extends ServerOptions {
class RedisEngine (line 133) | class RedisEngine extends ClusterEngine {
method constructor (line 137) | constructor(pubClient: any, subClient: any, opts?: RedisEngineOptions) {
method publishMessage (line 166) | publishMessage(message: Message & { _source?: string }): void {
constant RETURN_BUFFERS (line 177) | const RETURN_BUFFERS = true;
function SUBSCRIBE (line 179) | function SUBSCRIBE(
function isRedisClient (line 198) | function isRedisClient(redisClient: any) {
FILE: packages/socket.io-cluster-engine/test/cluster.ts
constant WORKER_COUNT (line 6) | const WORKER_COUNT = 3;
function onExit (line 29) | function onExit() {
FILE: packages/socket.io-cluster-engine/test/in-memory.ts
class InMemoryEngine (line 9) | class InMemoryEngine extends ClusterEngine {
method constructor (line 10) | constructor(
method publishMessage (line 18) | publishMessage(message: Message) {
FILE: packages/socket.io-cluster-engine/test/util.ts
function url (line 3) | function url(port: number, sid?: string) {
function handshake (line 11) | async function handshake(port: number) {
FILE: packages/socket.io-component-emitter/lib/cjs/index.d.ts
type EventsMap (line 5) | interface EventsMap {
type DefaultEventsMap (line 13) | interface DefaultEventsMap {
type EventNames (line 20) | type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
type EventParams (line 23) | type EventParams<
type ReservedOrUserEventNames (line 31) | type ReservedOrUserEventNames<
type ReservedOrUserListener (line 40) | type ReservedOrUserListener<
type FallbackToUntypedListener (line 58) | type FallbackToUntypedListener<T> = [T] extends [never]
class Emitter (line 75) | class Emitter<
FILE: packages/socket.io-component-emitter/lib/cjs/index.js
function Emitter (line 14) | function Emitter(obj) {
function mixin (line 26) | function mixin(obj) {
function on (line 61) | function on() {
FILE: packages/socket.io-component-emitter/lib/esm/index.d.ts
type EventsMap (line 5) | interface EventsMap {
type DefaultEventsMap (line 13) | interface DefaultEventsMap {
type EventNames (line 20) | type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
type EventParams (line 23) | type EventParams<
type ReservedOrUserEventNames (line 31) | type ReservedOrUserEventNames<
type ReservedOrUserListener (line 40) | type ReservedOrUserListener<
type FallbackToUntypedListener (line 58) | type FallbackToUntypedListener<T> = [T] extends [never]
class Emitter (line 75) | class Emitter<
FILE: packages/socket.io-component-emitter/lib/esm/index.js
function Emitter (line 7) | function Emitter(obj) {
function mixin (line 19) | function mixin(obj) {
function on (line 54) | function on() {
FILE: packages/socket.io-component-emitter/test/emitter.js
function Custom (line 4) | function Custom() {
function one (line 83) | function one() { calls.push('one'); }
function two (line 84) | function two() { calls.push('two'); }
function one (line 99) | function one() { calls.push('one'); }
function b (line 113) | function b () {
function one (line 133) | function one() { calls.push('one'); }
function two (line 134) | function two() { calls.push('two'); }
function cb (line 150) | function cb() {}
function cb1 (line 162) | function cb1() {}
function cb2 (line 163) | function cb2() {}
function one (line 178) | function one() { calls.push('one'); }
function two (line 179) | function two() { calls.push('two'); }
function foo (line 200) | function foo(){}
FILE: packages/socket.io-parser/bench/index.js
function test (line 4) | function test(packet, deferred) {
FILE: packages/socket.io-parser/lib/binary.ts
function deconstructPacket (line 11) | function deconstructPacket(packet) {
function _deconstructPacket (line 20) | function _deconstructPacket(data, buffers) {
function reconstructPacket (line 54) | function reconstructPacket(packet, buffers) {
function _reconstructPacket (line 60) | function _reconstructPacket(data, buffers) {
FILE: packages/socket.io-parser/lib/index.ts
constant RESERVED_EVENTS (line 11) | const RESERVED_EVENTS = [
type PacketType (line 28) | enum PacketType {
type Packet (line 38) | interface Packet {
class Encoder (line 50) | class Encoder {
method constructor (line 56) | constructor(private replacer?: (this: any, key: string, value: any) =>...
method encode (line 63) | public encode(obj: Packet) {
method encodeAsString (line 86) | private encodeAsString(obj: Packet) {
method encodeAsBinary (line 124) | private encodeAsBinary(obj: Packet) {
type DecoderReservedEvents (line 134) | interface DecoderReservedEvents {
type JSONReviver (line 138) | type JSONReviver = (this: any, key: string, value: any) => any;
type DecoderOptions (line 140) | interface DecoderOptions {
class Decoder (line 157) | class Decoder extends Emitter<{}, {}, DecoderReservedEvents> {
method constructor (line 164) | constructor(opts?: DecoderOptions | JSONReviver) {
method add (line 181) | public add(obj: any) {
method decodeString (line 225) | private decodeString(str): Packet {
method tryParse (line 298) | private tryParse(str) {
method isPayloadValid (line 306) | private static isPayloadValid(type: PacketType, payload: any): boolean {
method destroy (line 331) | public destroy() {
class BinaryReconstructor (line 348) | class BinaryReconstructor {
method constructor (line 352) | constructor(readonly packet: Packet) {
method takeBinaryData (line 364) | public takeBinaryData(binData) {
method finishedReconstruction (line 378) | public finishedReconstruction() {
function isNamespaceValid (line 384) | function isNamespaceValid(nsp: unknown) {
function isAckIdValid (line 399) | function isAckIdValid(id: unknown) {
function isObject (line 404) | function isObject(value: any): boolean {
function isDataValid (line 408) | function isDataValid(type: PacketType, payload: unknown) {
function isPacketValid (line 430) | function isPacketValid(packet: Packet): boolean {
FILE: packages/socket.io-parser/lib/is-binary.ts
function isBinary (line 25) | function isBinary(obj: any) {
function hasBinary (line 33) | function hasBinary(obj: any, toJSON?: boolean) {
FILE: packages/socket.io-parser/wdio.conf.js
constant BASE_SAUCE_OPTIONS (line 1) | const BASE_SAUCE_OPTIONS = {
FILE: packages/socket.io-postgres-emitter/lib/index.ts
constant EMITTER_UID (line 12) | const EMITTER_UID = "emitter";
type EventType (line 49) | enum EventType {
type BroadcastFlags (line 62) | interface BroadcastFlags {
type PostgresEmitterOptions (line 67) | interface PostgresEmitterOptions {
class Emitter (line 84) | class Emitter<
method constructor (line 92) | constructor(
method of (line 109) | public of(nsp: string): Emitter {
method emit (line 119) | public emit<Ev extends EventNames<EmitEvents>>(
method to (line 136) | public to(
method in (line 149) | public in(
method except (line 162) | public except(
method volatile (line 176) | public get volatile(): BroadcastOperator<EmitEvents, ServerSideEvents> {
method compress (line 187) | public compress(
method socketsJoin (line 199) | public socketsJoin(rooms: string | string[]): void {
method socketsLeave (line 209) | public socketsLeave(rooms: string | string[]): void {
method disconnectSockets (line 219) | public disconnectSockets(close: boolean = false): void {
method serverSideEmit (line 229) | public serverSideEmit<Ev extends EventNames<ServerSideEvents>>(
constant RESERVED_EVENTS (line 239) | const RESERVED_EVENTS: ReadonlySet<string | Symbol> = new Set(<const>[
class BroadcastOperator (line 248) | class BroadcastOperator<
method constructor (line 253) | constructor(
method to (line 267) | public to(
method in (line 291) | public in(
method except (line 304) | public except(
method compress (line 328) | public compress(
method volatile (line 348) | public get volatile(): BroadcastOperator<EmitEvents, ServerSideEvents> {
method publish (line 358) | private async publish(document: any) {
method publishWithAttachment (line 393) | private async publishWithAttachment(document: any) {
method emit (line 423) | public emit<Ev extends EventNames<EmitEvents>>(
method socketsJoin (line 462) | public socketsJoin(rooms: string | string[]): void {
method socketsLeave (line 481) | public socketsLeave(rooms: string | string[]): void {
method disconnectSockets (line 500) | public disconnectSockets(close: boolean = false): void {
method serverSideEmit (line 519) | public serverSideEmit<Ev extends EventNames<ServerSideEvents>>(
FILE: packages/socket.io-postgres-emitter/lib/typed-events.ts
type EventsMap (line 5) | interface EventsMap {
type DefaultEventsMap (line 13) | interface DefaultEventsMap {
type EventNames (line 20) | type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
type EventParams (line 23) | type EventParams<
type TypedEventBroadcaster (line 32) | interface TypedEventBroadcaster<EmitEvents extends EventsMap> {
FILE: packages/socket.io-postgres-emitter/test/index.ts
constant NODES_COUNT (line 11) | const NODES_COUNT = 3;
FILE: packages/socket.io-postgres-emitter/test/util.ts
function times (line 1) | function times(count: number, fn: () => void) {
function sleep (line 11) | function sleep(duration: number) {
FILE: packages/socket.io-redis-streams-emitter/lib/adapter-types.ts
type MessageType (line 2) | enum MessageType {
type ServerId (line 18) | type ServerId = string;
type ClusterMessage (line 20) | type ClusterMessage = {
type BroadcastFlags (line 68) | interface BroadcastFlags {
FILE: packages/socket.io-redis-streams-emitter/lib/index.ts
constant EMITTER_UID (line 14) | const EMITTER_UID = "emitter";
type DistributiveOmit (line 16) | type DistributiveOmit<T, K extends keyof any> = T extends any
method emit (line 35) | public emit<Ev extends EventNames<EmitEvents>>(
method to (line 49) | public to(
method in (line 62) | public in(
method except (line 75) | public except(
method volatile (line 89) | public get volatile(): BroadcastOperator<EmitEvents, ServerSideEvents> {
method compress (line 100) | public compress(
method socketsJoin (line 112) | public socketsJoin(rooms: string | string[]): void {
method socketsLeave (line 122) | public socketsLeave(rooms: string | string[]): void {
method disconnectSockets (line 132) | public disconnectSockets(close: boolean = false): void {
method serverSideEmit (line 142) | public serverSideEmit<Ev extends EventNames<ServerSideEvents>>(
method newBroadcastOperator (line 149) | private newBroadcastOperator() {
constant RESERVED_EVENTS (line 156) | const RESERVED_EVENTS: ReadonlySet<string | Symbol> = new Set(<const>[
class BroadcastOperator (line 165) | class BroadcastOperator<
method constructor (line 170) | constructor(
method to (line 186) | public to(
method in (line 210) | public in(
method except (line 223) | public except(
method compress (line 247) | public compress(
method volatile (line 267) | public get volatile(): BroadcastOperator<EmitEvents, ServerSideEvents> {
method emit (line 283) | public emit<Ev extends EventNames<EmitEvents>>(
method socketsJoin (line 321) | public socketsJoin(rooms: string | string[]): void {
method socketsLeave (line 341) | public socketsLeave(rooms: string | string[]): void {
method disconnectSockets (line 361) | public disconnectSockets(close: boolean = false): void {
method serverSideEmit (line 381) | public serverSideEmit<Ev extends EventNames<ServerSideEvents>>(
function flattenPayload (line 400) | function flattenPayload(message: ClusterMessage) {
type RedisStreamsEmitterOptions (line 430) | interface RedisStreamsEmitterOptions {
class Emitter (line 443) | class Emitter<
method constructor (line 451) | constructor(
method of (line 468) | public of(nsp: string) {
method publish (line 472) | protected override publish(
FILE: packages/socket.io-redis-streams-emitter/lib/typed-events.ts
type EventsMap (line 5) | interface EventsMap {
type DefaultEventsMap (line 13) | interface DefaultEventsMap {
type EventNames (line 20) | type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
type EventParams (line 23) | type EventParams<
type TypedEventBroadcaster (line 32) | interface TypedEventBroadcaster<EmitEvents extends EventsMap> {
FILE: packages/socket.io-redis-streams-emitter/lib/util.ts
function hasBinary (line 1) | function hasBinary(obj: any, toJSON?: boolean): boolean {
function isRedisV4Client (line 39) | function isRedisV4Client(redisClient: any) {
function XADD (line 46) | function XADD(
FILE: packages/socket.io-redis-streams-emitter/test/index.ts
constant PROPAGATION_DELAY_IN_MS (line 8) | const PROPAGATION_DELAY_IN_MS = 100;
FILE: packages/socket.io-redis-streams-emitter/test/util.ts
function times (line 9) | function times(count: number, fn: () => void) {
function sleep (line 21) | function sleep(duration: number) {
function initRedisClient (line 30) | async function initRedisClient() {
function init (line 102) | async function init() {
function setup (line 138) | async function setup() {
FILE: packages/socket.io/client-dist/socket.io.js
function _arrayLikeToArray (line 12) | function _arrayLikeToArray(r, a) {
function _arrayWithoutHoles (line 17) | function _arrayWithoutHoles(r) {
function _construct (line 20) | function _construct(t, e, r) {
function _defineProperties (line 27) | function _defineProperties(e, r) {
function _createClass (line 33) | function _createClass(e, r, t) {
function _createForOfIteratorHelper (line 38) | function _createForOfIteratorHelper(r, e) {
function _extends (line 86) | function _extends() {
function _getPrototypeOf (line 95) | function _getPrototypeOf(t) {
function _inheritsLoose (line 100) | function _inheritsLoose(t, o) {
function _isNativeFunction (line 103) | function _isNativeFunction(t) {
function _isNativeReflectConstruct (line 110) | function _isNativeReflectConstruct() {
function _iterableToArray (line 118) | function _iterableToArray(r) {
function _nonIterableSpread (line 121) | function _nonIterableSpread() {
function _setPrototypeOf (line 124) | function _setPrototypeOf(t, e) {
function _toConsumableArray (line 129) | function _toConsumableArray(r) {
function _toPrimitive (line 132) | function _toPrimitive(t, r) {
function _toPropertyKey (line 142) | function _toPropertyKey(t) {
function _typeof (line 146) | function _typeof(o) {
function _unsupportedIterableToArray (line 155) | function _unsupportedIterableToArray(r, a) {
function _wrapNativeSuper (line 162) | function _wrapNativeSuper(t) {
function toArray (line 235) | function toArray(data) {
function encodePacketToBinary (line 245) | function encodePacketToBinary(packet, callback) {
function createPacketEncoderStream (line 382) | function createPacketEncoderStream() {
function totalLength (line 414) | function totalLength(chunks) {
function concatChunks (line 419) | function concatChunks(chunks, size) {
function createPacketDecoderStream (line 437) | function createPacketDecoderStream(maxPayload, binaryType) {
function Emitter (line 508) | function Emitter(obj) {
function mixin (line 520) | function mixin(obj) {
function on (line 553) | function on() {
function createCookieJar (line 683) | function createCookieJar() {}
function pick (line 685) | function pick(obj) {
function installTimerFunctions (line 699) | function installTimerFunctions(obj, opts) {
function byteLength (line 711) | function byteLength(obj) {
function utf8Length (line 718) | function utf8Length(str) {
function randomString (line 739) | function randomString() {
function encode (line 751) | function encode(obj) {
function decode (line 767) | function decode(qs) {
function TransportError (line 778) | function TransportError(reason, description, context) {
function Transport (line 796) | function Transport(opts) {
function Polling (line 916) | function Polling() {
function empty (line 1079) | function empty() {}
function BaseXHR (line 1087) | function BaseXHR(opts) {
function Request (line 1144) | function Request(createRequest, uri, opts) {
function unloadHandler (line 1300) | function unloadHandler() {
function XHR (line 1321) | function XHR(opts) {
function newRequest (line 1339) | function newRequest(opts) {
function BaseWS (line 1357) | function BaseWS() {
function WS (line 1476) | function WS() {
function WT (line 1499) | function WT() {
function parse (line 1607) | function parse(str) {
function pathNames (line 1633) | function pathNames(obj, path) {
function queryKey (line 1644) | function queryKey(uri, query) {
function SocketWithoutUpgrade (line 1695) | function SocketWithoutUpgrade(uri, opts) {
function SocketWithUpgrade (line 2178) | function SocketWithUpgrade() {
function freezeTransport (line 2239) | function freezeTransport() {
function onTransportClose (line 2255) | function onTransportClose() {
function onclose (line 2259) | function onclose() {
function onupgrade (line 2263) | function onupgrade(to) {
function Socket (line 2331) | function Socket(uri) {
function getDefaultExportFromCjs (line 2349) | function getDefaultExportFromCjs (x) {
function requireMs (line 2357) | function requireMs() {
function setup (line 2521) | function setup(env) {
function useColors (line 2849) | function useColors() {
function formatArgs (line 2882) | function formatArgs(args) {
function save (line 2925) | function save(namespaces) {
function load (line 2944) | function load() {
function localstorage (line 2971) | function localstorage() {
function url (line 3009) | function url(uri) {
function isBinary (line 3067) | function isBinary(obj) {
function hasBinary (line 3070) | function hasBinary(obj, toJSON) {
function deconstructPacket (line 3103) | function deconstructPacket(packet) {
function _deconstructPacket (line 3114) | function _deconstructPacket(data, buffers) {
function reconstructPacket (line 3148) | function reconstructPacket(packet, buffers) {
function _reconstructPacket (line 3153) | function _reconstructPacket(data, buffers) {
function Encoder (line 3216) | function Encoder(replacer) {
function Decoder (line 3289) | function Decoder(reviver) {
function BinaryReconstructor (line 3443) | function BinaryReconstructor(packet) {
function isNamespaceValid (line 3476) | function isNamespaceValid(nsp) {
function isAckIdValid (line 3483) | function isAckIdValid(id) {
function isObject (line 3487) | function isObject(value) {
function isDataValid (line 3490) | function isDataValid(type, payload) {
function isPacketValid (line 3506) | function isPacketValid(packet) {
method PacketType (line 3513) | get PacketType () { return PacketType; }
function on (line 3519) | function on(obj, ev, fn) {
function Socket (line 3568) | function Socket(io, nsp, opts) {
function Backoff (line 4481) | function Backoff(opts) {
function Manager (line 4539) | function Manager(uri, opts) {
function lookup (line 4915) | function lookup(uri, opts) {
FILE: packages/socket.io/lib/broadcast-operator.ts
class BroadcastOperator (line 20) | class BroadcastOperator<EmitEvents extends EventsMap, SocketData>
method constructor (line 23) | constructor(
method to (line 48) | public to(room: Room | Room[]) {
method in (line 73) | public in(room: Room | Room[]) {
method except (line 93) | public except(room: Room | Room[]) {
method compress (line 117) | public compress(compress: boolean) {
method volatile (line 137) | public get volatile() {
method local (line 156) | public get local() {
method timeout (line 180) | public timeout(timeout: number) {
method emit (line 209) | public emit<Ev extends EventNames<EmitEvents>>(
method emitWithAck (line 324) | public emitWithAck<Ev extends EventNamesWithError<EmitEvents>>(
method allSockets (line 347) | public allSockets(): Promise<Set<SocketId>> {
method fetchSockets (line 380) | public fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]> {
method socketsJoin (line 416) | public socketsJoin(room: Room | Room[]): void {
method socketsLeave (line 441) | public socketsLeave(room: Room | Room[]): void {
method disconnectSockets (line 466) | public disconnectSockets(close: boolean = false): void {
type SocketDetails (line 481) | interface SocketDetails<SocketData> {
class RemoteSocket (line 491) | class RemoteSocket<EmitEvents extends EventsMap, SocketData>
method constructor (line 501) | constructor(adapter: Adapter, details: SocketDetails<SocketData>) {
method timeout (line 539) | public timeout(
method emit (line 545) | public emit<Ev extends EventNames<EmitEvents>>(
method join (line 557) | public join(room: Room | Room[]): void {
method leave (line 566) | public leave(room: Room): void {
method disconnect (line 576) | public disconnect(close = false): this {
FILE: packages/socket.io/lib/client.ts
type WriteOptions (line 14) | interface WriteOptions {
type CloseReason (line 21) | type CloseReason =
class Client (line 28) | class Client<
method constructor (line 62) | constructor(
method request (line 80) | public get request(): IncomingMessage {
method setup (line 89) | private setup() {
method connect (line 118) | private connect(name: string, auth: Record<string, unknown> = {}): void {
method doConnect (line 156) | private doConnect(name: string, auth: Record<string, unknown>): void {
method _disconnect (line 175) | _disconnect(): void {
method _remove (line 188) | _remove(
method close (line 205) | private close(): void {
method _packet (line 220) | _packet(packet: Packet | Packet[], opts: WriteOptions = {}): void {
method writeToEngine (line 231) | private writeToEngine(
method ondata (line 254) | private ondata(data: unknown): void {
method ondecoded (line 269) | private ondecoded(packet: Packet): void {
method _parseNamespace (line 289) | private _parseNamespace(packet: Packet) {
method onerror (line 309) | private onerror(err): void {
method onclose (line 323) | private onclose(
method destroy (line 345) | private destroy(): void {
FILE: packages/socket.io/lib/index.ts
type ParentNspNameMatchFn (line 57) | type ParentNspNameMatchFn = (
type AdapterConstructor (line 63) | type AdapterConstructor = typeof Adapter | ((nsp: Namespace) => Adapter);
type TServerInstance (line 65) | type TServerInstance =
type ServerOptions (line 71) | interface ServerOptions extends EngineOptions, AttachOptions {
class Server (line 149) | class Server<
method constructor (line 301) | constructor(
method _opts (line 342) | get _opts() {
method serveClient (line 355) | public serveClient(v?: boolean): this | boolean {
method _checkNamespace (line 370) | _checkNamespace(
method path (line 415) | public path(v?: string): this | string {
method connectTimeout (line 436) | public connectTimeout(v?: number): this | number {
method adapter (line 450) | public adapter(
method listen (line 468) | public listen(
method attach (line 482) | public attach(
method attachApp (line 523) | public attachApp(app /*: TemplatedApp */, opts: Partial<ServerOptions>...
method initEngine (line 593) | private initEngine(
method attachServe (line 617) | private attachServe(srv: TServerInstance): void {
method serve (line 646) | private serve(req: IncomingMessage, res: ServerResponse): void {
method sendFile (line 684) | private static sendFile(
method bind (line 725) | public bind(engine: any): this {
method onconnection (line 740) | private onconnection(conn: RawSocket): this {
method of (line 769) | public of(
method close (line 822) | public async close(fn?: (err?: Error) => void): Promise<void> {
method use (line 864) | public use(
method to (line 890) | public to(room: Room | Room[]) {
method in (line 904) | public in(room: Room | Room[]) {
method except (line 924) | public except(room: Room | Room[]) {
method send (line 943) | public send(...args: EventParams<EmitEvents, "message">): this {
method write (line 955) | public write(...args: EventParams<EmitEvents, "message">): this {
method serverSideEmit (line 988) | public serverSideEmit<Ev extends EventNames<ServerSideEvents>>(
method serverSideEmitWithAck (line 1014) | public serverSideEmitWithAck<Ev extends EventNamesWithAck<ServerSideEv...
method allSockets (line 1027) | public allSockets(): Promise<Set<SocketId>> {
method compress (line 1040) | public compress(compress: boolean) {
method volatile (line 1054) | public get volatile() {
method local (line 1067) | public get local() {
method timeout (line 1085) | public timeout(timeout: number) {
method fetchSockets (line 1113) | public fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]> {
method socketsJoin (line 1132) | public socketsJoin(room: Room | Room[]) {
method socketsLeave (line 1150) | public socketsLeave(room: Room | Room[]) {
method disconnectSockets (line 1168) | public disconnectSockets(close: boolean = false) {
FILE: packages/socket.io/lib/namespace.ts
type ExtendedError (line 25) | interface ExtendedError extends Error {
type NamespaceReservedEventsMap (line 29) | interface NamespaceReservedEventsMap<
type ServerReservedEventsMap (line 43) | interface ServerReservedEventsMap<
constant RESERVED_EVENTS (line 64) | const RESERVED_EVENTS: ReadonlySet<string | Symbol> = new Set<
class Namespace (line 121) | class Namespace<
method constructor (line 180) | constructor(
method _initAdapter (line 197) | _initAdapter(): void {
method use (line 219) | public use(
method run (line 236) | private run(
method to (line 278) | public to(room: Room | Room[]) {
method in (line 297) | public in(room: Room | Room[]) {
method except (line 322) | public except(room: Room | Room[]) {
method _add (line 335) | async _add(
method _createSocket (line 382) | private async _createSocket(
method _doConnect (line 408) | private _doConnect(
method _remove (line 434) | _remove(
method emit (line 462) | public emit<Ev extends EventNamesWithoutAck<EmitEvents>>(
method send (line 489) | public send(...args: EventParams<EmitEvents, "message">): this {
method write (line 501) | public write(...args: EventParams<EmitEvents, "message">): this {
method serverSideEmit (line 536) | public serverSideEmit<Ev extends EventNames<ServerSideEvents>>(
method serverSideEmitWithAck (line 569) | public serverSideEmitWithAck<Ev extends EventNamesWithAck<ServerSideEv...
method _onServerSideEmit (line 596) | _onServerSideEmit(args: [string, ...any[]]) {
method allSockets (line 606) | public allSockets(): Promise<Set<SocketId>> {
method compress (line 623) | public compress(compress: boolean) {
method volatile (line 642) | public get volatile() {
method local (line 660) | public get local() {
method timeout (line 683) | public timeout(timeout: number) {
method fetchSockets (line 716) | public fetchSockets() {
method socketsJoin (line 738) | public socketsJoin(room: Room | Room[]) {
method socketsLeave (line 760) | public socketsLeave(room: Room | Room[]) {
method disconnectSockets (line 782) | public disconnectSockets(close: boolean = false) {
FILE: packages/socket.io/lib/parent-namespace.ts
class ParentNamespace (line 30) | class ParentNamespace<
method constructor (line 41) | constructor(
method _initAdapter (line 50) | _initAdapter(): void {
method emit (line 54) | public emit<Ev extends EventNamesWithoutAck<EmitEvents>>(
method createChild (line 65) | createChild(
method fetchSockets (line 101) | fetchSockets(): Promise<RemoteSocket<EmitEvents, SocketData>[]> {
class ParentBroadcastAdapter (line 115) | class ParentBroadcastAdapter extends Adapter {
method broadcast (line 116) | broadcast(packet: any, opts: BroadcastOptions) {
FILE: packages/socket.io/lib/socket-types.ts
type ClientReservedEvents (line 5) | type ClientReservedEvents = "connect_error";
type DisconnectReason (line 8) | type DisconnectReason =
type SocketReservedEventsMap (line 21) | interface SocketReservedEventsMap {
type EventEmitterReservedEventsMap (line 28) | interface EventEmitterReservedEventsMap {
constant RESERVED_EVENTS (line 39) | const RESERVED_EVENTS: ReadonlySet<string | Symbol> = new Set<
type Handshake (line 56) | interface Handshake {
FILE: packages/socket.io/lib/socket.ts
constant RECOVERABLE_DISCONNECT_REASONS (line 39) | const RECOVERABLE_DISCONNECT_REASONS: ReadonlySet<DisconnectReason> = ne...
type Event (line 51) | type Event = [string, ...any[]];
function noop (line 53) | function noop() {}
class Socket (line 86) | class Socket<
method constructor (line 158) | constructor(
method buildHandshake (line 201) | private buildHandshake(auth: object): Handshake {
method emit (line 235) | public emit<Ev extends EventNames<EmitEvents>>(
method emitWithAck (line 294) | public emitWithAck<Ev extends EventNamesWithAck<EmitEvents>>(
method registerAckCallback (line 315) | private registerAckCallback(id: number, ack: (...args: any[]) => void)...
method to (line 355) | public to(room: Room | Room[]) {
method in (line 371) | public in(room: Room | Room[]) {
method except (line 394) | public except(room: Room | Room[]) {
method send (line 415) | public send(...args: EventParams<EmitEvents, "message">): this {
method write (line 425) | public write(...args: EventParams<EmitEvents, "message">): this {
method packet (line 437) | private packet(
method join (line 461) | public join(rooms: Room | Array<Room>): Promise<void> | void {
method leave (line 485) | public leave(room: string): Promise<void> | void {
method leaveAll (line 496) | private leaveAll(): void {
method _onconnect (line 508) | _onconnect(): void {
method _onpacket (line 528) | _onpacket(packet: Packet): void {
method onevent (line 559) | private onevent(packet: Packet): void {
method ack (line 583) | private ack(id: number): () => void {
method onack (line 607) | private onack(packet: Packet): void {
method ondisconnect (line 623) | private ondisconnect(): void {
method _onerror (line 633) | _onerror(err: Error): void {
method _onclose (line 650) | _onclose(reason: DisconnectReason, description?: any): this | undefined {
method _cleanup (line 680) | _cleanup() {
method _error (line 693) | _error(err): void {
method disconnect (line 712) | public disconnect(close = false): this {
method compress (line 734) | public compress(compress: boolean): this {
method volatile (line 751) | public get volatile(): this {
method broadcast (line 768) | public get broadcast() {
method local (line 783) | public get local() {
method timeout (line 802) | public timeout(
method dispatch (line 820) | private dispatch(event: Event): void {
method use (line 859) | public use(fn: (event: Event, next: (err?: Error) => void) => void): t...
method run (line 871) | private run(event: Event, fn: (err?: Error) => void): void {
method disconnected (line 895) | public get disconnected() {
method request (line 902) | public get request(): IncomingMessage {
method conn (line 918) | public get conn() {
method rooms (line 934) | public get rooms(): Set<Room> {
method onAny (line 951) | public onAny(listener: (...args: any[]) => void): this {
method prependAny (line 963) | public prependAny(listener: (...args: any[]) => void): this {
method offAny (line 989) | public offAny(listener?: (...args: any[]) => void): this {
method listenersAny (line 1011) | public listenersAny() {
method onAnyOutgoing (line 1030) | public onAnyOutgoing(listener: (...args: any[]) => void): this {
method prependAnyOutgoing (line 1049) | public prependAnyOutgoing(listener: (...args: any[]) => void): this {
method offAnyOutgoing (line 1075) | public offAnyOutgoing(listener?: (...args: any[]) => void): this {
method listenersAnyOutgoing (line 1097) | public listenersAnyOutgoing() {
method notifyOutgoingListeners (line 1108) | private notifyOutgoingListeners(packet: Packet) {
method newBroadcastOperator (line 1117) | private newBroadcastOperator() {
FILE: packages/socket.io/lib/typed-events.ts
type EventsMap (line 6) | interface EventsMap {
type DefaultEventsMap (line 14) | interface DefaultEventsMap {
type EventNames (line 21) | type EventNames<Map extends EventsMap> = keyof Map & (string | symbol);
type EventNamesWithAck (line 26) | type EventNamesWithAck<
type EventNamesWithoutAck (line 47) | type EventNamesWithoutAck<
type RemoveAcknowledgements (line 62) | type RemoveAcknowledgements<E extends EventsMap> = {
type EventNamesWithError (line 66) | type EventNamesWithError<
type EventParams (line 80) | type EventParams<
type ReservedOrUserEventNames (line 88) | type ReservedOrUserEventNames<
type ReservedOrUserListener (line 97) | type ReservedOrUserListener<
type FallbackToUntypedListener (line 115) | type FallbackToUntypedListener<T> = [T] extends [never]
type TypedEventBroadcaster (line 123) | interface TypedEventBroadcaster<EmitEvents extends EventsMap> {
method on (line 157) | on<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
method once (line 170) | once<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEvents>>(
method emit (line 183) | emit<Ev extends EventNames<EmitEvents>>(
method emitReserved (line 199) | protected emitReserved<Ev extends EventNames<ReservedEvents>>(
method emitUntyped (line 216) | protected emitUntyped(ev: string, ...args: any[]): boolean {
method listeners (line 226) | listeners<Ev extends ReservedOrUserEventNames<ReservedEvents, ListenEven...
type IsAny (line 246) | type IsAny<T> = 0 extends 1 & T ? true : false;
type IfAny (line 256) | type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> =
type Last (line 267) | type Last<ValueType extends readonly unknown[]> =
type FirstNonErrorTuple (line 276) | type FirstNonErrorTuple<T extends unknown[]> = T[0] extends Error
type AllButLast (line 279) | type AllButLast<T extends any[]> = T extends [...infer H, infer L]
type LooseParameters (line 285) | type LooseParameters<T> = T extends (...args: infer P) => any ? P : never;
type FirstNonErrorArg (line 287) | type FirstNonErrorArg<T> = T extends (...args: infer Params) => any
type PrependTimeoutError (line 290) | type PrependTimeoutError<T extends any[]> = {
type MultiplyArray (line 298) | type MultiplyArray<T extends unknown[]> = {
type InferFirstAndPreserveLabel (line 301) | type InferFirstAndPreserveLabel<T extends any[]> = T extends [any, ...in...
type ExpectMultipleResponses (line 311) | type ExpectMultipleResponses<T extends any[]> = {
type DecorateAcknowledgements (line 346) | type DecorateAcknowledgements<E> = {
type DecorateAcknowledgementsWithTimeoutAndMultipleResponses (line 352) | type DecorateAcknowledgementsWithTimeoutAndMultipleResponses<E> = {
type DecorateAcknowledgementsWithMultipleResponses (line 358) | type DecorateAcknowledgementsWithMultipleResponses<E> = {
FILE: packages/socket.io/lib/uws.ts
constant SEPARATOR (line 9) | const SEPARATOR = "\x1f";
function patchAdapter (line 13) | function patchAdapter(app /* : TemplatedApp */) {
function subscribe (line 94) | function subscribe(
function restoreAdapter (line 115) | function restoreAdapter() {
function serveFile (line 127) | function serveFile(res /* : HttpResponse */, filepath: string) {
FILE: packages/socket.io/test/close.ts
function fixture (line 95) | function fixture(filename) {
FILE: packages/socket.io/test/connection-state-recovery.ts
function init (line 7) | async function init(httpServer: HttpServer, io: Server) {
class DummyAdapter (line 223) | class DummyAdapter extends Adapter {
method persistSession (line 224) | persistSession(session) {
method restoreSession (line 228) | restoreSession(pid, offset) {
FILE: packages/socket.io/test/messaging-many.ts
function emit (line 43) | function emit() {
function emit (line 79) | function emit() {
FILE: packages/socket.io/test/namespaces.ts
function close (line 162) | function close() {
function getSockets (line 232) | async function getSockets() {
function getSockets (line 270) | async function getSockets() {
function getSockets (line 309) | async function getSockets() {
FILE: packages/socket.io/test/socket.io.test-d.ts
type Events (line 62) | enum Events {
type BidirectionalEvents (line 136) | interface BidirectionalEvents {
type ToEmit (line 181) | type ToEmit<Map extends EventsMap, Ev extends keyof Map = keyof Map> = (
type ToEmitWithAck (line 185) | type ToEmitWithAck<
type ClientToServerEvents (line 189) | interface ClientToServerEvents {
type ServerToClientEvents (line 199) | interface ServerToClientEvents {
type ServerToClientEventsNoAck (line 216) | interface ServerToClientEventsNoAck {
type ServerToClientEventsWithError (line 223) | interface ServerToClientEventsWithError {
type ServerToClientEventsWithMultiple (line 239) | interface ServerToClientEventsWithMultiple {
type ServerToClientEventsWithMultipleAndError (line 250) | interface ServerToClientEventsWithMultipleAndError {
type ServerToClientEventsWithMultipleWithAck (line 265) | interface ServerToClientEventsWithMultipleWithAck {
type ServerToClientEventsWithAck (line 270) | interface ServerToClientEventsWithAck {
type ClientToServerEvents (line 567) | interface ClientToServerEvents {
type ServerToClientEvents (line 572) | interface ServerToClientEvents {
type InterServerEvents (line 577) | interface InterServerEvents {
class MyCustomAdapter (line 653) | class MyCustomAdapter extends Adapter {
method constructor (line 654) | constructor(
FILE: packages/socket.io/test/socket.ts
type Events (line 609) | type Events = {
FILE: packages/socket.io/test/support/expectjs.d.ts
type Assertion (line 4) | interface Assertion {
type Root (line 158) | interface Root extends Assertion {
type Be (line 166) | interface Be extends Assertion {
type An (line 175) | interface An extends Assertion {
type Not (line 187) | interface Not extends Expect.NotBase {
type NotBase (line 191) | interface NotBase extends Assertion {
type To (line 198) | interface To extends Expect.ToBase {
type ToBase (line 202) | interface ToBase extends Assertion {
type Only (line 209) | interface Only extends Assertion {
type Have (line 213) | interface Have extends Assertion {
FILE: packages/socket.io/test/support/util.ts
function createClient (line 36) | function createClient<
function success (line 48) | function success(
function successFn (line 58) | function successFn(
function assert (line 72) | function assert(condition: any): asserts condition {
function getPort (line 76) | function getPort(io: Server): number {
function createPartialDone (line 80) | function createPartialDone(count: number, done: (err?: Error) => void) {
function waitFor (line 91) | function waitFor<T = unknown>(emitter, event) {
function eioHandshake (line 98) | function eioHandshake(httpServer): Promise<string> {
function eioPush (line 110) | function eioPush(httpServer, sid: string, body: string): Promise<void> {
function eioPoll (line 123) | function eioPoll(httpServer, sid): Promise<string> {
FILE: packages/socket.io/test/utility-methods.ts
constant SOCKETS_COUNT (line 11) | const SOCKETS_COUNT = 3;
class DummyAdapter (line 13) | class DummyAdapter extends Adapter {
method fetchSockets (line 14) | fetchSockets(opts: BroadcastOptions): Promise<any[]> {
Condensed preview — 756 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9,209K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 1043,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: 'to triage'\nassignees: ''\n\n---\n\n**Descr"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 182,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Ask a Question\n url: https://github.com/socketio/socket.io/discu"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 606,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: 'enhancement'\nassignees: ''\n\n---\n\n**"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 268,
"preview": "\n### The kind of change this PR does introduce\n\n* [x] a bug fix\n* [ ] a new feature\n* [ ] an update to the documentation"
},
{
"path": ".github/workflows/build-examples.yml",
"chars": 996,
"preview": "name: Build examples\n\non:\n schedule:\n - cron: '0 0 * * 0'\n\npermissions:\n contents: read\n\njobs:\n build-examples:\n "
},
{
"path": ".github/workflows/ci-browser.yml",
"chars": 921,
"preview": "name: CI (browser)\n\non:\n push:\n branches:\n - '**'\n paths:\n - 'packages/engine.io-parser/**'\n - 'pa"
},
{
"path": ".github/workflows/ci.yml",
"chars": 1800,
"preview": "name: CI\n\non:\n push:\n branches:\n - '**'\n pull_request:\n schedule:\n - cron: '0 0 * * 0'\n\npermissions:\n con"
},
{
"path": ".github/workflows/publish.yml",
"chars": 797,
"preview": "# reference: https://docs.npmjs.com/trusted-publishers#for-github-actions\n\nname: Publish\n\non:\n push:\n tags:\n # "
},
{
"path": ".gitignore",
"chars": 125,
"preview": ".DS_Store\nlib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\nbenchmarks/*.png\nnode_modules\ncoverage\n.idea\n.nyc_output\ndist/\nbu"
},
{
"path": "CHANGELOG.md",
"chars": 1538,
"preview": "# Changelog\n\nHere are the detailed changelogs for each package in this monorepo:\n\n| Package |"
},
{
"path": "CONTRIBUTING.md",
"chars": 7375,
"preview": "# Socket.IO Contributing Guide\n\nThanks a lot for your interest in contributing to Socket.IO!\n\nBefore submitting your con"
},
{
"path": "LICENSE",
"chars": 1113,
"preview": "(The MIT License)\n\nCopyright (c) 2014-present Guillermo Rauch and Socket.IO contributors\n\nPermission is hereby granted, "
},
{
"path": "README.md",
"chars": 1649,
"preview": "# socket.io\n\n[](https://www.npmjs.com/package/socket.io"
},
{
"path": "SECURITY.md",
"chars": 6931,
"preview": "# Security Policy\n\n<!-- TOC -->\n * [Supported Versions](#supported-versions)\n * [Reporting a Vulnerability](#reporting"
},
{
"path": "docs/README.md",
"chars": 82,
"preview": "\nThe documentation has been moved to the website [here](https://socket.io/docs/).\n"
},
{
"path": "docs/engine.io-protocol/v3-test-suite/.gitignore",
"chars": 13,
"preview": "node_modules\n"
},
{
"path": "docs/engine.io-protocol/v3-test-suite/index.html",
"chars": 705,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, "
},
{
"path": "docs/engine.io-protocol/v3-test-suite/node-imports.js",
"chars": 235,
"preview": "import fetch from \"node-fetch\";\nimport { WebSocket } from \"ws\";\nimport chai from \"chai\";\nimport chaiString from \"chai-st"
},
{
"path": "docs/engine.io-protocol/v3-test-suite/package.json",
"chars": 370,
"preview": "{\n \"name\": \"engine.io-protocol-test-suite\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {"
},
{
"path": "docs/engine.io-protocol/v3-test-suite/test-suite.js",
"chars": 16612,
"preview": "const isNodejs = typeof window === \"undefined\";\n\nif (isNodejs) {\n // make the tests runnable in both the browser and No"
},
{
"path": "docs/engine.io-protocol/v3.md",
"chars": 14655,
"preview": "# Engine.IO Protocol\n\nThis document describes the Engine.IO protocol. For a reference JavaScript\nimplementation, take a "
},
{
"path": "docs/engine.io-protocol/v4-current.md",
"chars": 16346,
"preview": "# Engine.IO Protocol\n\nThis document describes the 4th version of the Engine.IO protocol.\n\n**Table of content**\n\n- [Intro"
},
{
"path": "docs/engine.io-protocol/v4-test-suite/.gitignore",
"chars": 13,
"preview": "node_modules\n"
},
{
"path": "docs/engine.io-protocol/v4-test-suite/index.html",
"chars": 705,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, "
},
{
"path": "docs/engine.io-protocol/v4-test-suite/node-imports.js",
"chars": 235,
"preview": "import fetch from \"node-fetch\";\nimport { WebSocket } from \"ws\";\nimport chai from \"chai\";\nimport chaiString from \"chai-st"
},
{
"path": "docs/engine.io-protocol/v4-test-suite/package.json",
"chars": 370,
"preview": "{\n \"name\": \"engine.io-protocol-test-suite\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {"
},
{
"path": "docs/engine.io-protocol/v4-test-suite/test-suite.js",
"chars": 16642,
"preview": "const isNodejs = typeof window === \"undefined\";\n\nif (isNodejs) {\n // make the tests runnable in both the browser and No"
},
{
"path": "docs/socket.io-protocol/v3.md",
"chars": 9022,
"preview": "\n# socket.io-protocol\n\n This document describes the Socket.IO protocol. For a reference JavaScript\n implementation, ta"
},
{
"path": "docs/socket.io-protocol/v4.md",
"chars": 13251,
"preview": "\n# socket.io-protocol\n\n This document describes the Socket.IO protocol. For a reference JavaScript\n implementation, ta"
},
{
"path": "docs/socket.io-protocol/v5-current.md",
"chars": 20232,
"preview": "# Socket.IO Protocol\n\nThis document describes the 5th version of the Socket.IO protocol.\n\n**Table of content**\n\n- [Intro"
},
{
"path": "docs/socket.io-protocol/v5-test-suite/.gitignore",
"chars": 13,
"preview": "node_modules\n"
},
{
"path": "docs/socket.io-protocol/v5-test-suite/index.html",
"chars": 705,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, "
},
{
"path": "docs/socket.io-protocol/v5-test-suite/node-imports.js",
"chars": 235,
"preview": "import fetch from \"node-fetch\";\nimport { WebSocket } from \"ws\";\nimport chai from \"chai\";\nimport chaiString from \"chai-st"
},
{
"path": "docs/socket.io-protocol/v5-test-suite/package.json",
"chars": 370,
"preview": "{\n \"name\": \"socket.io-protocol-test-suite\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"type\": \"module\",\n \"scripts\": {"
},
{
"path": "docs/socket.io-protocol/v5-test-suite/test-suite.js",
"chars": 18337,
"preview": "const isNodejs = typeof window === \"undefined\";\n\nif (isNodejs) {\n // make the tests runnable in both the browser and No"
},
{
"path": "examples/.gitignore",
"chars": 18,
"preview": "package-lock.json\n"
},
{
"path": "examples/ReactNativeExample/.bundle/config",
"chars": 59,
"preview": "BUNDLE_PATH: \"vendor/bundle\"\nBUNDLE_FORCE_RUBY_PLATFORM: 1\n"
},
{
"path": "examples/ReactNativeExample/.eslintrc.js",
"chars": 64,
"preview": "module.exports = {\n root: true,\n extends: '@react-native',\n};\n"
},
{
"path": "examples/ReactNativeExample/.gitignore",
"chars": 989,
"preview": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.p"
},
{
"path": "examples/ReactNativeExample/.prettierrc.js",
"chars": 141,
"preview": "module.exports = {\n arrowParens: 'avoid',\n bracketSameLine: true,\n bracketSpacing: false,\n singleQuote: true,\n trai"
},
{
"path": "examples/ReactNativeExample/.watchmanconfig",
"chars": 3,
"preview": "{}\n"
},
{
"path": "examples/ReactNativeExample/App.tsx",
"chars": 2398,
"preview": "/**\n * Sample React Native App\n * https://github.com/facebook/react-native\n *\n * @format\n */\n\nimport React from 'react';"
},
{
"path": "examples/ReactNativeExample/Gemfile",
"chars": 365,
"preview": "source 'https://rubygems.org'\n\n# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version\nruby \""
},
{
"path": "examples/ReactNativeExample/README.md",
"chars": 3160,
"preview": "This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](ht"
},
{
"path": "examples/ReactNativeExample/__tests__/App.test.tsx",
"chars": 364,
"preview": "/**\n * @format\n */\n\nimport 'react-native';\nimport React from 'react';\nimport App from '../App';\n\n// Note: import explici"
},
{
"path": "examples/ReactNativeExample/android/app/build.gradle",
"chars": 4748,
"preview": "apply plugin: \"com.android.application\"\napply plugin: \"org.jetbrains.kotlin.android\"\napply plugin: \"com.facebook.react\"\n"
},
{
"path": "examples/ReactNativeExample/android/app/proguard-rules.pro",
"chars": 435,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /u"
},
{
"path": "examples/ReactNativeExample/android/app/src/debug/AndroidManifest.xml",
"chars": 313,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:to"
},
{
"path": "examples/ReactNativeExample/android/app/src/main/AndroidManifest.xml",
"chars": 971,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n <uses-permission android:name=\"android.permis"
},
{
"path": "examples/ReactNativeExample/android/app/src/main/java/com/reactnativeexample/MainActivity.kt",
"chars": 867,
"preview": "package com.reactnativeexample\n\nimport com.facebook.react.ReactActivity\nimport com.facebook.react.ReactActivityDelegate\n"
},
{
"path": "examples/ReactNativeExample/android/app/src/main/java/com/reactnativeexample/MainApplication.kt",
"chars": 1734,
"preview": "package com.reactnativeexample\n\nimport android.app.Application\nimport com.facebook.react.PackageList\nimport com.facebook"
},
{
"path": "examples/ReactNativeExample/android/app/src/main/res/drawable/rn_edit_text_material.xml",
"chars": 1909,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2014 The Android Open Source Project\n\n Licensed under the "
},
{
"path": "examples/ReactNativeExample/android/app/src/main/res/values/strings.xml",
"chars": 81,
"preview": "<resources>\n <string name=\"app_name\">ReactNativeExample</string>\n</resources>\n"
},
{
"path": "examples/ReactNativeExample/android/app/src/main/res/values/styles.xml",
"chars": 282,
"preview": "<resources>\n\n <!-- Base application theme. -->\n <style name=\"AppTheme\" parent=\"Theme.AppCompat.DayNight.NoActionBa"
},
{
"path": "examples/ReactNativeExample/android/build.gradle",
"chars": 545,
"preview": "buildscript {\n ext {\n buildToolsVersion = \"34.0.0\"\n minSdkVersion = 21\n compileSdkVersion = 34\n "
},
{
"path": "examples/ReactNativeExample/android/gradle/wrapper/gradle-wrapper.properties",
"chars": 250,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "examples/ReactNativeExample/android/gradle.properties",
"chars": 1827,
"preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
},
{
"path": "examples/ReactNativeExample/android/gradlew",
"chars": 8616,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "examples/ReactNativeExample/android/gradlew.bat",
"chars": 2868,
"preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
},
{
"path": "examples/ReactNativeExample/android/settings.gradle",
"chars": 262,
"preview": "rootProject.name = 'ReactNativeExample'\napply from: file(\"../node_modules/@react-native-community/cli-platform-android/n"
},
{
"path": "examples/ReactNativeExample/app.json",
"chars": 74,
"preview": "{\n \"name\": \"ReactNativeExample\",\n \"displayName\": \"ReactNativeExample\"\n}\n"
},
{
"path": "examples/ReactNativeExample/babel.config.js",
"chars": 72,
"preview": "module.exports = {\n presets: ['module:@react-native/babel-preset'],\n};\n"
},
{
"path": "examples/ReactNativeExample/index.js",
"chars": 183,
"preview": "/**\n * @format\n */\n\nimport {AppRegistry} from 'react-native';\nimport App from './App';\nimport {name as appName} from './"
},
{
"path": "examples/ReactNativeExample/ios/.xcode.env",
"chars": 482,
"preview": "# This `.xcode.env` file is versioned and is used to source the environment\n# used when running script phases inside Xco"
},
{
"path": "examples/ReactNativeExample/ios/Podfile",
"chars": 1831,
"preview": "# Resolve react_native_pods.rb with node to allow for hoisting\nrequire Pod::Executable.execute_command('node', ['-p',\n "
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/AppDelegate.h",
"chars": 98,
"preview": "#import <RCTAppDelegate.h>\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : RCTAppDelegate\n\n@end\n"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/AppDelegate.mm",
"chars": 816,
"preview": "#import \"AppDelegate.h\"\n\n#import <React/RCTBundleURLProvider.h>\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApp"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/Images.xcassets/AppIcon.appiconset/Contents.json",
"chars": 849,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"iphone\",\n \"scale\" : \"2x\",\n \"size\" : \"20x20\"\n },\n {\n \"idiom\""
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/Images.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"version\" : 1,\n \"author\" : \"xcode\"\n }\n}\n"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/Info.plist",
"chars": 1626,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/LaunchScreen.storyboard",
"chars": 4242,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample/main.m",
"chars": 199,
"preview": "#import <UIKit/UIKit.h>\n\n#import \"AppDelegate.h\"\n\nint main(int argc, char *argv[])\n{\n @autoreleasepool {\n return UIA"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample.xcodeproj/project.pbxproj",
"chars": 29133,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 54;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExample.xcodeproj/xcshareddata/xcschemes/ReactNativeExample.xcscheme",
"chars": 3402,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1210\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExampleTests/Info.plist",
"chars": 733,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "examples/ReactNativeExample/ios/ReactNativeExampleTests/ReactNativeExampleTests.m",
"chars": 2012,
"preview": "#import <UIKit/UIKit.h>\n#import <XCTest/XCTest.h>\n\n#import <React/RCTLog.h>\n#import <React/RCTRootView.h>\n\n#define TIMEO"
},
{
"path": "examples/ReactNativeExample/jest.config.js",
"chars": 48,
"preview": "module.exports = {\n preset: 'react-native',\n};\n"
},
{
"path": "examples/ReactNativeExample/metro.config.js",
"chars": 302,
"preview": "const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\n/**\n * Metro configuration\n * https://fa"
},
{
"path": "examples/ReactNativeExample/package.json",
"chars": 953,
"preview": "{\n \"name\": \"ReactNativeExample\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"scripts\": {\n \"android\": \"react-native r"
},
{
"path": "examples/ReactNativeExample/server/index.js",
"chars": 269,
"preview": "import { Server } from 'socket.io';\n\nconst io = new Server();\n\nio.on('connection', (socket) => {\n console.log(`connect:"
},
{
"path": "examples/ReactNativeExample/server/package.json",
"chars": 244,
"preview": "{\n \"name\": \"server\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"type\": \"module\",\n \"scripts\": "
},
{
"path": "examples/ReactNativeExample/socket.js",
"chars": 132,
"preview": "import { io } from 'socket.io-client';\n\nexport const socket = io('http://192.168.0.10:3000'); //\tuse the IP address of y"
},
{
"path": "examples/ReactNativeExample/tsconfig.json",
"chars": 65,
"preview": "{\n \"extends\": \"@react-native/typescript-config/tsconfig.json\"\n}\n"
},
{
"path": "examples/angular-todomvc/.browserslistrc",
"chars": 703,
"preview": "# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.\n# For addit"
},
{
"path": "examples/angular-todomvc/.editorconfig",
"chars": 274,
"preview": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size ="
},
{
"path": "examples/angular-todomvc/.gitignore",
"chars": 631,
"preview": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist\n/tmp\n/out-tsc\n# Only "
},
{
"path": "examples/angular-todomvc/README.md",
"chars": 1277,
"preview": "# Angular TodoMVC + Socket.IO\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) ver"
},
{
"path": "examples/angular-todomvc/angular.json",
"chars": 3695,
"preview": "{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"newProjectRoot\": \"projects\",\n \""
},
{
"path": "examples/angular-todomvc/e2e/protractor.conf.js",
"chars": 904,
"preview": "// @ts-check\n// Protractor configuration file, see link for more information\n// https://github.com/angular/protractor/bl"
},
{
"path": "examples/angular-todomvc/e2e/src/app.e2e-spec.ts",
"chars": 666,
"preview": "import { AppPage } from './app.po';\nimport { browser, logging } from 'protractor';\n\ndescribe('workspace-project App', ()"
},
{
"path": "examples/angular-todomvc/e2e/src/app.po.ts",
"chars": 274,
"preview": "import { browser, by, element } from 'protractor';\n\nexport class AppPage {\n async navigateTo(): Promise<unknown> {\n "
},
{
"path": "examples/angular-todomvc/e2e/tsconfig.json",
"chars": 274,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"../tsconfig.json\",\n \"compi"
},
{
"path": "examples/angular-todomvc/karma.conf.js",
"chars": 1432,
"preview": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-fi"
},
{
"path": "examples/angular-todomvc/package.json",
"chars": 1338,
"preview": "{\n \"name\": \"angular-todomvc\",\n \"version\": \"0.0.0\",\n \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"ng serve\",\n \"build\""
},
{
"path": "examples/angular-todomvc/server.ts",
"chars": 631,
"preview": "import { Server } from \"socket.io\";\n\nconst io = new Server(8080, {\n cors: {\n origin: \"http://localhost:4200\",\n me"
},
{
"path": "examples/angular-todomvc/src/app/app.component.css",
"chars": 0,
"preview": ""
},
{
"path": "examples/angular-todomvc/src/app/app.component.html",
"chars": 1524,
"preview": "<section class=\"todoapp\">\n <header class=\"header\">\n <h1>todos</h1>\n <input class=\"new-todo\" placeholder=\"What nee"
},
{
"path": "examples/angular-todomvc/src/app/app.component.spec.ts",
"chars": 967,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { AppComponent } from './app.component';\n\ndescribe('AppComponent"
},
{
"path": "examples/angular-todomvc/src/app/app.component.ts",
"chars": 1186,
"preview": "import { Component } from '@angular/core';\nimport { RemoteTodoStore, Todo } from './store';\n\n@Component({\n selector: 'a"
},
{
"path": "examples/angular-todomvc/src/app/app.module.ts",
"chars": 435,
"preview": "import { BrowserModule } from '@angular/platform-browser';\nimport { NgModule } from '@angular/core';\n\nimport { AppCompon"
},
{
"path": "examples/angular-todomvc/src/app/store.ts",
"chars": 2131,
"preview": "import { io, Socket } from \"socket.io-client\";\n\nexport class Todo {\n completed: boolean;\n editing: boolean;\n\n private"
},
{
"path": "examples/angular-todomvc/src/assets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "examples/angular-todomvc/src/environments/environment.prod.ts",
"chars": 51,
"preview": "export const environment = {\n production: true\n};\n"
},
{
"path": "examples/angular-todomvc/src/environments/environment.ts",
"chars": 662,
"preview": "// This file can be replaced during build by using the `fileReplacements` array.\n// `ng build --prod` replaces `environm"
},
{
"path": "examples/angular-todomvc/src/index.html",
"chars": 302,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>Angular Todo MVC</title>\n <base href=\"/\">\n <"
},
{
"path": "examples/angular-todomvc/src/main.ts",
"chars": 372,
"preview": "import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynami"
},
{
"path": "examples/angular-todomvc/src/polyfills.ts",
"chars": 2826,
"preview": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfi"
},
{
"path": "examples/angular-todomvc/src/styles.css",
"chars": 7245,
"preview": "/* imported from node_modules/todomvc-app-css/index.css */\nhtml,\nbody {\n margin: 0;\n padding: 0;\n}\n\nbutton {\n margin:"
},
{
"path": "examples/angular-todomvc/src/test.ts",
"chars": 753,
"preview": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/dist/"
},
{
"path": "examples/angular-todomvc/tsconfig.app.json",
"chars": 287,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"./tsconfig.json\",\n \"compil"
},
{
"path": "examples/angular-todomvc/tsconfig.json",
"chars": 737,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"compileOnSave\": false,\n \"compilerOpti"
},
{
"path": "examples/angular-todomvc/tsconfig.spec.json",
"chars": 333,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"./tsconfig.json\",\n \"compil"
},
{
"path": "examples/angular-todomvc/tslint.json",
"chars": 3185,
"preview": "{\n \"extends\": \"tslint:recommended\",\n \"rulesDirectory\": [\n \"codelyzer\"\n ],\n \"rules\": {\n \"align\": {\n \"optio"
},
{
"path": "examples/basic-crud-application/README.md",
"chars": 1222,
"preview": "# Basic CRUD application with Socket.IO\n\nPlease read the related [guide](https://socket.io/get-started/basic-crud-applic"
},
{
"path": "examples/basic-crud-application/angular-client/.editorconfig",
"chars": 274,
"preview": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size ="
},
{
"path": "examples/basic-crud-application/angular-client/.gitignore",
"chars": 548,
"preview": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# Compiled output\n/dist\n/tmp\n/out-tsc\n/bazel-"
},
{
"path": "examples/basic-crud-application/angular-client/README.md",
"chars": 1067,
"preview": "# AngularClient\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.2.\n\n"
},
{
"path": "examples/basic-crud-application/angular-client/angular.json",
"chars": 2857,
"preview": "{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"newProjectRoot\": \"projects\",\n \""
},
{
"path": "examples/basic-crud-application/angular-client/package.json",
"chars": 1109,
"preview": "{\n \"name\": \"angular-client\",\n \"version\": \"0.0.0\",\n \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"ng serve\",\n \"build\":"
},
{
"path": "examples/basic-crud-application/angular-client/src/app/app.component.css",
"chars": 0,
"preview": ""
},
{
"path": "examples/basic-crud-application/angular-client/src/app/app.component.html",
"chars": 1664,
"preview": "<section class=\"todoapp\">\n <header class=\"header\">\n <h1>todos</h1>\n<!-- <input class=\"new-todo\" placeholder=\"What"
},
{
"path": "examples/basic-crud-application/angular-client/src/app/app.component.spec.ts",
"chars": 940,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { AppComponent } from './app.component';\n\ndescribe('AppComponent"
},
{
"path": "examples/basic-crud-application/angular-client/src/app/app.component.ts",
"chars": 1431,
"preview": "import { Component } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterOutlet } from "
},
{
"path": "examples/basic-crud-application/angular-client/src/app/app.config.ts",
"chars": 227,
"preview": "import { ApplicationConfig } from '@angular/core';\nimport { provideRouter } from '@angular/router';\n\nimport { routes } f"
},
{
"path": "examples/basic-crud-application/angular-client/src/app/app.routes.ts",
"chars": 77,
"preview": "import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"
},
{
"path": "examples/basic-crud-application/angular-client/src/app/store.ts",
"chars": 3202,
"preview": "import { io, Socket } from \"socket.io-client\";\nimport { ClientEvents, ServerEvents } from \"../../../common/events\";\nimpo"
},
{
"path": "examples/basic-crud-application/angular-client/src/assets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "examples/basic-crud-application/angular-client/src/environments/environment.development.ts",
"chars": 69,
"preview": "export const environment = {\n serverUrl: \"http://localhost:3000\"\n};\n"
},
{
"path": "examples/basic-crud-application/angular-client/src/environments/environment.ts",
"chars": 76,
"preview": "export const environment = {\n serverUrl: \"https://my-custom-domain.com\"\n};\n"
},
{
"path": "examples/basic-crud-application/angular-client/src/index.html",
"chars": 299,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>AngularClient</title>\n <base href=\"/\">\n <met"
},
{
"path": "examples/basic-crud-application/angular-client/src/main.ts",
"chars": 250,
"preview": "import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport {"
},
{
"path": "examples/basic-crud-application/angular-client/src/styles.css",
"chars": 7245,
"preview": "/* imported from node_modules/todomvc-app-css/index.css */\nhtml,\nbody {\n margin: 0;\n padding: 0;\n}\n\nbutton {\n margin:"
},
{
"path": "examples/basic-crud-application/angular-client/tsconfig.app.json",
"chars": 263,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"./tsconfig.json\",\n \"compil"
},
{
"path": "examples/basic-crud-application/angular-client/tsconfig.json",
"chars": 877,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"compileOnSave\": false,\n \"compilerOpti"
},
{
"path": "examples/basic-crud-application/angular-client/tsconfig.spec.json",
"chars": 273,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"./tsconfig.json\",\n \"compil"
},
{
"path": "examples/basic-crud-application/common/events.ts",
"chars": 956,
"preview": "export type TodoID = string;\n\nexport interface Todo {\n id: TodoID;\n completed: boolean;\n title: string;\n}\n\ninterface "
},
{
"path": "examples/basic-crud-application/server/lib/app.ts",
"chars": 1002,
"preview": "import { Server as HttpServer } from \"http\";\nimport { Server, ServerOptions } from \"socket.io\";\nimport { ClientEvents, S"
},
{
"path": "examples/basic-crud-application/server/lib/index.ts",
"chars": 382,
"preview": "import { createServer } from \"http\";\nimport { createApplication } from \"./app\";\nimport { InMemoryTodoRepository } from \""
},
{
"path": "examples/basic-crud-application/server/lib/todo-management/todo.handlers.ts",
"chars": 3721,
"preview": "import { Errors, mapErrorDetails, sanitizeErrorMessage } from \"../util\";\nimport { v4 as uuid } from \"uuid\";\nimport { Com"
},
{
"path": "examples/basic-crud-application/server/lib/todo-management/todo.repository.ts",
"chars": 1149,
"preview": "import { Errors } from \"../util\";\nimport { Todo, TodoID } from \"../../../common/events\";\n\nabstract class CrudRepository<"
},
{
"path": "examples/basic-crud-application/server/lib/util.ts",
"chars": 585,
"preview": "import { ValidationErrorItem } from \"joi\";\n\nexport enum Errors {\n ENTITY_NOT_FOUND = \"entity not found\",\n INVALID_PAYL"
},
{
"path": "examples/basic-crud-application/server/package.json",
"chars": 987,
"preview": "{\n \"name\": \"basic-crud-server\",\n \"version\": \"0.0.1\",\n \"description\": \"Server for the Basic CRUD Socket.IO example\",\n "
},
{
"path": "examples/basic-crud-application/server/test/todo-management/todo.tests.ts",
"chars": 8191,
"preview": "import { createApplication } from \"../../lib/app\";\nimport { createServer, Server } from \"http\";\nimport {\n InMemoryTodoR"
},
{
"path": "examples/basic-crud-application/server/tsconfig.json",
"chars": 161,
"preview": "{\n \"compilerOptions\": {\n \"outDir\": \"./dist\",\n \"module\": \"commonjs\",\n \"target\": \"es2017\",\n \"strict\": true\n "
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/README.md",
"chars": 647,
"preview": "\nA basic TODO project.\n\n| Characteristic | "
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/docker-compose.yml",
"chars": 143,
"preview": "version: \"3\"\n\nservices:\n postgres:\n image: postgres:12\n ports:\n - \"5432:5432\"\n environment:\n POSTGRE"
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/lib/app.js",
"chars": 865,
"preview": "import { Server } from \"socket.io\";\nimport createTodoHandlers from \"./todo-management/todo.handlers.js\";\nimport { setupW"
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/lib/cluster.js",
"chars": 634,
"preview": "import cluster from \"cluster\";\nimport { createServer } from \"http\";\nimport { setupMaster } from \"@socket.io/sticky\";\nimp"
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/lib/index.js",
"chars": 1154,
"preview": "import { createServer } from \"http\";\nimport { createApplication } from \"./app.js\";\nimport { Sequelize } from \"sequelize\""
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/lib/todo-management/todo.handlers.js",
"chars": 3121,
"preview": "import { Errors, mapErrorDetails, sanitizeErrorMessage } from \"../util.js\";\nimport { v4 as uuid } from \"uuid\";\nimport Jo"
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/lib/todo-management/todo.repository.js",
"chars": 1510,
"preview": "import { Errors } from \"../util.js\";\nimport { Model, DataTypes } from \"sequelize\";\n\nclass CrudRepository {\n findAll() {"
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/lib/util.js",
"chars": 505,
"preview": "export const Errors = {\n ENTITY_NOT_FOUND: \"entity not found\",\n INVALID_PAYLOAD: \"invalid payload\",\n};\n\nconst errorVal"
},
{
"path": "examples/basic-crud-application/server-postgres-cluster/package.json",
"chars": 847,
"preview": "{\n \"name\": \"basic-crud-server\",\n \"version\": \"0.0.1\",\n \"description\": \"Server for the Basic CRUD Socket.IO example (wi"
},
{
"path": "examples/basic-crud-application/vue-client/.gitignore",
"chars": 231,
"preview": ".DS_Store\nnode_modules\n/dist\n\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyar"
},
{
"path": "examples/basic-crud-application/vue-client/README.md",
"chars": 314,
"preview": "# vue-client\n\n## Project setup\n```\nyarn install\n```\n\n### Compiles and hot-reloads for development\n```\nyarn serve\n```\n\n##"
},
{
"path": "examples/basic-crud-application/vue-client/babel.config.js",
"chars": 73,
"preview": "module.exports = {\n presets: [\n '@vue/cli-plugin-babel/preset'\n ]\n}\n"
},
{
"path": "examples/basic-crud-application/vue-client/jsconfig.json",
"chars": 279,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"module\": \"esnext\",\n \"baseUrl\": \"./\",\n \"moduleResolution\": \"node"
},
{
"path": "examples/basic-crud-application/vue-client/package.json",
"chars": 955,
"preview": "{\n \"name\": \"vue-client\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"serve\": \"vue-cli-service serve --"
},
{
"path": "examples/basic-crud-application/vue-client/public/index.html",
"chars": 675,
"preview": "<!DOCTYPE html>\n<html lang=\"\">\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
},
{
"path": "examples/basic-crud-application/vue-client/public/styles.css",
"chars": 7245,
"preview": "/* imported from node_modules/todomvc-app-css/index.css */\nhtml,\nbody {\n margin: 0;\n padding: 0;\n}\n\nbutton {\n margin:"
},
{
"path": "examples/basic-crud-application/vue-client/src/App.vue",
"chars": 2889,
"preview": "<script setup>\nimport { computed, ref } from \"vue\";\nimport { useTodoStore } from \"@/stores/todo\";\nimport { socket } from"
},
{
"path": "examples/basic-crud-application/vue-client/src/main.js",
"chars": 193,
"preview": "import { createApp } from \"vue\";\nimport { createPinia } from \"pinia\";\nimport App from \"./App.vue\";\n\nconst pinia = create"
},
{
"path": "examples/basic-crud-application/vue-client/src/socket.js",
"chars": 243,
"preview": "import { io } from \"socket.io-client\";\n\n// \"undefined\" means the URL will be computed from the `window.location` object\n"
},
{
"path": "examples/basic-crud-application/vue-client/src/stores/todo.js",
"chars": 2289,
"preview": "import { defineStore } from \"pinia\";\nimport { socket } from \"@/socket\";\n\nexport const useTodoStore = defineStore(\"todo\","
},
{
"path": "examples/basic-crud-application/vue-client/vue.config.js",
"chars": 118,
"preview": "const { defineConfig } = require('@vue/cli-service')\nmodule.exports = defineConfig({\n transpileDependencies: true\n})\n"
},
{
"path": "examples/basic-websocket-client/README.md",
"chars": 290,
"preview": "# Basic Socket.IO client\n\nPlease check the associated guide: https://socket.io/how-to/build-a-basic-client\n\nContent:\n\n``"
},
{
"path": "examples/basic-websocket-client/check-bundle-size.js",
"chars": 468,
"preview": "import { rollup } from \"rollup\";\nimport terser from \"@rollup/plugin-terser\";\nimport { brotliCompressSync } from \"node:zl"
},
{
"path": "examples/basic-websocket-client/package.json",
"chars": 395,
"preview": "{\n \"type\": \"module\",\n \"devDependencies\": {\n \"@rollup/plugin-terser\": \"^0.4.0\",\n \"chai\": \"^4.3.7\",\n \"mocha\": \""
},
{
"path": "examples/basic-websocket-client/rollup.config.js",
"chars": 191,
"preview": "import terser from \"@rollup/plugin-terser\";\n\nexport default {\n input: \"./src/index.js\",\n output: {\n file: \"./bundle"
},
{
"path": "examples/basic-websocket-client/src/index.js",
"chars": 5466,
"preview": "class EventEmitter {\n #listeners = new Map();\n\n on(event, listener) {\n let listeners = this.#listeners.get(event);\n"
},
{
"path": "examples/basic-websocket-client/test/index.js",
"chars": 3586,
"preview": "import { createServer } from \"node:http\";\nimport { io as ioc } from \"../src/index.js\";\nimport { WebSocket } from \"ws\";\ni"
},
{
"path": "examples/chat/README.md",
"chars": 446,
"preview": "\n# Socket.IO Chat\n\nA simple chat demo for Socket.IO\n\n## How to use\n\n```\n$ npm i\n$ npm start\n```\n\nAnd point your browser "
},
{
"path": "examples/chat/index.js",
"chars": 1945,
"preview": "// Setup basic express server\nconst express = require('express');\nconst app = express();\nconst path = require('path');\nc"
},
{
"path": "examples/chat/package.json",
"chars": 328,
"preview": "{\n \"name\": \"socket.io-chat\",\n \"version\": \"0.0.0\",\n \"description\": \"A simple chat client using socket.io\",\n \"main\": \""
},
{
"path": "examples/chat/public/index.html",
"chars": 737,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Socket.IO Chat Example</title>\n <link rel=\"st"
},
{
"path": "examples/chat/public/main.js",
"chars": 7549,
"preview": "$(function() {\n const FADE_TIME = 150; // ms\n const TYPING_TIMER_LENGTH = 400; // ms\n const COLORS = [\n '#e21400',"
},
{
"path": "examples/chat/public/style.css",
"chars": 1870,
"preview": "/* Fix user-agent */\n\n* {\n box-sizing: border-box;\n}\n\nhtml {\n font-weight: 300;\n -webkit-font-smoothing: antialiased;"
},
{
"path": "examples/cluster-engine-node-cluster/README.md",
"chars": 747,
"preview": "# Example with `@socket.io/cluster-engine` and Node.js cluster\n\n## How to use\n\n```bash\n# run the server\n$ node server.js"
},
{
"path": "examples/cluster-engine-node-cluster/client.js",
"chars": 600,
"preview": "import { io } from \"socket.io-client\";\n\nconst CLIENTS_COUNT = 3;\n\nfor (let i = 0; i < CLIENTS_COUNT; i++) {\n const sock"
},
{
"path": "examples/cluster-engine-node-cluster/package.json",
"chars": 277,
"preview": "{\n \"private\": true,\n \"name\": \"cluster-engine-node-cluster\",\n \"version\": \"0.0.1\",\n \"type\": \"module\",\n \"dependencies\""
},
{
"path": "examples/cluster-engine-node-cluster/server.js",
"chars": 1478,
"preview": "import cluster from \"node:cluster\";\nimport process from \"node:process\";\nimport { availableParallelism } from \"node:os\";\n"
},
{
"path": "examples/cluster-engine-redis/README.md",
"chars": 855,
"preview": "# Example with `@socket.io/cluster-engine` and Redis\n\n## How to use\n\n```bash\n# start the redis server\n$ docker compose u"
},
{
"path": "examples/cluster-engine-redis/client.js",
"chars": 600,
"preview": "import { io } from \"socket.io-client\";\n\nconst CLIENTS_COUNT = 3;\n\nfor (let i = 0; i < CLIENTS_COUNT; i++) {\n const sock"
},
{
"path": "examples/cluster-engine-redis/compose.yaml",
"chars": 69,
"preview": "services:\n redis:\n image: redis:7\n ports:\n - \"6379:6379\"\n"
},
{
"path": "examples/cluster-engine-redis/package.json",
"chars": 321,
"preview": "{\n \"private\": true,\n \"name\": \"cluster-engine-redis\",\n \"version\": \"0.0.1\",\n \"type\": \"module\",\n \"dependencies\": {\n "
},
{
"path": "examples/cluster-engine-redis/server.js",
"chars": 1563,
"preview": "import { RedisEngine } from \"@socket.io/cluster-engine\";\nimport { createServer } from \"node:http\";\nimport { createClient"
},
{
"path": "examples/cluster-haproxy/README.md",
"chars": 971,
"preview": "\n# Socket.IO Chat with haproxy & redis\n\nA simple chat demo for socket.io\n\n## How to use\n\nInstall [Docker Compose](https:"
},
{
"path": "examples/cluster-haproxy/docker-compose.yml",
"chars": 805,
"preview": "services:\n haproxy:\n image: haproxy:1.7-alpine\n volumes:\n - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg"
},
{
"path": "examples/cluster-haproxy/haproxy.cfg",
"chars": 800,
"preview": "# Reference: http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/\n\nglobal\n daemon\n maxconn 4096\n"
},
{
"path": "examples/cluster-haproxy/server/Dockerfile",
"chars": 251,
"preview": "FROM node:14-alpine\n\n# Create app directory\nRUN mkdir -p /usr/src/app\nWORKDIR /usr/src/app\n\n# Install app dependencies\nC"
},
{
"path": "examples/cluster-haproxy/server/index.js",
"chars": 2267,
"preview": "// Setup basic express server\nvar express = require('express');\nvar app = express();\nvar server = require('http').create"
},
{
"path": "examples/cluster-haproxy/server/package.json",
"chars": 360,
"preview": "{\n \"name\": \"socket.io-chat\",\n \"version\": \"0.0.0\",\n \"description\": \"A simple chat client using socket.io\",\n \"main\": \""
},
{
"path": "examples/cluster-haproxy/server/public/index.html",
"chars": 737,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>Socket.IO Chat Example</title>\n <link rel=\"st"
},
{
"path": "examples/cluster-haproxy/server/public/main.js",
"chars": 7699,
"preview": "$(function() {\n var FADE_TIME = 150; // ms\n var TYPING_TIMER_LENGTH = 400; // ms\n var COLORS = [\n '#e21400', '#915"
},
{
"path": "examples/cluster-haproxy/server/public/style.css",
"chars": 1870,
"preview": "/* Fix user-agent */\n\n* {\n box-sizing: border-box;\n}\n\nhtml {\n font-weight: 300;\n -webkit-font-smoothing: antialiased;"
},
{
"path": "examples/cluster-httpd/README.md",
"chars": 955,
"preview": "\n# Socket.IO Chat with httpd & redis\n\nA simple chat demo for socket.io\n\n## How to use\n\nInstall [Docker Compose](https://"
},
{
"path": "examples/cluster-httpd/docker-compose.yml",
"chars": 795,
"preview": "services:\n httpd:\n image: httpd:2.4-alpine\n volumes:\n - ./httpd.conf:/usr/local/apache2/conf/httpd.conf:ro\n "
},
{
"path": "examples/cluster-httpd/httpd.conf",
"chars": 2185,
"preview": "\nListen 80\n\nServerName localhost\n\nLoadModule mpm_event_module modules/mod_mpm_event.so\n\nLoadModule authn_fil"
},
{
"path": "examples/cluster-httpd/server/Dockerfile",
"chars": 251,
"preview": "FROM node:14-alpine\n\n# Create app directory\nRUN mkdir -p /usr/src/app\nWORKDIR /usr/src/app\n\n# Install app dependencies\nC"
},
{
"path": "examples/cluster-httpd/server/index.js",
"chars": 2181,
"preview": "// Setup basic express server\nvar express = require('express');\nvar app = express();\nvar server = require('http').create"
}
]
// ... and 556 more files (download for full content)
About this extraction
This page contains the full source code of the socketio/socket.io GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 756 files (8.1 MB), approximately 2.2M tokens, and a symbol index with 1447 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.