Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import { WebRTCChunkSource } from "@suaveplan/drive-webrtc/chunk-source/chunk-source";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/chunk-source/chunk-source bundle size", () => {
it("does not reach into signalling or low-level WebRTC", {
timeout: 5000,
}, () => {
const src = WebRTCChunkSource.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/SignalingClient/);
});
});

View File

@@ -0,0 +1,13 @@
import { WebRTCClient } from "@suaveplan/drive-webrtc/client/webrtc-client";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/client/webrtc-client bundle size", () => {
it("does not drag in signalling or discovery code", {
timeout: 5000,
}, () => {
const src = WebRTCClient.toString();
expect(src).not.toMatch(/SignalingClient/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
expect(src).not.toMatch(/WebSocket/);
});
});

View File

@@ -0,0 +1,13 @@
import { DataChannelManager } from "@suaveplan/drive-webrtc/data-channel/data-channel-manager";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/data-channel/data-channel-manager bundle size", () => {
it("does not pull signalling or discovery code", {
timeout: 5000,
}, () => {
const src = DataChannelManager.toString();
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/SignalingClient/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
});
});

View File

@@ -0,0 +1,14 @@
import { ChunkIntegrityManager } from "@suaveplan/drive-webrtc/integrity/chunk-integrity";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/integrity/chunk-integrity bundle size", () => {
it("does not reach into signalling or peer code", {
timeout: 5000,
}, () => {
const src = ChunkIntegrityManager.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/SignalingClient/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
});
});

View File

@@ -0,0 +1,14 @@
import { LRUCache } from "@suaveplan/drive-webrtc/lru-cache/lru-cache";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/lru-cache bundle size", () => {
it("does not reach into WebRTC / WebSocket primitives", {
timeout: 5000,
}, () => {
const src = LRUCache.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
expect(src).not.toMatch(/SignalingClient/);
});
});

View File

@@ -0,0 +1,13 @@
import { PeerManager } from "@suaveplan/drive-webrtc/peer-manager/peer-manager";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/peer-manager/peer-manager bundle size", () => {
it("does not reach into low-level WebRTC primitives", {
timeout: 5000,
}, () => {
const src = PeerManager.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
});
});

View File

@@ -0,0 +1,13 @@
import { WebRTCDrivePlugin } from "@suaveplan/drive-webrtc/plugin/webrtc-plugin";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/plugin/webrtc-plugin bundle size", () => {
it("loads the orchestrator class", { timeout: 5000 }, () => {
const src = WebRTCDrivePlugin.toString();
// Orchestrator is allowed to reference both signalling and
// WebRTC primitives because it wires them. Verify it does not
// pull in unrelated rate-limiter or LRU internals.
expect(src).not.toMatch(/RateLimiter/);
expect(src).not.toMatch(/class LRUCache/);
});
});

View File

@@ -0,0 +1,15 @@
import { RateLimiter } from "@suaveplan/drive-webrtc/rate-limiter/rate-limiter";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/rate-limiter/rate-limiter bundle size", () => {
it("is a leaf module — pulls no other subsystem", {
timeout: 5000,
}, () => {
const src = RateLimiter.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
expect(src).not.toMatch(/SignalingClient/);
expect(src).not.toMatch(/PeerManager/);
});
});

View File

@@ -0,0 +1,24 @@
import {
generateSecurePeerId,
generateSecureRequestId,
validatePeerSecurity,
validateSignalingUrl,
} from "@suaveplan/drive-webrtc/security/security-validator";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/security/security-validator bundle size", () => {
it("is a leaf module — pulls no other subsystem", {
timeout: 5000,
}, () => {
const combined =
generateSecurePeerId.toString() +
generateSecureRequestId.toString() +
validatePeerSecurity.toString() +
validateSignalingUrl.toString();
expect(combined).not.toMatch(/RTCPeerConnection/);
expect(combined).not.toMatch(/WebSocket/);
expect(combined).not.toMatch(/SignalingClient/);
expect(combined).not.toMatch(/PeerManager/);
expect(combined).not.toMatch(/ChunkDiscoveryManager/);
});
});

