feat: 实现 Go 与 JS/TS SDK 连接收发与其余接口
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import {
|
||||
APIError,
|
||||
AuthReason,
|
||||
Transport,
|
||||
TransportConfig,
|
||||
buildCleanConnectFlags,
|
||||
marshalJSON,
|
||||
} from "./types.js";
|
||||
|
||||
export interface FakeConnect {
|
||||
cleanStart: boolean;
|
||||
sessionExpiry: number;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/** 单测用假 MQTT。 */
|
||||
export class FakeTransport implements Transport {
|
||||
private cfg?: TransportConfig;
|
||||
private cred = "";
|
||||
private up: string[] = [];
|
||||
private connects: FakeConnect[] = [];
|
||||
autoHello = true;
|
||||
helloToken = "nst_test_token";
|
||||
helloServerTimeMs = 1_750_000_000_000;
|
||||
maxBodyBytes = 262144;
|
||||
maxMetaBytes = 4096;
|
||||
maxFrameBytes = 786432;
|
||||
|
||||
setCredential(passwordOrToken: string): void {
|
||||
this.cred = passwordOrToken;
|
||||
}
|
||||
|
||||
async start(cfg: TransportConfig): Promise<void> {
|
||||
this.cfg = cfg;
|
||||
await this.simulateConnectOK();
|
||||
}
|
||||
|
||||
async publishUp(payload: Uint8Array | string): Promise<void> {
|
||||
const s = typeof payload === "string" ? payload : new TextDecoder().decode(payload);
|
||||
this.up.push(s);
|
||||
if (this.autoHello) {
|
||||
try {
|
||||
const head = JSON.parse(s) as { type?: string; rid?: string };
|
||||
if (head.type === "hello" && head.rid) this.replyHello(head.rid);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this.cfg?.onOffline();
|
||||
}
|
||||
|
||||
private replyHello(rid: string): void {
|
||||
const resp = marshalJSON({
|
||||
v: 1,
|
||||
type: "resp",
|
||||
rid,
|
||||
ok: true,
|
||||
data: {
|
||||
server_time_ms: this.helloServerTimeMs,
|
||||
server_version: "0.1.0",
|
||||
max_body_bytes: this.maxBodyBytes,
|
||||
max_meta_bytes: this.maxMetaBytes,
|
||||
max_frame_bytes: this.maxFrameBytes,
|
||||
max_ttl_seconds: 2592000,
|
||||
max_schedule_seconds: 31536000,
|
||||
ack_timeout_seconds: 300,
|
||||
session_token: this.helloToken,
|
||||
},
|
||||
});
|
||||
this.injectDown(resp);
|
||||
}
|
||||
|
||||
async simulateConnectOK(): Promise<void> {
|
||||
const { cleanStart, sessionExpiry } = buildCleanConnectFlags();
|
||||
this.connects.push({ cleanStart, sessionExpiry, password: this.cred });
|
||||
this.cfg?.onConnectPacket?.(cleanStart, sessionExpiry);
|
||||
this.cfg?.backoff.markOnline();
|
||||
await this.cfg?.mqttReady();
|
||||
}
|
||||
|
||||
async simulateReconnect(): Promise<void> {
|
||||
this.cfg?.backoff.markOffline();
|
||||
this.cfg?.onOffline();
|
||||
await this.simulateConnectOK();
|
||||
}
|
||||
|
||||
simulateAuthFail(reason: AuthReason): void {
|
||||
this.cfg?.onAuthFailed(reason);
|
||||
}
|
||||
|
||||
simulateKick(): void {
|
||||
this.cfg?.onKicked();
|
||||
}
|
||||
|
||||
injectDown(payload: string | Uint8Array): void {
|
||||
const bytes = typeof payload === "string" ? new TextEncoder().encode(payload) : payload;
|
||||
this.cfg?.onDown(bytes);
|
||||
}
|
||||
|
||||
replyOK(rid: string, data: unknown = {}): void {
|
||||
this.injectDown(marshalJSON({ v: 1, type: "resp", rid, ok: true, data }));
|
||||
}
|
||||
|
||||
replyErr(rid: string, code: string, message: string): void {
|
||||
this.injectDown(
|
||||
marshalJSON({ v: 1, type: "resp", rid, ok: false, error: { code, message } }),
|
||||
);
|
||||
}
|
||||
|
||||
upFrames(): string[] {
|
||||
return [...this.up];
|
||||
}
|
||||
|
||||
getConnects(): FakeConnect[] {
|
||||
return [...this.connects];
|
||||
}
|
||||
|
||||
findUp(type: string): Array<Record<string, unknown>> {
|
||||
const out: Array<Record<string, unknown>> = [];
|
||||
for (const s of this.up) {
|
||||
try {
|
||||
const m = JSON.parse(s) as Record<string, unknown>;
|
||||
if (m.type === type) out.push(m);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
export function assertNever(_x: never): void {
|
||||
throw new APIError("bad_request", "unreachable");
|
||||
}
|
||||
Reference in New Issue
Block a user