@squord/sdk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +544 -2
- package/dist/api-DbHoBFJY.d.cts +726 -0
- package/dist/api-DbHoBFJY.d.ts +726 -0
- package/dist/index.cjs +3881 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2340 -0
- package/dist/index.d.ts +2340 -0
- package/dist/index.js +3779 -0
- package/dist/index.js.map +1 -0
- package/dist/testing/index.cjs +789 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +261 -0
- package/dist/testing/index.d.ts +261 -0
- package/dist/testing/index.js +763 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +70 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/testing/index.ts","../../src/testing/MockRest.ts","../../src/testing/MockGateway.ts","../../src/testing/fixtures.ts"],"sourcesContent":["/**\n * @squord/sdk/testing — ferramentas para testar bots sem uma comunidade real.\n *\n * - `createMockRest()`: servidor REST em memória (passe `fetchImpl` ao cliente).\n * - `createMockGateway()`: gateway simulado que fala o protocolo real\n * (passe `wsFactory` ao cliente).\n * - `createMockEnvironment()`: REST + gateway já conectados, com a rota de\n * login respondendo — espalhe `...env.options` no `SquordClient` e pronto.\n * - `fixtures`: payloads de exemplo no formato da API.\n */\n\nexport { MockRest, createMockRest } from \"./MockRest\";\nexport type { MockRestCall, MockRouteHandler, MockRouteMatch } from \"./MockRest\";\nexport { MockGatewayServer, createMockGateway } from \"./MockGateway\";\nexport type { MockGatewayOptions } from \"./MockGateway\";\nexport * as fixtures from \"./fixtures\";\n\nimport { createMockRest } from \"./MockRest\";\nimport type { MockRest } from \"./MockRest\";\nimport { createMockGateway } from \"./MockGateway\";\nimport type { MockGatewayServer } from \"./MockGateway\";\nimport * as fixtures from \"./fixtures\";\n\n/** Opções aceitas por `createMockEnvironment`. */\nexport interface MockEnvironmentOptions {\n /** Token que o mock aceita no identify. Padrão: aceita qualquer. */\n token?: string;\n /** Intervalo de heartbeat anunciado. Padrão: 200 (testes rápidos). */\n heartbeatIntervalMs?: number;\n /** Backoff de reconexão curto para testes. Padrão: 20. */\n reconnectBaseMs?: number;\n}\n\nexport interface MockEnvironment {\n /** Opções prontas para espalhar no `SquordClient`. */\n options: {\n apiBaseURL: string;\n fetchImpl: typeof fetch;\n ws: (url: string) => unknown;\n gatewayReconnectBaseMs: number;\n };\n /** O gateway simulado: use `emitEvent` para simular eventos do Squord. */\n gateway: MockGatewayServer;\n /** O REST em memória: registre rotas e inspecione `callLog`. */\n rest: MockRest;\n}\n\n/**\n * Monta o ambiente completo de teste: `createMockRest` com a rota de login\n * (`GET /bots/@me`) já respondendo com um bot de exemplo, e `createMockGateway`\n * falando o protocolo real.\n *\n * ```js\n * import { SquordClient } from \"@squord/sdk\";\n * import { createMockEnvironment, fixtures } from \"@squord/sdk/testing\";\n *\n * const env = createMockEnvironment();\n * const client = new SquordClient({ token: \"sqb_1.demo\", ...env.options });\n * client.on(\"message.created\", (m) => { /* ... *\\/ });\n * await client.login();\n * env.gateway.emitEvent(\"message.created\", { message: fixtures.message() });\n * ```\n */\nexport function createMockEnvironment(\n options: MockEnvironmentOptions = {},\n): MockEnvironment {\n const rest = createMockRest();\n\n // Rota de login (usada pelo SquordClient.login()).\n rest.get(\"/bots/@me\", () => ({ status: 200, body: fixtures.bot() }));\n\n // Envio de mensagens: ecoa o corpo como uma Message real.\n rest.post(\"/channels/:channelId/messages\", (match) => {\n const body = (match.body ?? {}) as {\n content?: string;\n replyToId?: string;\n nonce?: string;\n };\n return {\n status: 201,\n body: fixtures.message({\n channelId: match.params.channelId,\n content: body.content ?? \"\",\n replyToId: body.replyToId ?? null,\n nonce: body.nonce ?? null,\n author: fixtures.botUser(),\n }),\n };\n });\n\n // Sincronização de comandos (CommandRegistry.sync): lista vazia por padrão.\n rest.put(\"/bots/@me/commands\", () => ({ status: 200, body: [] }));\n rest.put(\"/bots/@me/guilds/:guildId/commands\", () => ({ status: 200, body: [] }));\n\n const gateway = createMockGateway({\n heartbeatIntervalMs: options.heartbeatIntervalMs ?? 200,\n token: options.token,\n });\n\n return {\n options: {\n apiBaseURL: \"https://mock.test\",\n fetchImpl: rest.fetch,\n ws: gateway.wsFactory,\n gatewayReconnectBaseMs: options.reconnectBaseMs ?? 20,\n },\n gateway,\n rest,\n };\n}\n","/**\n * MockRest: um servidor REST em memória para testar bots sem rede.\n *\n * Implementa `fetch` (passado ao cliente em `fetchImpl`) e responde às\n * rotas registradas com padrões tipo `GET /channels/:channelId/messages`.\n * Rotas não registradas respondem `404 NOT_FOUND` com o envelope oficial,\n * e as validações mínimas do protocolo (token presente, JSON válido) são\n * aplicadas como a API real faria.\n */\n\nexport interface MockRestCall {\n method: string;\n path: string;\n params: Record<string, string>;\n query: URLSearchParams;\n body: unknown;\n headers: Record<string, string>;\n requestId: string | null;\n}\n\nexport interface MockRouteMatch {\n params: Record<string, string>;\n query: URLSearchParams;\n body: unknown;\n call: MockRestCall;\n}\n\nexport interface MockRouteHandler {\n (match: MockRouteMatch): { status: number; body?: unknown; headers?: Record<string, string> } | Promise<unknown>;\n}\n\ninterface Route {\n method: string;\n pattern: string;\n segments: string[];\n handler: MockRouteHandler;\n}\n\nconst API_ERROR_HEADERS = { \"x-request-id\": \"mock-request-id\" };\n\nexport class MockRest {\n private routes: Route[] = [];\n private readonly calls: MockRestCall[] = [];\n /** Quando definido, todo request recebe esta resposta (testes de falha). */\n private failingHandler: ((call: MockRestCall) => Promise<Response> | Response) | null = null;\n /** Token esperado no header Authorization (sem o prefixo `Bot `). */\n expectedToken: string | null = null;\n\n /** Registra uma rota. `handler` devolve `{ status, body }` ou o corpo puro (status 200). */\n on(method: string, pattern: string, handler: MockRouteHandler): this {\n this.routes.push({\n method: method.toUpperCase(),\n pattern,\n segments: pattern.split(\"/\").filter(Boolean),\n handler,\n });\n return this;\n }\n\n get(pattern: string, handler: MockRouteHandler): this {\n return this.on(\"GET\", pattern, handler);\n }\n post(pattern: string, handler: MockRouteHandler): this {\n return this.on(\"POST\", pattern, handler);\n }\n put(pattern: string, handler: MockRouteHandler): this {\n return this.on(\"PUT\", pattern, handler);\n }\n patch(pattern: string, handler: MockRouteHandler): this {\n return this.on(\"PATCH\", pattern, handler);\n }\n delete(pattern: string, handler: MockRouteHandler): this {\n return this.on(\"DELETE\", pattern, handler);\n }\n\n /** Força falha em todas as requisições (ex.: simular queda de rede). */\n failWith(handler: (call: MockRestCall) => Promise<Response> | Response): void {\n this.failingHandler = handler;\n }\n\n /** Volta ao comportamento normal. */\n clearFailure(): void {\n this.failingHandler = null;\n }\n\n /** Histórico de chamadas recebidas. */\n get callLog(): readonly MockRestCall[] {\n return this.calls;\n }\n\n /** Última chamada registrada. */\n get lastCall(): MockRestCall | undefined {\n return this.calls[this.calls.length - 1];\n }\n\n /** Remove rotas e histórico. */\n reset(): void {\n this.routes = [];\n this.calls.length = 0;\n this.failingHandler = null;\n }\n\n /** A implementação de `fetch` para passar em `new SquordClient({ fetchImpl })`. */\n readonly fetch = async (input: string | URL | Request, init?: RequestInit): Promise<Response> => {\n const request = input instanceof Request ? input : new Request(input as string | URL, init);\n const url = new URL(request.url);\n const method = request.method.toUpperCase();\n\n let body: unknown = undefined;\n const rawBody = init?.body ?? (input instanceof Request ? undefined : undefined);\n if (rawBody !== undefined && rawBody !== null) {\n if (typeof rawBody === \"string\") {\n body = rawBody ? JSON.parse(rawBody) : undefined;\n } else if (rawBody instanceof ArrayBuffer || ArrayBuffer.isView(rawBody)) {\n body = rawBody;\n } else {\n body = rawBody;\n }\n } else if (input instanceof Request) {\n const clone = input.clone();\n const text = await clone.text().catch(() => \"\");\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n }\n\n const headers: Record<string, string> = {};\n for (const [key, value] of request.headers) headers[key] = value;\n\n const call: MockRestCall = {\n method,\n path: url.pathname,\n params: {},\n query: url.searchParams,\n body,\n headers,\n requestId: headers[\"x-request-id\"] ?? null,\n };\n this.calls.push(call);\n\n if (this.failingHandler) {\n return this.failingHandler(call);\n }\n\n if (this.expectedToken) {\n const auth = headers.authorization ?? \"\";\n if (auth !== `Bot ${this.expectedToken}`) {\n return jsonResponse(401, {\n statusCode: 401,\n code: \"INVALID_TOKEN\",\n message: \"Invalid token\",\n });\n }\n }\n\n const pathSegments = url.pathname.split(\"/\").filter(Boolean);\n for (const route of this.routes) {\n if (route.method !== method) continue;\n const match = matchSegments(route.segments, pathSegments);\n if (!match) continue;\n\n const matchInfo: MockRouteMatch = {\n params: match,\n query: url.searchParams,\n body,\n call: { ...call, params: match },\n };\n const result = await route.handler(matchInfo);\n const response =\n result && typeof result === \"object\" && \"status\" in result\n ? (result as { status: number; body?: unknown; headers?: Record<string, string> })\n : { status: 200, body: result };\n return jsonResponse(response.status, response.body, response.headers);\n }\n\n return jsonResponse(404, {\n statusCode: 404,\n code: \"NOT_FOUND\",\n message: `Rota não mockada: ${method} ${url.pathname}`,\n });\n };\n}\n\nfunction matchSegments(pattern: string[], path: string[]): Record<string, string> | null {\n if (pattern.length !== path.length) return null;\n const params: Record<string, string> = {};\n for (let i = 0; i < pattern.length; i++) {\n const p = pattern[i]!;\nconst s = path[i]!;\n if (p.startsWith(\":\")) {\n params[p.slice(1)] = decodeURIComponent(s);\n } else if (p !== s) {\n return null;\n }\n }\n return params;\n}\n\nfunction jsonResponse(status: number, body: unknown, headers?: Record<string, string>): Response {\n const payload = body === undefined || body === null ? undefined : JSON.stringify(body);\n return new Response(payload, {\n status,\n headers: {\n ...(payload !== undefined ? { \"Content-Type\": \"application/json\" } : {}),\n ...API_ERROR_HEADERS,\n ...headers,\n },\n });\n}\n\n/** Cria um `MockRest` já com as rotas mínimas que o `login()` usa. */\nexport function createMockRest(options: { token?: string } = {}): MockRest {\n const rest = new MockRest();\n if (options.token) rest.expectedToken = options.token;\n return rest;\n}\n","/**\n * MockGateway: um gateway do Squord simulado em memória.\n *\n * Fala o protocolo real — `hello`, `identify`, `ready`, `heartbeat`,\n * `heartbeat.ack`, `resume`, `resumed`, `invalid_session`, `reconnect` —\n * para testar o ciclo de vida do cliente (login, reconexão, resume,\n * deduplicação) sem rede. Passe `wsFactory` em `new SquordClient({ ws })`.\n *\n * Os eventos emitidos são guardados num buffer global com sequência `s`\n * crescente, como o histórico do gateway real (até 500 eventos), e o\n * `resume` reenvia tudo que veio depois do `lastSequence` informado.\n *\n * ```ts\n * const gateway = createMockGateway();\n * const client = new SquordClient({ token: \"sqb_1.segredo\", ws: gateway.wsFactory });\n * await client.login();\n * gateway.emitEvent(\"message.created\", { message: fixtures.message() });\n * ```\n */\n\nexport interface MockGatewayOptions {\n /** Intervalo de heartbeat anunciado no hello. Padrão: 30000. */\n heartbeatIntervalMs?: number;\n /** Token aceito no identify. Aceita qualquer token por padrão. */\n token?: string;\n /** Payload do ready (userId e guilds). */\n ready?: { userId: string; guilds?: Array<{ id: string; name: string; iconUrl: string | null }> };\n /** `true` para recusar o próximo resume (treinar o fluxo `invalid_session`). */\n refuseResumeOnce?: boolean;\n /** `true` para nunca responder heartbeat.ack (treinar detecção de zumbi). */\n suppressHeartbeatAck?: boolean;\n}\n\ninterface StoredEvent {\n type: string;\n d: unknown;\n s: number;\n}\n\n/** WebSocket simulado (lado cliente). */\nclass MockWebSocket {\n static OPEN = 1;\n static CLOSING = 2;\n static CLOSED = 3;\n\n readyState = 0; // CONNECTING\n private listeners = new Map<string, Array<(event: Record<string, unknown>) => void>>();\n\n constructor(readonly server: MockGatewayServer) {\n queueMicrotask(() => {\n this.readyState = MockWebSocket.OPEN;\n this.dispatch(\"open\", {});\n this.server.handleClientOpen(this);\n });\n }\n\n addEventListener(type: string, listener: (event: never) => void): void {\n const list = this.listeners.get(type) ?? [];\n list.push(listener as (event: Record<string, unknown>) => void);\n this.listeners.set(type, list);\n }\n\n removeEventListener(type: string, listener: (event: never) => void): void {\n const list = this.listeners.get(type) ?? [];\n const index = list.indexOf(listener as (event: Record<string, unknown>) => void);\n if (index >= 0) list.splice(index, 1);\n }\n\n dispatch(type: string, event: Record<string, unknown>): void {\n for (const listener of [...(this.listeners.get(type) ?? [])]) {\n listener(event);\n }\n }\n\n /** Frame do cliente: entrega ao servidor. */\n send(data: string): void {\n if (this.readyState !== MockWebSocket.OPEN) return;\n if (Buffer.byteLength(data, \"utf8\") > 65_536) {\n this.serverClose(1009, \"frame too large\");\n return;\n }\n let frame: Record<string, unknown>;\n try {\n frame = JSON.parse(data) as Record<string, unknown>;\n } catch {\n this.serverClose(4002, \"decode error\");\n return;\n }\n this.server.handleClientFrame(this, frame);\n }\n\n close(code = 1000, reason = \"\"): void {\n if (this.readyState === MockWebSocket.CLOSED) return;\n this.readyState = MockWebSocket.CLOSED;\n this.server.handleClientClose(this, code, reason);\n this.dispatch(\"close\", { code, reason, wasClean: true });\n }\n\n /** Servidor fecha a conexão. */\n serverClose(code: number, reason: string): void {\n if (this.readyState === MockWebSocket.CLOSED) return;\n this.readyState = MockWebSocket.CLOSED;\n this.server.handleClientClose(this, code, reason, true);\n this.dispatch(\"close\", { code, reason, wasClean: true });\n }\n\n /** Servidor envia frame. */\n receive(frame: Record<string, unknown>): void {\n this.dispatch(\"message\", { data: JSON.stringify(frame) });\n }\n}\n\ninterface ClientSession {\n authenticated: boolean;\n sessionId: string;\n}\n\ninterface SocketState {\n session?: ClientSession;\n}\n\nexport class MockGatewayServer {\n readonly options: MockGatewayOptions;\n private sockets = new Set<MockWebSocket>();\n private eventBuffer: StoredEvent[] = [];\n private globalSequence = 0;\n private refuseResumePending: boolean;\n private knownSessionIds = new Set<string>();\n\n constructor(options: MockGatewayOptions = {}) {\n this.options = options;\n this.refuseResumePending = options.refuseResumeOnce ?? false;\n }\n\n /** Fábrica de WebSocket para passar ao cliente. */\n readonly wsFactory = (url: string): MockWebSocket => {\n const pathname = (() => {\n try {\n return new URL(url.replace(/^wss/, \"https\")).pathname;\n } catch {\n return url;\n }\n })();\n if (!/\\/gateway$/.test(pathname)) {\n throw new Error(`MockGateway: caminho inválido ${url} (use wss://.../gateway)`);\n }\n return new MockWebSocket(this);\n };\n\n /** Conexões abertas no momento. */\n get connectionCount(): number {\n return this.sockets.size;\n }\n\n /** Última sequência emitida. */\n get lastSequence(): number {\n return this.eventBuffer.length > 0 ? this.eventBuffer[this.eventBuffer.length - 1]!.s : 0;\n }\n\n /** Total de eventos já emitidos. */\n get totalEvents(): number {\n return this.globalSequence;\n }\n\n /**\n * Emite um evento durável: guarda no buffer (sequência crescente) e\n * entrega às conexões autenticadas.\n */\n emitEvent(type: string, d: unknown): void {\n const s = ++this.globalSequence;\n this.eventBuffer.push({ type, d, s });\n if (this.eventBuffer.length > 500) this.eventBuffer.shift();\n for (const socket of this.sockets) {\n const state = socket as unknown as SocketState;\n if (state.session?.authenticated) {\n socket.receive({ op: \"event\", type, d, s, timestamp: Date.now() });\n }\n }\n }\n\n /** Envia um frame cru às conexões autenticadas (sem `s`). */\n sendFrame(frame: Record<string, unknown>): void {\n for (const socket of this.sockets) {\n const state = socket as unknown as SocketState;\n if (state.session?.authenticated) socket.receive({ ...frame, timestamp: Date.now() });\n }\n }\n\n /**\n * Envia um evento com sequência arbitrária (para treinar a deduplicação\n * do cliente: `s` repetido ou antigo deve ser descartado).\n */\n sendEventWithSequence(type: string, d: unknown, s: number): void {\n for (const socket of this.sockets) {\n const state = socket as unknown as SocketState;\n if (state.session?.authenticated) {\n socket.receive({ op: \"event\", type, d, s, timestamp: Date.now() });\n }\n }\n }\n\n /** Fecha as conexões com um código (ex.: 4009 para treinar resume). */\n closeAll(code: number, reason: string): void {\n for (const socket of [...this.sockets]) {\n socket.serverClose(code, reason);\n }\n }\n\n /** Pede reconexão (frame `reconnect` + fechamento 4007, como o real). */\n requestReconnect(reason = \"gateway shutting down\"): void {\n for (const socket of [...this.sockets]) {\n socket.receive({\n op: \"reconnect\",\n d: { reason, resumable: true },\n timestamp: Date.now(),\n });\n }\n this.closeAll(4007, reason);\n }\n\n /** Descarta o histórico de eventos (o próximo resume falha com `invalid_session`). */\n expireHistory(): void {\n this.eventBuffer = [];\n }\n\n /** Reinicia o estado do mock. */\n reset(): void {\n this.sockets.clear();\n this.eventBuffer = [];\n this.globalSequence = 0;\n this.knownSessionIds.clear();\n this.refuseResumePending = this.options.refuseResumeOnce ?? false;\n }\n\n // ------------------------------------------------------------------\n // \"Servidor\": handlers chamados pelo MockWebSocket\n // ------------------------------------------------------------------\n\n handleClientOpen(socket: MockWebSocket): void {\n this.sockets.add(socket);\n socket.receive({\n op: \"hello\",\n d: {\n heartbeatIntervalMs: this.options.heartbeatIntervalMs ?? 30_000,\n sessionId: `mock-${Math.random().toString(36).slice(2, 12)}`,\n protocolVersion: 1,\n },\n timestamp: Date.now(),\n });\n }\n\n handleClientFrame(socket: MockWebSocket, frame: Record<string, unknown>): void {\n const op = frame.op as string;\n const d = (frame.d ?? {}) as Record<string, unknown>;\n const state = socket as unknown as SocketState;\n\n switch (op) {\n case \"identify\": {\n if (state.session?.authenticated) {\n socket.serverClose(4005, \"already authenticated\");\n return;\n }\n if (this.options.token && d.token !== this.options.token) {\n socket.serverClose(4004, \"invalid token\");\n return;\n }\n const sessionId = `mock-${Math.random().toString(36).slice(2, 12)}`;\n this.knownSessionIds.add(sessionId);\n state.session = { authenticated: true, sessionId };\n socket.receive({\n op: \"ready\",\n d: {\n sessionId,\n userId: this.options.ready?.userId ?? \"1300000000000000010\",\n guilds: this.options.ready?.guilds ?? [],\n resumeGatewayUrl: \"wss://gateway.squord.com.br/gateway\",\n },\n timestamp: Date.now(),\n });\n return;\n }\n case \"resume\": {\n const sessionId = d.sessionId as string;\n const lastSequence = (d.lastSequence as number) ?? 0;\n if (this.refuseResumePending) {\n this.refuseResumePending = false;\n socket.receive({\n op: \"invalid_session\",\n d: { resumable: false },\n timestamp: Date.now(),\n });\n return;\n }\n if (!this.knownSessionIds.has(sessionId)) {\n socket.receive({\n op: \"invalid_session\",\n d: { resumable: false },\n timestamp: Date.now(),\n });\n return;\n }\n state.session = { authenticated: true, sessionId };\n const replay = this.eventBuffer.filter((event) => event.s > lastSequence);\n for (const event of replay) {\n socket.receive({\n op: \"event\",\n type: event.type,\n d: event.d,\n s: event.s,\n timestamp: Date.now(),\n });\n }\n const sequence = replay.length > 0 ? replay[replay.length - 1]!.s : lastSequence;\n socket.receive({\n op: \"resumed\",\n d: { sessionId, replayed: replay.length, sequence },\n timestamp: Date.now(),\n });\n return;\n }\n case \"heartbeat\": {\n if (!state.session?.authenticated) {\n socket.serverClose(4003, \"not authenticated\");\n return;\n }\n if (this.options.suppressHeartbeatAck) return;\n socket.receive({\n op: \"heartbeat.ack\",\n d: { sequence: this.lastSequence },\n timestamp: Date.now(),\n });\n return;\n }\n case \"presence.update\":\n case \"subscribe\":\n case \"unsubscribe\":\n case \"typing.start\":\n case \"voice.state.update\":\n return; // aceitos e ignorados, como o real\n default:\n socket.serverClose(4001, \"unknown opcode\");\n }\n }\n\n handleClientClose(socket: MockWebSocket, code: number, reason: string, byServer = false): void {\n this.sockets.delete(socket);\n (socket as unknown as SocketState).session = undefined;\n void code;\n void reason;\n void byServer;\n }\n}\n\n/** Cria o mock do gateway. Use `ws: gateway.wsFactory` no `SquordClient`. */\nexport function createMockGateway(options: MockGatewayOptions = {}): MockGatewayServer {\n return new MockGatewayServer(options);\n}\n","/**\n * Fixtures: payloads de exemplo no formato real da API, para testes de bots\n * e de handlers sem uma comunidade de verdade.\n */\n\nimport type {\n APIChannel,\n APIGuild,\n APIInteraction,\n APIMember,\n APIMessage,\n APIRole,\n APIUser,\n APICommand,\n} from \"../types/api\";\n\n/** Um usuário (Ana, dos exemplos da documentação). */\nexport function user(overrides: Partial<APIUser> = {}): APIUser {\n return {\n id: \"1300000000000000020\",\n username: \"ana\",\n displayName: \"Ana\",\n avatarUrl: null,\n avatarAnimatedUrl: null,\n nameStyle: null,\n flags: 0,\n deleted: false,\n suspended: false,\n premium: false,\n ...overrides,\n };\n}\n\n/** A conta do bot. */\nexport function botUser(overrides: Partial<APIUser> = {}): APIUser {\n return user({\n id: \"1300000000000000010\",\n username: \"bot~meubot\",\n displayName: \"Meu Bot\",\n flags: 32, // BOT\n ...overrides,\n });\n}\n\n/** Um membro de um Space. */\nexport function member(overrides: Partial<APIMember> = {}): APIMember {\n return {\n id: \"1300000000000000011\",\n guildId: \"1300000000000000001\",\n userId: \"1300000000000000020\",\n user: user(),\n type: \"INTERNAL\",\n nickname: null,\n avatarUrl: null,\n avatarAnimatedUrl: null,\n bannerUrl: null,\n bannerAnimatedUrl: null,\n bio: null,\n bioEmojis: [],\n nameStyle: null,\n profileFont: null,\n profileTheme: null,\n roleIds: [],\n joinedAt: \"2026-10-01T10:00:00.000Z\",\n timeoutUntil: null,\n deaf: false,\n mute: false,\n pending: false,\n boostingSince: null,\n createdAt: \"2026-10-01T10:00:00.000Z\",\n updatedAt: \"2026-10-01T10:00:00.000Z\",\n ...overrides,\n };\n}\n\n/** Um canal de texto. */\nexport function channel(overrides: Partial<APIChannel> = {}): APIChannel {\n return {\n id: \"1300000000000000040\",\n guildId: \"1300000000000000001\",\n categoryId: null,\n name: \"geral\",\n type: \"TEXT\",\n position: 0,\n topic: null,\n topicUpdatedAt: null,\n topicUpdatedById: null,\n isPrivate: false,\n rateLimitPerUser: 0,\n bitrate: null,\n userLimit: null,\n chatEnabled: true,\n lastMessageId: null,\n overwrites: [],\n availableTags: [],\n requireTag: false,\n defaultAutoArchiveMinutes: null,\n createdAt: \"2026-10-01T10:00:00.000Z\",\n updatedAt: \"2026-10-01T10:00:00.000Z\",\n ...overrides,\n };\n}\n\n/** Um cargo. */\nexport function role(overrides: Partial<APIRole> = {}): APIRole {\n return {\n id: \"1300000000000000001\",\n guildId: \"1300000000000000001\",\n name: \"@everyone\",\n color: null,\n position: 0,\n permissions: \"1685839112193\",\n hoist: false,\n mentionable: false,\n managed: false,\n managedKind: null,\n botId: null,\n icon: null,\n selfAssignable: false,\n createdAt: \"2026-10-01T10:00:00.000Z\",\n updatedAt: \"2026-10-01T10:00:00.000Z\",\n ...overrides,\n };\n}\n\n/** Um Space com o bloco `self` do bot. */\nexport function guild(overrides: Partial<APIGuild> = {}): APIGuild {\n return {\n id: \"1300000000000000001\",\n ownerId: \"1300000000000000009\",\n name: \"Meu Space\",\n slug: \"meu-space\",\n description: null,\n iconUrl: null,\n iconAnimatedUrl: null,\n bannerUrl: null,\n bannerAnimatedUrl: null,\n bannerPlaceholder: null,\n defaultChannelId: \"1300000000000000040\",\n systemChannelId: null,\n visibility: \"PUBLIC\",\n verificationLevel: \"NONE\",\n accessMode: \"LINK\",\n requireVerifiedEmail: false,\n requireTwoFactor: false,\n moderationMfaRequired: false,\n joinRequestRoleIds: [],\n requireJoinMessage: false,\n joinRequestRetryDays: 0,\n memberCount: 2,\n flags: 0,\n planId: \"free\",\n vanityLapsesAt: null,\n vanityInvite: false,\n boostCount: 0,\n boostLevel: 0,\n boostMessages: false,\n discoveryCategory: null,\n locale: null,\n rules: [],\n rulesUpdatedAt: null,\n discoverable: false,\n discoverableSince: null,\n minAccountAgeDays: 0,\n createdAt: \"2026-10-01T10:00:00.000Z\",\n updatedAt: \"2026-10-01T10:00:00.000Z\",\n self: {\n memberId: \"1300000000000000012\",\n roleIds: [\"1300000000000000031\"],\n permissions: \"155649\",\n isOwner: false,\n },\n ...overrides,\n };\n}\n\n/** Uma mensagem. */\nexport function message(overrides: Partial<APIMessage> = {}): APIMessage {\n return {\n id: \"1300000000000000100\",\n guildId: \"1300000000000000001\",\n channelId: \"1300000000000000040\",\n authorId: \"1300000000000000020\",\n type: \"DEFAULT\",\n content: \"Olá!\",\n replyToId: null,\n attachments: [],\n embeds: [],\n components: [],\n interaction: null,\n mentions: { userIds: [], roleIds: [], channelIds: [], everyone: false },\n reactions: [],\n pinned: false,\n editedAt: null,\n deletedAt: null,\n moderated: false,\n nonce: null,\n call: null,\n poll: null,\n forward: null,\n relay: null,\n relayedCount: null,\n stickers: [],\n emojis: [],\n thread: null,\n automod: null,\n createdAt: \"2026-10-05T14:30:00.000Z\",\n updatedAt: \"2026-10-05T14:30:00.000Z\",\n author: user(),\n memberNickname: null,\n memberAvatarUrl: null,\n memberNameStyle: null,\n replyTo: null,\n ...overrides,\n };\n}\n\n/** Uma interação de comando (`interaction.created` com `type: \"COMMAND\"`). */\nexport function commandInteraction(overrides: Partial<APIInteraction> = {}): APIInteraction {\n return {\n id: \"1300000000000000400\",\n token: \"tk_9f2c1d7e8a4b\",\n type: \"COMMAND\",\n guildId: \"1300000000000000001\",\n channelId: \"1300000000000000040\",\n user: user(),\n member: member(),\n command: {\n id: \"1300000000000000500\",\n name: \"ping\",\n options: [],\n },\n createdAt: \"2026-10-05T14:40:00.000Z\",\n ...overrides,\n };\n}\n\n/** Uma interação de componente (`type: \"COMPONENT\"`). */\nexport function componentInteraction(overrides: Partial<APIInteraction> = {}): APIInteraction {\n return {\n id: \"1300000000000000401\",\n token: \"tk_1b3d5f7a9c2e\",\n type: \"COMPONENT\",\n guildId: \"1300000000000000001\",\n channelId: \"1300000000000000040\",\n user: user(),\n member: member(),\n component: {\n messageId: \"1300000000000000100\",\n customId: \"confirmar\",\n type: \"button\",\n values: [],\n },\n createdAt: \"2026-10-05T14:41:00.000Z\",\n ...overrides,\n };\n}\n\n/** Um comando de aplicação registrado. */\nexport function command(overrides: Partial<APICommand> = {}): APICommand {\n return {\n id: \"1300000000000000500\",\n botId: \"1300000000000000010\",\n guildId: null,\n name: \"ping\",\n description: \"Verifica a latência do bot\",\n options: [],\n updatedAt: \"2026-10-05T14:00:00.000Z\",\n ...overrides,\n };\n}\n\n/** Um bot (visão do dono, `GET /bots/@me`). */\nexport function bot(overrides: Record<string, unknown> = {}): Record<string, unknown> {\n return {\n id: \"1300000000000000010\",\n user: botUser(),\n description: \"Bot de exemplo\",\n ownerUsername: \"ana\",\n public: false,\n verified: false,\n installCount: 1,\n termsUrl: null,\n privacyUrl: null,\n createdAt: \"2026-10-01T10:00:00.000Z\",\n intents: 13,\n ...overrides,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { N as APIUser, l as APIChannel, h as APICommand, Q as APIInteraction, u as APIGuild, v as APIMember, E as APIMessage, y as APIRole } from '../api-DbHoBFJY.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MockRest: um servidor REST em memória para testar bots sem rede.
|
|
5
|
+
*
|
|
6
|
+
* Implementa `fetch` (passado ao cliente em `fetchImpl`) e responde às
|
|
7
|
+
* rotas registradas com padrões tipo `GET /channels/:channelId/messages`.
|
|
8
|
+
* Rotas não registradas respondem `404 NOT_FOUND` com o envelope oficial,
|
|
9
|
+
* e as validações mínimas do protocolo (token presente, JSON válido) são
|
|
10
|
+
* aplicadas como a API real faria.
|
|
11
|
+
*/
|
|
12
|
+
interface MockRestCall {
|
|
13
|
+
method: string;
|
|
14
|
+
path: string;
|
|
15
|
+
params: Record<string, string>;
|
|
16
|
+
query: URLSearchParams;
|
|
17
|
+
body: unknown;
|
|
18
|
+
headers: Record<string, string>;
|
|
19
|
+
requestId: string | null;
|
|
20
|
+
}
|
|
21
|
+
interface MockRouteMatch {
|
|
22
|
+
params: Record<string, string>;
|
|
23
|
+
query: URLSearchParams;
|
|
24
|
+
body: unknown;
|
|
25
|
+
call: MockRestCall;
|
|
26
|
+
}
|
|
27
|
+
interface MockRouteHandler {
|
|
28
|
+
(match: MockRouteMatch): {
|
|
29
|
+
status: number;
|
|
30
|
+
body?: unknown;
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
} | Promise<unknown>;
|
|
33
|
+
}
|
|
34
|
+
declare class MockRest {
|
|
35
|
+
private routes;
|
|
36
|
+
private readonly calls;
|
|
37
|
+
/** Quando definido, todo request recebe esta resposta (testes de falha). */
|
|
38
|
+
private failingHandler;
|
|
39
|
+
/** Token esperado no header Authorization (sem o prefixo `Bot `). */
|
|
40
|
+
expectedToken: string | null;
|
|
41
|
+
/** Registra uma rota. `handler` devolve `{ status, body }` ou o corpo puro (status 200). */
|
|
42
|
+
on(method: string, pattern: string, handler: MockRouteHandler): this;
|
|
43
|
+
get(pattern: string, handler: MockRouteHandler): this;
|
|
44
|
+
post(pattern: string, handler: MockRouteHandler): this;
|
|
45
|
+
put(pattern: string, handler: MockRouteHandler): this;
|
|
46
|
+
patch(pattern: string, handler: MockRouteHandler): this;
|
|
47
|
+
delete(pattern: string, handler: MockRouteHandler): this;
|
|
48
|
+
/** Força falha em todas as requisições (ex.: simular queda de rede). */
|
|
49
|
+
failWith(handler: (call: MockRestCall) => Promise<Response> | Response): void;
|
|
50
|
+
/** Volta ao comportamento normal. */
|
|
51
|
+
clearFailure(): void;
|
|
52
|
+
/** Histórico de chamadas recebidas. */
|
|
53
|
+
get callLog(): readonly MockRestCall[];
|
|
54
|
+
/** Última chamada registrada. */
|
|
55
|
+
get lastCall(): MockRestCall | undefined;
|
|
56
|
+
/** Remove rotas e histórico. */
|
|
57
|
+
reset(): void;
|
|
58
|
+
/** A implementação de `fetch` para passar em `new SquordClient({ fetchImpl })`. */
|
|
59
|
+
readonly fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
60
|
+
}
|
|
61
|
+
/** Cria um `MockRest` já com as rotas mínimas que o `login()` usa. */
|
|
62
|
+
declare function createMockRest(options?: {
|
|
63
|
+
token?: string;
|
|
64
|
+
}): MockRest;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* MockGateway: um gateway do Squord simulado em memória.
|
|
68
|
+
*
|
|
69
|
+
* Fala o protocolo real — `hello`, `identify`, `ready`, `heartbeat`,
|
|
70
|
+
* `heartbeat.ack`, `resume`, `resumed`, `invalid_session`, `reconnect` —
|
|
71
|
+
* para testar o ciclo de vida do cliente (login, reconexão, resume,
|
|
72
|
+
* deduplicação) sem rede. Passe `wsFactory` em `new SquordClient({ ws })`.
|
|
73
|
+
*
|
|
74
|
+
* Os eventos emitidos são guardados num buffer global com sequência `s`
|
|
75
|
+
* crescente, como o histórico do gateway real (até 500 eventos), e o
|
|
76
|
+
* `resume` reenvia tudo que veio depois do `lastSequence` informado.
|
|
77
|
+
*
|
|
78
|
+
* ```ts
|
|
79
|
+
* const gateway = createMockGateway();
|
|
80
|
+
* const client = new SquordClient({ token: "sqb_1.segredo", ws: gateway.wsFactory });
|
|
81
|
+
* await client.login();
|
|
82
|
+
* gateway.emitEvent("message.created", { message: fixtures.message() });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
interface MockGatewayOptions {
|
|
86
|
+
/** Intervalo de heartbeat anunciado no hello. Padrão: 30000. */
|
|
87
|
+
heartbeatIntervalMs?: number;
|
|
88
|
+
/** Token aceito no identify. Aceita qualquer token por padrão. */
|
|
89
|
+
token?: string;
|
|
90
|
+
/** Payload do ready (userId e guilds). */
|
|
91
|
+
ready?: {
|
|
92
|
+
userId: string;
|
|
93
|
+
guilds?: Array<{
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
iconUrl: string | null;
|
|
97
|
+
}>;
|
|
98
|
+
};
|
|
99
|
+
/** `true` para recusar o próximo resume (treinar o fluxo `invalid_session`). */
|
|
100
|
+
refuseResumeOnce?: boolean;
|
|
101
|
+
/** `true` para nunca responder heartbeat.ack (treinar detecção de zumbi). */
|
|
102
|
+
suppressHeartbeatAck?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/** WebSocket simulado (lado cliente). */
|
|
105
|
+
declare class MockWebSocket {
|
|
106
|
+
readonly server: MockGatewayServer;
|
|
107
|
+
static OPEN: number;
|
|
108
|
+
static CLOSING: number;
|
|
109
|
+
static CLOSED: number;
|
|
110
|
+
readyState: number;
|
|
111
|
+
private listeners;
|
|
112
|
+
constructor(server: MockGatewayServer);
|
|
113
|
+
addEventListener(type: string, listener: (event: never) => void): void;
|
|
114
|
+
removeEventListener(type: string, listener: (event: never) => void): void;
|
|
115
|
+
dispatch(type: string, event: Record<string, unknown>): void;
|
|
116
|
+
/** Frame do cliente: entrega ao servidor. */
|
|
117
|
+
send(data: string): void;
|
|
118
|
+
close(code?: number, reason?: string): void;
|
|
119
|
+
/** Servidor fecha a conexão. */
|
|
120
|
+
serverClose(code: number, reason: string): void;
|
|
121
|
+
/** Servidor envia frame. */
|
|
122
|
+
receive(frame: Record<string, unknown>): void;
|
|
123
|
+
}
|
|
124
|
+
declare class MockGatewayServer {
|
|
125
|
+
readonly options: MockGatewayOptions;
|
|
126
|
+
private sockets;
|
|
127
|
+
private eventBuffer;
|
|
128
|
+
private globalSequence;
|
|
129
|
+
private refuseResumePending;
|
|
130
|
+
private knownSessionIds;
|
|
131
|
+
constructor(options?: MockGatewayOptions);
|
|
132
|
+
/** Fábrica de WebSocket para passar ao cliente. */
|
|
133
|
+
readonly wsFactory: (url: string) => MockWebSocket;
|
|
134
|
+
/** Conexões abertas no momento. */
|
|
135
|
+
get connectionCount(): number;
|
|
136
|
+
/** Última sequência emitida. */
|
|
137
|
+
get lastSequence(): number;
|
|
138
|
+
/** Total de eventos já emitidos. */
|
|
139
|
+
get totalEvents(): number;
|
|
140
|
+
/**
|
|
141
|
+
* Emite um evento durável: guarda no buffer (sequência crescente) e
|
|
142
|
+
* entrega às conexões autenticadas.
|
|
143
|
+
*/
|
|
144
|
+
emitEvent(type: string, d: unknown): void;
|
|
145
|
+
/** Envia um frame cru às conexões autenticadas (sem `s`). */
|
|
146
|
+
sendFrame(frame: Record<string, unknown>): void;
|
|
147
|
+
/**
|
|
148
|
+
* Envia um evento com sequência arbitrária (para treinar a deduplicação
|
|
149
|
+
* do cliente: `s` repetido ou antigo deve ser descartado).
|
|
150
|
+
*/
|
|
151
|
+
sendEventWithSequence(type: string, d: unknown, s: number): void;
|
|
152
|
+
/** Fecha as conexões com um código (ex.: 4009 para treinar resume). */
|
|
153
|
+
closeAll(code: number, reason: string): void;
|
|
154
|
+
/** Pede reconexão (frame `reconnect` + fechamento 4007, como o real). */
|
|
155
|
+
requestReconnect(reason?: string): void;
|
|
156
|
+
/** Descarta o histórico de eventos (o próximo resume falha com `invalid_session`). */
|
|
157
|
+
expireHistory(): void;
|
|
158
|
+
/** Reinicia o estado do mock. */
|
|
159
|
+
reset(): void;
|
|
160
|
+
handleClientOpen(socket: MockWebSocket): void;
|
|
161
|
+
handleClientFrame(socket: MockWebSocket, frame: Record<string, unknown>): void;
|
|
162
|
+
handleClientClose(socket: MockWebSocket, code: number, reason: string, byServer?: boolean): void;
|
|
163
|
+
}
|
|
164
|
+
/** Cria o mock do gateway. Use `ws: gateway.wsFactory` no `SquordClient`. */
|
|
165
|
+
declare function createMockGateway(options?: MockGatewayOptions): MockGatewayServer;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Fixtures: payloads de exemplo no formato real da API, para testes de bots
|
|
169
|
+
* e de handlers sem uma comunidade de verdade.
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
/** Um usuário (Ana, dos exemplos da documentação). */
|
|
173
|
+
declare function user(overrides?: Partial<APIUser>): APIUser;
|
|
174
|
+
/** A conta do bot. */
|
|
175
|
+
declare function botUser(overrides?: Partial<APIUser>): APIUser;
|
|
176
|
+
/** Um membro de um Space. */
|
|
177
|
+
declare function member(overrides?: Partial<APIMember>): APIMember;
|
|
178
|
+
/** Um canal de texto. */
|
|
179
|
+
declare function channel(overrides?: Partial<APIChannel>): APIChannel;
|
|
180
|
+
/** Um cargo. */
|
|
181
|
+
declare function role(overrides?: Partial<APIRole>): APIRole;
|
|
182
|
+
/** Um Space com o bloco `self` do bot. */
|
|
183
|
+
declare function guild(overrides?: Partial<APIGuild>): APIGuild;
|
|
184
|
+
/** Uma mensagem. */
|
|
185
|
+
declare function message(overrides?: Partial<APIMessage>): APIMessage;
|
|
186
|
+
/** Uma interação de comando (`interaction.created` com `type: "COMMAND"`). */
|
|
187
|
+
declare function commandInteraction(overrides?: Partial<APIInteraction>): APIInteraction;
|
|
188
|
+
/** Uma interação de componente (`type: "COMPONENT"`). */
|
|
189
|
+
declare function componentInteraction(overrides?: Partial<APIInteraction>): APIInteraction;
|
|
190
|
+
/** Um comando de aplicação registrado. */
|
|
191
|
+
declare function command(overrides?: Partial<APICommand>): APICommand;
|
|
192
|
+
/** Um bot (visão do dono, `GET /bots/@me`). */
|
|
193
|
+
declare function bot(overrides?: Record<string, unknown>): Record<string, unknown>;
|
|
194
|
+
|
|
195
|
+
declare const fixtures_bot: typeof bot;
|
|
196
|
+
declare const fixtures_botUser: typeof botUser;
|
|
197
|
+
declare const fixtures_channel: typeof channel;
|
|
198
|
+
declare const fixtures_command: typeof command;
|
|
199
|
+
declare const fixtures_commandInteraction: typeof commandInteraction;
|
|
200
|
+
declare const fixtures_componentInteraction: typeof componentInteraction;
|
|
201
|
+
declare const fixtures_guild: typeof guild;
|
|
202
|
+
declare const fixtures_member: typeof member;
|
|
203
|
+
declare const fixtures_message: typeof message;
|
|
204
|
+
declare const fixtures_role: typeof role;
|
|
205
|
+
declare const fixtures_user: typeof user;
|
|
206
|
+
declare namespace fixtures {
|
|
207
|
+
export { fixtures_bot as bot, fixtures_botUser as botUser, fixtures_channel as channel, fixtures_command as command, fixtures_commandInteraction as commandInteraction, fixtures_componentInteraction as componentInteraction, fixtures_guild as guild, fixtures_member as member, fixtures_message as message, fixtures_role as role, fixtures_user as user };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @squord/sdk/testing — ferramentas para testar bots sem uma comunidade real.
|
|
212
|
+
*
|
|
213
|
+
* - `createMockRest()`: servidor REST em memória (passe `fetchImpl` ao cliente).
|
|
214
|
+
* - `createMockGateway()`: gateway simulado que fala o protocolo real
|
|
215
|
+
* (passe `wsFactory` ao cliente).
|
|
216
|
+
* - `createMockEnvironment()`: REST + gateway já conectados, com a rota de
|
|
217
|
+
* login respondendo — espalhe `...env.options` no `SquordClient` e pronto.
|
|
218
|
+
* - `fixtures`: payloads de exemplo no formato da API.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
/** Opções aceitas por `createMockEnvironment`. */
|
|
222
|
+
interface MockEnvironmentOptions {
|
|
223
|
+
/** Token que o mock aceita no identify. Padrão: aceita qualquer. */
|
|
224
|
+
token?: string;
|
|
225
|
+
/** Intervalo de heartbeat anunciado. Padrão: 200 (testes rápidos). */
|
|
226
|
+
heartbeatIntervalMs?: number;
|
|
227
|
+
/** Backoff de reconexão curto para testes. Padrão: 20. */
|
|
228
|
+
reconnectBaseMs?: number;
|
|
229
|
+
}
|
|
230
|
+
interface MockEnvironment {
|
|
231
|
+
/** Opções prontas para espalhar no `SquordClient`. */
|
|
232
|
+
options: {
|
|
233
|
+
apiBaseURL: string;
|
|
234
|
+
fetchImpl: typeof fetch;
|
|
235
|
+
ws: (url: string) => unknown;
|
|
236
|
+
gatewayReconnectBaseMs: number;
|
|
237
|
+
};
|
|
238
|
+
/** O gateway simulado: use `emitEvent` para simular eventos do Squord. */
|
|
239
|
+
gateway: MockGatewayServer;
|
|
240
|
+
/** O REST em memória: registre rotas e inspecione `callLog`. */
|
|
241
|
+
rest: MockRest;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Monta o ambiente completo de teste: `createMockRest` com a rota de login
|
|
245
|
+
* (`GET /bots/@me`) já respondendo com um bot de exemplo, e `createMockGateway`
|
|
246
|
+
* falando o protocolo real.
|
|
247
|
+
*
|
|
248
|
+
* ```js
|
|
249
|
+
* import { SquordClient } from "@squord/sdk";
|
|
250
|
+
* import { createMockEnvironment, fixtures } from "@squord/sdk/testing";
|
|
251
|
+
*
|
|
252
|
+
* const env = createMockEnvironment();
|
|
253
|
+
* const client = new SquordClient({ token: "sqb_1.demo", ...env.options });
|
|
254
|
+
* client.on("message.created", (m) => { /* ... *\/ });
|
|
255
|
+
* await client.login();
|
|
256
|
+
* env.gateway.emitEvent("message.created", { message: fixtures.message() });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare function createMockEnvironment(options?: MockEnvironmentOptions): MockEnvironment;
|
|
260
|
+
|
|
261
|
+
export { type MockEnvironment, type MockEnvironmentOptions, type MockGatewayOptions, MockGatewayServer, MockRest, type MockRestCall, type MockRouteHandler, type MockRouteMatch, createMockEnvironment, createMockGateway, createMockRest, fixtures };
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { N as APIUser, l as APIChannel, h as APICommand, Q as APIInteraction, u as APIGuild, v as APIMember, E as APIMessage, y as APIRole } from '../api-DbHoBFJY.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MockRest: um servidor REST em memória para testar bots sem rede.
|
|
5
|
+
*
|
|
6
|
+
* Implementa `fetch` (passado ao cliente em `fetchImpl`) e responde às
|
|
7
|
+
* rotas registradas com padrões tipo `GET /channels/:channelId/messages`.
|
|
8
|
+
* Rotas não registradas respondem `404 NOT_FOUND` com o envelope oficial,
|
|
9
|
+
* e as validações mínimas do protocolo (token presente, JSON válido) são
|
|
10
|
+
* aplicadas como a API real faria.
|
|
11
|
+
*/
|
|
12
|
+
interface MockRestCall {
|
|
13
|
+
method: string;
|
|
14
|
+
path: string;
|
|
15
|
+
params: Record<string, string>;
|
|
16
|
+
query: URLSearchParams;
|
|
17
|
+
body: unknown;
|
|
18
|
+
headers: Record<string, string>;
|
|
19
|
+
requestId: string | null;
|
|
20
|
+
}
|
|
21
|
+
interface MockRouteMatch {
|
|
22
|
+
params: Record<string, string>;
|
|
23
|
+
query: URLSearchParams;
|
|
24
|
+
body: unknown;
|
|
25
|
+
call: MockRestCall;
|
|
26
|
+
}
|
|
27
|
+
interface MockRouteHandler {
|
|
28
|
+
(match: MockRouteMatch): {
|
|
29
|
+
status: number;
|
|
30
|
+
body?: unknown;
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
} | Promise<unknown>;
|
|
33
|
+
}
|
|
34
|
+
declare class MockRest {
|
|
35
|
+
private routes;
|
|
36
|
+
private readonly calls;
|
|
37
|
+
/** Quando definido, todo request recebe esta resposta (testes de falha). */
|
|
38
|
+
private failingHandler;
|
|
39
|
+
/** Token esperado no header Authorization (sem o prefixo `Bot `). */
|
|
40
|
+
expectedToken: string | null;
|
|
41
|
+
/** Registra uma rota. `handler` devolve `{ status, body }` ou o corpo puro (status 200). */
|
|
42
|
+
on(method: string, pattern: string, handler: MockRouteHandler): this;
|
|
43
|
+
get(pattern: string, handler: MockRouteHandler): this;
|
|
44
|
+
post(pattern: string, handler: MockRouteHandler): this;
|
|
45
|
+
put(pattern: string, handler: MockRouteHandler): this;
|
|
46
|
+
patch(pattern: string, handler: MockRouteHandler): this;
|
|
47
|
+
delete(pattern: string, handler: MockRouteHandler): this;
|
|
48
|
+
/** Força falha em todas as requisições (ex.: simular queda de rede). */
|
|
49
|
+
failWith(handler: (call: MockRestCall) => Promise<Response> | Response): void;
|
|
50
|
+
/** Volta ao comportamento normal. */
|
|
51
|
+
clearFailure(): void;
|
|
52
|
+
/** Histórico de chamadas recebidas. */
|
|
53
|
+
get callLog(): readonly MockRestCall[];
|
|
54
|
+
/** Última chamada registrada. */
|
|
55
|
+
get lastCall(): MockRestCall | undefined;
|
|
56
|
+
/** Remove rotas e histórico. */
|
|
57
|
+
reset(): void;
|
|
58
|
+
/** A implementação de `fetch` para passar em `new SquordClient({ fetchImpl })`. */
|
|
59
|
+
readonly fetch: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
60
|
+
}
|
|
61
|
+
/** Cria um `MockRest` já com as rotas mínimas que o `login()` usa. */
|
|
62
|
+
declare function createMockRest(options?: {
|
|
63
|
+
token?: string;
|
|
64
|
+
}): MockRest;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* MockGateway: um gateway do Squord simulado em memória.
|
|
68
|
+
*
|
|
69
|
+
* Fala o protocolo real — `hello`, `identify`, `ready`, `heartbeat`,
|
|
70
|
+
* `heartbeat.ack`, `resume`, `resumed`, `invalid_session`, `reconnect` —
|
|
71
|
+
* para testar o ciclo de vida do cliente (login, reconexão, resume,
|
|
72
|
+
* deduplicação) sem rede. Passe `wsFactory` em `new SquordClient({ ws })`.
|
|
73
|
+
*
|
|
74
|
+
* Os eventos emitidos são guardados num buffer global com sequência `s`
|
|
75
|
+
* crescente, como o histórico do gateway real (até 500 eventos), e o
|
|
76
|
+
* `resume` reenvia tudo que veio depois do `lastSequence` informado.
|
|
77
|
+
*
|
|
78
|
+
* ```ts
|
|
79
|
+
* const gateway = createMockGateway();
|
|
80
|
+
* const client = new SquordClient({ token: "sqb_1.segredo", ws: gateway.wsFactory });
|
|
81
|
+
* await client.login();
|
|
82
|
+
* gateway.emitEvent("message.created", { message: fixtures.message() });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
interface MockGatewayOptions {
|
|
86
|
+
/** Intervalo de heartbeat anunciado no hello. Padrão: 30000. */
|
|
87
|
+
heartbeatIntervalMs?: number;
|
|
88
|
+
/** Token aceito no identify. Aceita qualquer token por padrão. */
|
|
89
|
+
token?: string;
|
|
90
|
+
/** Payload do ready (userId e guilds). */
|
|
91
|
+
ready?: {
|
|
92
|
+
userId: string;
|
|
93
|
+
guilds?: Array<{
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
iconUrl: string | null;
|
|
97
|
+
}>;
|
|
98
|
+
};
|
|
99
|
+
/** `true` para recusar o próximo resume (treinar o fluxo `invalid_session`). */
|
|
100
|
+
refuseResumeOnce?: boolean;
|
|
101
|
+
/** `true` para nunca responder heartbeat.ack (treinar detecção de zumbi). */
|
|
102
|
+
suppressHeartbeatAck?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/** WebSocket simulado (lado cliente). */
|
|
105
|
+
declare class MockWebSocket {
|
|
106
|
+
readonly server: MockGatewayServer;
|
|
107
|
+
static OPEN: number;
|
|
108
|
+
static CLOSING: number;
|
|
109
|
+
static CLOSED: number;
|
|
110
|
+
readyState: number;
|
|
111
|
+
private listeners;
|
|
112
|
+
constructor(server: MockGatewayServer);
|
|
113
|
+
addEventListener(type: string, listener: (event: never) => void): void;
|
|
114
|
+
removeEventListener(type: string, listener: (event: never) => void): void;
|
|
115
|
+
dispatch(type: string, event: Record<string, unknown>): void;
|
|
116
|
+
/** Frame do cliente: entrega ao servidor. */
|
|
117
|
+
send(data: string): void;
|
|
118
|
+
close(code?: number, reason?: string): void;
|
|
119
|
+
/** Servidor fecha a conexão. */
|
|
120
|
+
serverClose(code: number, reason: string): void;
|
|
121
|
+
/** Servidor envia frame. */
|
|
122
|
+
receive(frame: Record<string, unknown>): void;
|
|
123
|
+
}
|
|
124
|
+
declare class MockGatewayServer {
|
|
125
|
+
readonly options: MockGatewayOptions;
|
|
126
|
+
private sockets;
|
|
127
|
+
private eventBuffer;
|
|
128
|
+
private globalSequence;
|
|
129
|
+
private refuseResumePending;
|
|
130
|
+
private knownSessionIds;
|
|
131
|
+
constructor(options?: MockGatewayOptions);
|
|
132
|
+
/** Fábrica de WebSocket para passar ao cliente. */
|
|
133
|
+
readonly wsFactory: (url: string) => MockWebSocket;
|
|
134
|
+
/** Conexões abertas no momento. */
|
|
135
|
+
get connectionCount(): number;
|
|
136
|
+
/** Última sequência emitida. */
|
|
137
|
+
get lastSequence(): number;
|
|
138
|
+
/** Total de eventos já emitidos. */
|
|
139
|
+
get totalEvents(): number;
|
|
140
|
+
/**
|
|
141
|
+
* Emite um evento durável: guarda no buffer (sequência crescente) e
|
|
142
|
+
* entrega às conexões autenticadas.
|
|
143
|
+
*/
|
|
144
|
+
emitEvent(type: string, d: unknown): void;
|
|
145
|
+
/** Envia um frame cru às conexões autenticadas (sem `s`). */
|
|
146
|
+
sendFrame(frame: Record<string, unknown>): void;
|
|
147
|
+
/**
|
|
148
|
+
* Envia um evento com sequência arbitrária (para treinar a deduplicação
|
|
149
|
+
* do cliente: `s` repetido ou antigo deve ser descartado).
|
|
150
|
+
*/
|
|
151
|
+
sendEventWithSequence(type: string, d: unknown, s: number): void;
|
|
152
|
+
/** Fecha as conexões com um código (ex.: 4009 para treinar resume). */
|
|
153
|
+
closeAll(code: number, reason: string): void;
|
|
154
|
+
/** Pede reconexão (frame `reconnect` + fechamento 4007, como o real). */
|
|
155
|
+
requestReconnect(reason?: string): void;
|
|
156
|
+
/** Descarta o histórico de eventos (o próximo resume falha com `invalid_session`). */
|
|
157
|
+
expireHistory(): void;
|
|
158
|
+
/** Reinicia o estado do mock. */
|
|
159
|
+
reset(): void;
|
|
160
|
+
handleClientOpen(socket: MockWebSocket): void;
|
|
161
|
+
handleClientFrame(socket: MockWebSocket, frame: Record<string, unknown>): void;
|
|
162
|
+
handleClientClose(socket: MockWebSocket, code: number, reason: string, byServer?: boolean): void;
|
|
163
|
+
}
|
|
164
|
+
/** Cria o mock do gateway. Use `ws: gateway.wsFactory` no `SquordClient`. */
|
|
165
|
+
declare function createMockGateway(options?: MockGatewayOptions): MockGatewayServer;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Fixtures: payloads de exemplo no formato real da API, para testes de bots
|
|
169
|
+
* e de handlers sem uma comunidade de verdade.
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
/** Um usuário (Ana, dos exemplos da documentação). */
|
|
173
|
+
declare function user(overrides?: Partial<APIUser>): APIUser;
|
|
174
|
+
/** A conta do bot. */
|
|
175
|
+
declare function botUser(overrides?: Partial<APIUser>): APIUser;
|
|
176
|
+
/** Um membro de um Space. */
|
|
177
|
+
declare function member(overrides?: Partial<APIMember>): APIMember;
|
|
178
|
+
/** Um canal de texto. */
|
|
179
|
+
declare function channel(overrides?: Partial<APIChannel>): APIChannel;
|
|
180
|
+
/** Um cargo. */
|
|
181
|
+
declare function role(overrides?: Partial<APIRole>): APIRole;
|
|
182
|
+
/** Um Space com o bloco `self` do bot. */
|
|
183
|
+
declare function guild(overrides?: Partial<APIGuild>): APIGuild;
|
|
184
|
+
/** Uma mensagem. */
|
|
185
|
+
declare function message(overrides?: Partial<APIMessage>): APIMessage;
|
|
186
|
+
/** Uma interação de comando (`interaction.created` com `type: "COMMAND"`). */
|
|
187
|
+
declare function commandInteraction(overrides?: Partial<APIInteraction>): APIInteraction;
|
|
188
|
+
/** Uma interação de componente (`type: "COMPONENT"`). */
|
|
189
|
+
declare function componentInteraction(overrides?: Partial<APIInteraction>): APIInteraction;
|
|
190
|
+
/** Um comando de aplicação registrado. */
|
|
191
|
+
declare function command(overrides?: Partial<APICommand>): APICommand;
|
|
192
|
+
/** Um bot (visão do dono, `GET /bots/@me`). */
|
|
193
|
+
declare function bot(overrides?: Record<string, unknown>): Record<string, unknown>;
|
|
194
|
+
|
|
195
|
+
declare const fixtures_bot: typeof bot;
|
|
196
|
+
declare const fixtures_botUser: typeof botUser;
|
|
197
|
+
declare const fixtures_channel: typeof channel;
|
|
198
|
+
declare const fixtures_command: typeof command;
|
|
199
|
+
declare const fixtures_commandInteraction: typeof commandInteraction;
|
|
200
|
+
declare const fixtures_componentInteraction: typeof componentInteraction;
|
|
201
|
+
declare const fixtures_guild: typeof guild;
|
|
202
|
+
declare const fixtures_member: typeof member;
|
|
203
|
+
declare const fixtures_message: typeof message;
|
|
204
|
+
declare const fixtures_role: typeof role;
|
|
205
|
+
declare const fixtures_user: typeof user;
|
|
206
|
+
declare namespace fixtures {
|
|
207
|
+
export { fixtures_bot as bot, fixtures_botUser as botUser, fixtures_channel as channel, fixtures_command as command, fixtures_commandInteraction as commandInteraction, fixtures_componentInteraction as componentInteraction, fixtures_guild as guild, fixtures_member as member, fixtures_message as message, fixtures_role as role, fixtures_user as user };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @squord/sdk/testing — ferramentas para testar bots sem uma comunidade real.
|
|
212
|
+
*
|
|
213
|
+
* - `createMockRest()`: servidor REST em memória (passe `fetchImpl` ao cliente).
|
|
214
|
+
* - `createMockGateway()`: gateway simulado que fala o protocolo real
|
|
215
|
+
* (passe `wsFactory` ao cliente).
|
|
216
|
+
* - `createMockEnvironment()`: REST + gateway já conectados, com a rota de
|
|
217
|
+
* login respondendo — espalhe `...env.options` no `SquordClient` e pronto.
|
|
218
|
+
* - `fixtures`: payloads de exemplo no formato da API.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
/** Opções aceitas por `createMockEnvironment`. */
|
|
222
|
+
interface MockEnvironmentOptions {
|
|
223
|
+
/** Token que o mock aceita no identify. Padrão: aceita qualquer. */
|
|
224
|
+
token?: string;
|
|
225
|
+
/** Intervalo de heartbeat anunciado. Padrão: 200 (testes rápidos). */
|
|
226
|
+
heartbeatIntervalMs?: number;
|
|
227
|
+
/** Backoff de reconexão curto para testes. Padrão: 20. */
|
|
228
|
+
reconnectBaseMs?: number;
|
|
229
|
+
}
|
|
230
|
+
interface MockEnvironment {
|
|
231
|
+
/** Opções prontas para espalhar no `SquordClient`. */
|
|
232
|
+
options: {
|
|
233
|
+
apiBaseURL: string;
|
|
234
|
+
fetchImpl: typeof fetch;
|
|
235
|
+
ws: (url: string) => unknown;
|
|
236
|
+
gatewayReconnectBaseMs: number;
|
|
237
|
+
};
|
|
238
|
+
/** O gateway simulado: use `emitEvent` para simular eventos do Squord. */
|
|
239
|
+
gateway: MockGatewayServer;
|
|
240
|
+
/** O REST em memória: registre rotas e inspecione `callLog`. */
|
|
241
|
+
rest: MockRest;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Monta o ambiente completo de teste: `createMockRest` com a rota de login
|
|
245
|
+
* (`GET /bots/@me`) já respondendo com um bot de exemplo, e `createMockGateway`
|
|
246
|
+
* falando o protocolo real.
|
|
247
|
+
*
|
|
248
|
+
* ```js
|
|
249
|
+
* import { SquordClient } from "@squord/sdk";
|
|
250
|
+
* import { createMockEnvironment, fixtures } from "@squord/sdk/testing";
|
|
251
|
+
*
|
|
252
|
+
* const env = createMockEnvironment();
|
|
253
|
+
* const client = new SquordClient({ token: "sqb_1.demo", ...env.options });
|
|
254
|
+
* client.on("message.created", (m) => { /* ... *\/ });
|
|
255
|
+
* await client.login();
|
|
256
|
+
* env.gateway.emitEvent("message.created", { message: fixtures.message() });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare function createMockEnvironment(options?: MockEnvironmentOptions): MockEnvironment;
|
|
260
|
+
|
|
261
|
+
export { type MockEnvironment, type MockEnvironmentOptions, type MockGatewayOptions, MockGatewayServer, MockRest, type MockRestCall, type MockRouteHandler, type MockRouteMatch, createMockEnvironment, createMockGateway, createMockRest, fixtures };
|