View File

@@ -0,0 +1,13 @@
import { SignalingClient } from "@suaveplan/drive-webrtc/signaling/signaling-client";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/signaling/signaling-client bundle size", () => {
it("does not pull RTCPeerConnection or discovery code", {
timeout: 5000,
}, () => {
const src = SignalingClient.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
expect(src).not.toMatch(/DataChannelManager/);
});
});

View File

@@ -0,0 +1,22 @@
import {
SubChunkReassembler,
sendSubChunks,
splitIntoSubChunks,
} from "@suaveplan/drive-webrtc/sub-chunk/sub-chunk-splitter";
import { describe, expect, it } from "@suaveplan/testing/runner";
describe("@suaveplan/drive-webrtc/sub-chunk/sub-chunk-splitter bundle size", () => {
it("does not drag in higher-level subsystems", {
timeout: 5000,
}, () => {
const src =
SubChunkReassembler.toString() +
splitIntoSubChunks.toString() +
sendSubChunks.toString();
expect(src).not.toMatch(/RTCPeerConnection/);
expect(src).not.toMatch(/WebSocket/);
expect(src).not.toMatch(/SignalingClient/);
expect(src).not.toMatch(/ChunkDiscoveryManager/);
expect(src).not.toMatch(/PeerManager/);
});
});

View File

@@ -0,0 +1,185 @@
/**
* Boundary schema tests for WebRTCPluginConfigSchema and friends.
*/
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
IceServerSchema,
P2PConfigSchema,
SignalingConfigSchema,
SubChunkConfigSchema,
WebRTCPluginConfigSchema,
} from "../src/index.js";
describe("IceServerSchema", () => {
it("accepts a single-URL form", { timeout: 5000 }, () => {
expect(
IceServerSchema.safeParse({
urls: "stun:stun.l.google.com:19302",
}).success
).toBe(true);
});
it("accepts a non-empty URL array with credentials", {
timeout: 5000,
}, () => {
expect(
IceServerSchema.safeParse({
urls: ["turn:turn.example.com:3478"],
username: "u",
credential: "p",
credentialType: "password",
}).success
).toBe(true);
});
it("rejects an empty URL array", { timeout: 5000 }, () => {
expect(IceServerSchema.safeParse({ urls: [] }).success).toBe(false);
});
it("rejects unknown credentialType", { timeout: 5000 }, () => {
expect(
IceServerSchema.safeParse({
urls: "stun:x",
credentialType: "oauth",
}).success
).toBe(false);
});
});
describe("SignalingConfigSchema", () => {
it("accepts minimal valid config", { timeout: 5000 }, () => {
expect(
SignalingConfigSchema.safeParse({
url: "wss://signal.example.com",
}).success
).toBe(true);
});
it("rejects empty url", { timeout: 5000 }, () => {
expect(SignalingConfigSchema.safeParse({ url: "" }).success).toBe(
false
);
});
it("rejects non-positive reconnectDelay", { timeout: 5000 }, () => {
expect(
SignalingConfigSchema.safeParse({
url: "wss://x",
reconnectDelay: 0,
}).success
).toBe(false);
});
});
describe("P2PConfigSchema", () => {
it("accepts empty config", { timeout: 5000 }, () => {
expect(P2PConfigSchema.safeParse({}).success).toBe(true);
});
it("accepts a populated config", { timeout: 5000 }, () => {
expect(
P2PConfigSchema.safeParse({
priority: 10,
timeout: 30_000,
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
maxConcurrentDownloads: 5,
}).success
).toBe(true);
});
it("rejects negative priority", { timeout: 5000 }, () => {
expect(P2PConfigSchema.safeParse({ priority: -1 }).success).toBe(false);
});
it("rejects zero maxConcurrentDownloads", { timeout: 5000 }, () => {
expect(
P2PConfigSchema.safeParse({ maxConcurrentDownloads: 0 }).success
).toBe(false);
});
it("rejects float timeout", { timeout: 5000 }, () => {
expect(P2PConfigSchema.safeParse({ timeout: 1.5 }).success).toBe(false);
});
});
describe("SubChunkConfigSchema", () => {
it("accepts empty config", { timeout: 5000 }, () => {
expect(SubChunkConfigSchema.safeParse({}).success).toBe(true);
});
it("accepts a populated rateLimit", { timeout: 5000 }, () => {
expect(
SubChunkConfigSchema.safeParse({
size: 16_000,
backpressure: 262_144,
rateLimit: { delayMs: 5, everyNParts: 10 },
}).success
).toBe(true);
});
it("rejects zero everyNParts", { timeout: 5000 }, () => {
expect(
SubChunkConfigSchema.safeParse({
rateLimit: { delayMs: 0, everyNParts: 0 },
}).success
).toBe(false);
});
it("rejects negative delayMs", { timeout: 5000 }, () => {
expect(
SubChunkConfigSchema.safeParse({
rateLimit: { delayMs: -1, everyNParts: 1 },
}).success
).toBe(false);
});
});
describe("WebRTCPluginConfigSchema", () => {
it("accepts minimal valid config", { timeout: 5000 }, () => {
expect(
WebRTCPluginConfigSchema.safeParse({
signaling: { url: "wss://signal.example.com" },
}).success
).toBe(true);
});
it("rejects missing signaling", { timeout: 5000 }, () => {
expect(WebRTCPluginConfigSchema.safeParse({}).success).toBe(false);
});
it("rejects invalid nested p2p config", { timeout: 5000 }, () => {
expect(
WebRTCPluginConfigSchema.safeParse({
signaling: { url: "wss://x" },
p2p: { timeout: -5 },
}).success
).toBe(false);
});
it("accepts a fully populated config", { timeout: 5000 }, () => {
expect(
WebRTCPluginConfigSchema.safeParse({
signaling: {
url: "wss://signal.example.com",
peerId: "peer-a",
peerName: "Alice",
authToken: "tok",
reconnect: true,
reconnectDelay: 1000,
},
p2p: {
priority: 5,
timeout: 30_000,
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
maxConcurrentDownloads: 5,
},
subChunks: {
size: 16_000,
backpressure: 262_144,
rateLimit: { delayMs: 5, everyNParts: 10 },
},
}).success
).toBe(true);
});
});

