Skip to content

Type fixes in core library #434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/laravel-echo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@
"@babel/plugin-transform-numeric-separator": "^7.25.9",
"@babel/plugin-transform-object-assign": "^7.25.9",
"@babel/preset-env": "^7.26.7",
"@types/jquery": "^3.5.32",
"@types/node": "^20.0.0",
"@typescript-eslint/eslint-plugin": "^8.21.0",
"@typescript-eslint/parser": "^8.21.0",
"axios": "^1.9.0",
"eslint": "^9.0.0",
"prettier": "^3.5.3",
"pusher-js": "^8.0",
Expand Down
33 changes: 10 additions & 23 deletions packages/laravel-echo/src/connector/connector.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/// <reference types="window" />

import type { Channel, PresenceChannel } from "../channel";
import type { BroadcastDriver, EchoOptions } from "../echo";

Expand Down Expand Up @@ -88,29 +90,14 @@ export abstract class Connector<
* Extract the CSRF token from the page.
*/
protected csrfToken(): null | string {
let selector;

if (
typeof window !== "undefined" &&
typeof window.Laravel !== "undefined" &&
window.Laravel.csrfToken
) {
return window.Laravel.csrfToken;
}

if (this.options.csrfToken) {
return this.options.csrfToken;
}

if (
typeof document !== "undefined" &&
typeof document.querySelector === "function" &&
(selector = document.querySelector('meta[name="csrf-token"]'))
) {
return selector.getAttribute("content");
}

return null;
return (
window?.Laravel?.csrfToken ??
this.options.csrfToken ??
document
?.querySelector('meta[name="csrf-token"]')
?.getAttribute("content") ??
null
);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/laravel-echo/src/connector/pusher-connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class PusherConnector<
*/
channels: Record<string, AnyPusherChannel> = {};

options: PusherOptions<TBroadcastDriver>;
declare options: PusherOptions<TBroadcastDriver>;

/**
* Create a fresh Pusher connection.
Expand Down
23 changes: 16 additions & 7 deletions packages/laravel-echo/src/echo.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { InternalAxiosRequestConfig } from "axios";
import {
Channel,
NullChannel,
Expand Down Expand Up @@ -179,7 +180,9 @@ export default class Echo<T extends keyof Broadcaster> {
* send a connections socket id to a Laravel app with a X-Socket-Id header.
*/
registerInterceptors(): void {
if (typeof Vue === "function" && Vue.http) {
// TODO: This package is deprecated and we should remove it in a future version.
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (typeof Vue !== "undefined" && Vue?.http) {
this.registerVueRequestInterceptor();
}

Expand All @@ -200,12 +203,15 @@ export default class Echo<T extends keyof Broadcaster> {
* Register a Vue HTTP interceptor to add the X-Socket-ID header.
*/
registerVueRequestInterceptor(): void {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
Vue.http.interceptors.push(
(request: Record<any, any>, next: CallableFunction) => {
if (this.socketId()) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
request.headers.set("X-Socket-ID", this.socketId());
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-call
next();
},
);
Expand All @@ -215,13 +221,15 @@ export default class Echo<T extends keyof Broadcaster> {
* Register an Axios HTTP interceptor to add the X-Socket-ID header.
*/
registerAxiosRequestInterceptor(): void {
axios.interceptors.request.use((config: Record<any, any>) => {
if (this.socketId()) {
config.headers["X-Socket-Id"] = this.socketId();
}
axios!.interceptors.request.use(
(config: InternalAxiosRequestConfig<any>) => {
if (this.socketId()) {
config.headers["X-Socket-Id"] = this.socketId();
}

return config;
});
return config;
},
);
}

/**
Expand Down Expand Up @@ -348,6 +356,7 @@ type GenericOptions<TBroadcaster extends keyof Broadcaster> = {
host?: string | null;
key?: string | null;
namespace?: string | false;
withoutInterceptors?: boolean;

[key: string]: any;
};
Expand Down
61 changes: 36 additions & 25 deletions packages/laravel-echo/tests/echo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,47 @@ import Echo from "../src/echo";

describe("Echo", () => {
test("it will not throw error for supported driver", () => {
expect(() => new Echo({ broadcaster: "reverb" })).not.toThrow(
"Broadcaster string reverb is not supported.",
);
expect(
() =>
new Echo({ broadcaster: "reverb", withoutInterceptors: true }),
).not.toThrow("Broadcaster string reverb is not supported.");

expect(() => new Echo({ broadcaster: "pusher" })).not.toThrow(
"Broadcaster string pusher is not supported.",
);
expect(
() =>
new Echo({ broadcaster: "pusher", withoutInterceptors: true }),
).not.toThrow("Broadcaster string pusher is not supported.");

expect(() => new Echo({ broadcaster: "socket.io" })).not.toThrow(
"Broadcaster string socket.io is not supported.",
);
expect(
() =>
new Echo({
broadcaster: "socket.io",
withoutInterceptors: true,
}),
).not.toThrow("Broadcaster string socket.io is not supported.");

expect(() => new Echo({ broadcaster: "null" })).not.toThrow(
"Broadcaster string null is not supported.",
);
expect(() => new Echo({ broadcaster: NullConnector })).not.toThrow();

// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-empty-function
expect(() => new Echo({ broadcaster: () => {} })).not.toThrow(
"Broadcaster function is not supported.",
);
expect(
() => new Echo({ broadcaster: "null", withoutInterceptors: true }),
).not.toThrow("Broadcaster string null is not supported.");
expect(
() =>
new Echo({
broadcaster: NullConnector,
withoutInterceptors: true,
}),
).not.toThrow();
expect(
() =>
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-empty-function
new Echo({ broadcaster: () => {}, withoutInterceptors: true }),
).not.toThrow("Broadcaster function is not supported.");
});

test("it will throw error for unsupported driver", () => {
// eslint-disable-next-line
// @ts-ignore
expect(() => new Echo({ broadcaster: "foo" })).toThrow(
"Broadcaster string foo is not supported.",
);
expect(
// @ts-ignore
// eslint-disable-next-line
() => new Echo({ broadcaster: "foo", withoutInterceptors: true }),
).toThrow("Broadcaster string foo is not supported.");
});
});
2 changes: 1 addition & 1 deletion packages/laravel-echo/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"strict": true,
"typeRoots": ["node_modules/@types"],
"typeRoots": ["node_modules/@types", "./typings"],
"lib": ["dom", "es2020"]
},
"include": ["./typings/**/*.ts", "./src/**/*.ts"],
Expand Down
17 changes: 13 additions & 4 deletions packages/laravel-echo/typings/window.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { io } from "socket.io-client";
import type { AxiosStatic } from "axios";
import type { JQueryStatic } from "jquery";
import type Pusher from "pusher-js";

export {};
import type { io } from "socket.io-client";

declare global {
interface Window {
Expand All @@ -10,7 +10,16 @@ declare global {
};

io?: typeof io;

Pusher?: typeof Pusher;

Vue?: any;
axios?: AxiosStatic;
jQuery?: JQueryStatic;
Turbo?: object;
}

const Vue: any | undefined;
const axios: AxiosStatic | undefined;
const jQuery: JQueryStatic | undefined;
const Turbo: object | undefined;
}
4 changes: 4 additions & 0 deletions packages/laravel-echo/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const config: UserConfig = (() => {
emptyOutDir: true,
...common,
},
test: {
globals: true,
environment: "jsdom",
},
};
})();

Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"ably",
"react"
],
"homepage": "https://github.com/laravel/echotree/2.x/packages/react",
"homepage": "https://github.com/laravel/echo/tree/2.x/packages/react",
"repository": {
"type": "git",
"url": "https://github.com/laravel/echo"
Expand Down
Loading