View File

@@ -0,0 +1,430 @@
/**
* Boundary schema tests for SignalingMessageSchema and its variants.
*
* Asserts (a) every variant parses, (b) malformed payloads are
* rejected, (c) unknown discriminators are rejected.
*/
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
AnnounceChunksMessageSchema,
AnswerMessageSchema,
ChunkBroadcastRequestSchema,
ChunkBroadcastResponseSchema,
ChunkDataMessageSchema,
ChunkDataPartMessageSchema,
ChunkQueryMessageSchema,
ChunkQueryResponseSchema,
ChunkRequestMessageSchema,
ChunksUpdatedMessageSchema,
DataChannelChunkRequestSchema,
IceCandidateMessageSchema,
OfferMessageSchema,
PeerJoinedMessageSchema,
PeerLeftMessageSchema,
RegisteredMessageSchema,
RegisterMessageSchema,
SignalingMessageSchema,
} from "../src/index.js";
const validVariants: Array<{ name: string; value: unknown }> = [
{
name: "offer",
value: {
type: "offer",
from: "a",
to: "b",
payload: { type: "offer", sdp: "v=0" },
},
},
{
name: "answer",
value: {
type: "answer",
payload: { type: "answer", sdp: "v=0" },
},
},
{
name: "ice-candidate",
value: {
type: "ice-candidate",
payload: { candidate: "candidate:1 1 UDP 1 1.1.1.1 1 typ host" },
},
},
{
name: "register",
value: {
type: "register",
payload: {
peerId: "p1",
peerName: "Alice",
authToken: "tok",
chunks: ["1:0", "1:1"],
},
},
},
{
name: "registered",
value: {
type: "registered",
payload: {
peerId: "p1",
peers: [{ id: "p2", name: "Bob", chunks: ["2:0"] }],
},
},
},
{
name: "peer-joined",
value: {
type: "peer-joined",
payload: { id: "p3", name: "Carol", chunks: [] },
},
},
{
name: "peer-left",
value: { type: "peer-left", payload: { peerId: "p3" } },
},
{
name: "announce-chunks",
value: {
type: "announce-chunks",
payload: { chunks: ["1:0", "1:1"] },
},
},
{
name: "peer-chunks-updated",
value: {
type: "peer-chunks-updated",
payload: { peerId: "p1", chunks: ["1:0"] },
},
},
{
name: "request-chunk (signaling)",
value: {
type: "request-chunk",
payload: { requestId: "r1", fileId: "1", chunkId: "2" },
},
},
{
name: "chunk-data",
value: {
type: "chunk-data",
payload: {
requestId: "r1",
fileId: "1",
chunkId: "2",
data: "AAAA",
},
},
},
{
name: "chunk-data-part",
value: {
type: "chunk-data-part",
requestId: "r1",
partIndex: 0,
totalParts: 4,
data: "AAAA",
},
},
{
name: "request-chunk (data channel)",
value: {
type: "request-chunk",
requestId: "r1",
fileId: "1",
chunkId: "2",
},
},
{
name: "chunk-query",
value: {
type: "chunk-query",
requestId: "r1",
fileId: "1",
chunkIds: ["0", "1"],
},
},
{
name: "chunk-query-response",
value: {
type: "chunk-query-response",
requestId: "r1",
fileId: "1",
availableChunkIds: ["0", "1"],
},
},
{
name: "chunk-broadcast-request",
value: {
type: "chunk-broadcast-request",
requestId: "r1",
fileId: "1",
neededChunkIds: ["0", "1"],
},
},
{
name: "chunk-broadcast-response",
value: {
type: "chunk-broadcast-response",
requestId: "r1",
fileId: "1",
peerId: "p1",
availableChunkIds: ["0", "1"],
},
},
];
describe("SignalingMessageSchema (union)", () => {
for (const { name, value } of validVariants) {
it(`accepts the ${name} variant`, { timeout: 5000 }, () => {
const r = SignalingMessageSchema.safeParse(value);
expect(r.success).toBe(true);
});
}
it("rejects unknown discriminator", { timeout: 5000 }, () => {
const r = SignalingMessageSchema.safeParse({
type: "totally-unknown",
payload: {},
});
expect(r.success).toBe(false);
});
it("rejects fileId that is not a decimal string", { timeout: 5000 }, () => {
const r = SignalingMessageSchema.safeParse({
type: "chunk-query",
requestId: "r1",
fileId: "0xff",
chunkIds: ["0"],
});
expect(r.success).toBe(false);
});
it("rejects negative partIndex on chunk-data-part", {
timeout: 5000,
}, () => {
const r = SignalingMessageSchema.safeParse({
type: "chunk-data-part",
requestId: "r1",
partIndex: -1,
totalParts: 4,
data: "AA",
});
expect(r.success).toBe(false);
});
it("rejects zero totalParts on chunk-data-part", { timeout: 5000 }, () => {
const r = SignalingMessageSchema.safeParse({
type: "chunk-data-part",
requestId: "r1",
partIndex: 0,
totalParts: 0,
data: "AA",
});
expect(r.success).toBe(false);
});
it("rejects empty requestId", { timeout: 5000 }, () => {
const r = SignalingMessageSchema.safeParse({
type: "request-chunk",
requestId: "",
fileId: "1",
chunkId: "0",
});
expect(r.success).toBe(false);
});
});
describe("per-variant schemas", () => {
it("OfferMessageSchema rejects an answer", { timeout: 5000 }, () => {
expect(
OfferMessageSchema.safeParse({
type: "answer",
payload: { type: "answer" },
}).success
).toBe(false);
});
it("AnswerMessageSchema rejects missing payload", { timeout: 5000 }, () => {
expect(AnswerMessageSchema.safeParse({ type: "answer" }).success).toBe(
false
);
});
it("IceCandidateMessageSchema accepts minimum payload", {
timeout: 5000,
}, () => {
expect(
IceCandidateMessageSchema.safeParse({
type: "ice-candidate",
payload: {},
}).success
).toBe(true);
});
it("RegisterMessageSchema requires peerId", { timeout: 5000 }, () => {
expect(
RegisterMessageSchema.safeParse({
type: "register",
payload: { peerName: "n", chunks: [] },
}).success
).toBe(false);
});
it("RegisteredMessageSchema requires peers array", {
timeout: 5000,
}, () => {
expect(
RegisteredMessageSchema.safeParse({
type: "registered",
payload: { peerId: "p1" },
}).success
).toBe(false);
});
it("PeerJoinedMessageSchema requires id", { timeout: 5000 }, () => {
expect(
PeerJoinedMessageSchema.safeParse({
type: "peer-joined",
payload: { name: "n", chunks: [] },
}).success
).toBe(false);
});
it("PeerLeftMessageSchema rejects missing peerId", {
timeout: 5000,
}, () => {
expect(
PeerLeftMessageSchema.safeParse({
type: "peer-left",
payload: {},
}).success
).toBe(false);
});
it("AnnounceChunksMessageSchema accepts empty chunks array", {
timeout: 5000,
}, () => {
expect(
AnnounceChunksMessageSchema.safeParse({
type: "announce-chunks",
payload: { chunks: [] },
}).success
).toBe(true);
});
it("ChunksUpdatedMessageSchema rejects empty peerId", {
timeout: 5000,
}, () => {
expect(
ChunksUpdatedMessageSchema.safeParse({
type: "peer-chunks-updated",
payload: { peerId: "", chunks: [] },
}).success
).toBe(false);
});
it("ChunkRequestMessageSchema rejects empty data base64", {
timeout: 5000,
}, () => {
expect(
ChunkDataMessageSchema.safeParse({
type: "chunk-data",
payload: {
requestId: "r",
fileId: "1",
chunkId: "0",
data: "",
},
}).success
).toBe(false);
});
it("ChunkRequestMessageSchema requires nested payload", {
timeout: 5000,
}, () => {
expect(
ChunkRequestMessageSchema.safeParse({
type: "request-chunk",
requestId: "r",
fileId: "1",
chunkId: "0",
}).success
).toBe(false);
});
it("DataChannelChunkRequestSchema requires flat fields", {
timeout: 5000,
}, () => {
expect(
DataChannelChunkRequestSchema.safeParse({
type: "request-chunk",
payload: { requestId: "r", fileId: "1", chunkId: "0" },
}).success
).toBe(false);
});
it("ChunkDataPartMessageSchema rejects float partIndex", {
timeout: 5000,
}, () => {
expect(
ChunkDataPartMessageSchema.safeParse({
type: "chunk-data-part",
requestId: "r",
partIndex: 0.5,
totalParts: 4,
data: "x",
}).success
).toBe(false);
});
it("ChunkQueryMessageSchema accepts missing chunkIds", {
timeout: 5000,
}, () => {
expect(
ChunkQueryMessageSchema.safeParse({
type: "chunk-query",
requestId: "r",
fileId: "1",
}).success
).toBe(true);
});
it("ChunkQueryResponseSchema requires availableChunkIds", {
timeout: 5000,
}, () => {
expect(
ChunkQueryResponseSchema.safeParse({
type: "chunk-query-response",
requestId: "r",
fileId: "1",
}).success
).toBe(false);
});
it("ChunkBroadcastRequestSchema requires neededChunkIds", {
timeout: 5000,
}, () => {
expect(
ChunkBroadcastRequestSchema.safeParse({
type: "chunk-broadcast-request",
requestId: "r",
fileId: "1",
}).success
).toBe(false);
});
it("ChunkBroadcastResponseSchema requires peerId", {
timeout: 5000,
}, () => {
expect(
ChunkBroadcastResponseSchema.safeParse({
type: "chunk-broadcast-response",
requestId: "r",
fileId: "1",
availableChunkIds: [],
}).success
).toBe(false);
});
});