refactor(gateway): drop shared barrel, migrate to granular imports + shared error helpers

- delete src/shared/index.ts fat barrel; point 10 importers at the exact
  module they use (redis-channels, moderation-types, utils/pagination)
- message-capture/types.ts re-exports from shared/moderation-types directly
- shared/errors: add errorMessage() + isTransientStreamError() helpers,
  replacing the repeated err-message and transient-code checks
- drop unused imports flagged by biome

No behavior change. typecheck + lint + 138 tests green.
This commit is contained in:
asepharyana
2026-09-24 14:58:19 +07:00
parent 8743fcc0b5
commit 6bf3b40cc7
13 changed files with 60 additions and 26 deletions
@@ -1,8 +1,5 @@
import { inArray, lt } from "drizzle-orm"; import { inArray, lt } from "drizzle-orm";
import type { import type { NodePgDatabase } from "drizzle-orm/node-postgres";
NodePgDatabase,
NodePgQueryResultHKT,
} from "drizzle-orm/node-postgres";
import { createChildLogger } from "@/shared/logger/index"; import { createChildLogger } from "@/shared/logger/index";
import { config } from "../shared/config/index.js"; import { config } from "../shared/config/index.js";
import { getDatabase } from "../shared/database/drizzle.js"; import { getDatabase } from "../shared/database/drizzle.js";
@@ -1,12 +1,12 @@
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import Redis from "ioredis"; import Redis from "ioredis";
import { config } from "../../shared/config/index.js"; import { config } from "../../shared/config/index.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { import {
BACKEND_COMMAND, BACKEND_COMMAND,
type CommandMessage, type CommandMessage,
type CommandReply, type CommandReply,
} from "../../shared/index.js"; } from "../../shared/redis-channels.js";
import { createChildLogger } from "../../shared/logger/index.js";
import { GuildHandler } from "./guild.handler.js"; import { GuildHandler } from "./guild.handler.js";
import { import {
type CommandHandlerFn, type CommandHandlerFn,
@@ -1,6 +1,9 @@
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js"; import { createChildLogger } from "../../shared/logger/index.js";
import type {
CommandMessage,
CommandReply,
} from "../../shared/redis-channels.js";
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// GuildHandler // GuildHandler
@@ -4,7 +4,7 @@ import {
COMMAND_MODERATION_ACTION, COMMAND_MODERATION_ACTION,
type CommandMessage, type CommandMessage,
type CommandReply, type CommandReply,
} from "../../shared/index.js"; } from "../../shared/redis-channels.js";
import type { GuildHandler } from "./guild.handler.js"; import type { GuildHandler } from "./guild.handler.js";
import type { ModerationHandler } from "./moderation.handler.js"; import type { ModerationHandler } from "./moderation.handler.js";
@@ -1,6 +1,9 @@
import type { Client } from "discord.js-selfbot-v13"; import type { Client } from "discord.js-selfbot-v13";
import type { CommandMessage, CommandReply } from "../../shared/index.js";
import { createChildLogger } from "../../shared/logger/index.js"; import { createChildLogger } from "../../shared/logger/index.js";
import type {
CommandMessage,
CommandReply,
} from "../../shared/redis-channels.js";
import { messageStore } from "../message-capture/messageStore.js"; import { messageStore } from "../message-capture/messageStore.js";
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -1,9 +1,12 @@
import Redis from "ioredis"; import Redis from "ioredis";
import type { AttachmentRecord, MessageRecord } from "../../shared/index.js";
import { import {
type CustomLogger, type CustomLogger,
createChildLogger, createChildLogger,
} from "../../shared/logger/index.js"; } from "../../shared/logger/index.js";
import type {
AttachmentRecord,
MessageRecord,
} from "../../shared/moderation-types.js";
import { type DiscordGatewayEvent, EventChannels } from "./eventTypes.js"; import { type DiscordGatewayEvent, EventChannels } from "./eventTypes.js";
export class RedisEventPublisher { export class RedisEventPublisher {
@@ -17,7 +17,7 @@ import {
DISCORD_THREAD_DELETED, DISCORD_THREAD_DELETED,
DISCORD_THREAD_UPDATED, DISCORD_THREAD_UPDATED,
type DiscordGatewayEvent, type DiscordGatewayEvent,
} from "../../shared/index.js"; } from "../../shared/redis-channels.js";
export type { DiscordGatewayEvent }; export type { DiscordGatewayEvent };
@@ -2,8 +2,11 @@ import { and, desc, eq, inArray, type SQL, sql } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messagesTable } from "../../shared/database/schema.js"; import { messagesTable } from "../../shared/database/schema.js";
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js"; import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import {
buildCursorCondition,
pageResult,
} from "../../shared/utils/pagination.js";
import type { import type {
MessageQuery, MessageQuery,
MessageRecord, MessageRecord,
@@ -2,8 +2,11 @@ import { and, desc, eq, inArray, type SQL } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { moderationActionsTable } from "../../shared/database/schema.js"; import { moderationActionsTable } from "../../shared/database/schema.js";
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js"; import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import {
buildCursorCondition,
pageResult,
} from "../../shared/utils/pagination.js";
import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js"; import type { EventBroadcaster } from "../event-broadcaster/eventBroadcaster.js";
import type { ModerationAction, PageResult } from "../message-capture/types.js"; import type { ModerationAction, PageResult } from "../message-capture/types.js";
@@ -2,8 +2,11 @@ import { and, desc, eq, inArray, type SQL } from "drizzle-orm";
import type { NodePgDatabase } from "drizzle-orm/node-postgres"; import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import type * as schema from "../../shared/database/schema.js"; import type * as schema from "../../shared/database/schema.js";
import { messageReviewsTable } from "../../shared/database/schema.js"; import { messageReviewsTable } from "../../shared/database/schema.js";
import { buildCursorCondition, pageResult } from "../../shared/index.js";
import { createChildLogger, type Logger } from "../../shared/logger/index.js"; import { createChildLogger, type Logger } from "../../shared/logger/index.js";
import {
buildCursorCondition,
pageResult,
} from "../../shared/utils/pagination.js";
import type { MessageReview, PageResult } from "../message-capture/types.js"; import type { MessageReview, PageResult } from "../message-capture/types.js";
// ─── ReviewsDb Class ──────────────────────────────────────────────────────── // ─── ReviewsDb Class ────────────────────────────────────────────────────────
@@ -2,8 +2,7 @@ import type {
AnalysisQueueStatus, AnalysisQueueStatus,
AttachmentRecord, AttachmentRecord,
MessageRecord, MessageRecord,
UserMetadata, } from "../../shared/moderation-types.js";
} from "../../shared/index.js";
// Re-export all shared types for backward compatibility // Re-export all shared types for backward compatibility
export type { export type {
@@ -26,7 +25,7 @@ export type {
ReviewStatus, ReviewStatus,
RoleMetadata, RoleMetadata,
UserMetadata, UserMetadata,
} from "../../shared/index.js"; } from "../../shared/moderation-types.js";
// Local-only types (not shared across services) // Local-only types (not shared across services)
export type ModerationWsEvent = export type ModerationWsEvent =
@@ -46,3 +46,32 @@ export class ConfigError extends AppError {
this.name = "ConfigError"; this.name = "ConfigError";
} }
} }
// ---------------------------------------------------------------------------
// Generic error helpers (shared by every module — avoids the repeated
// `err instanceof Error ? err.message : String(err)` pattern, 18+ sites)
// ---------------------------------------------------------------------------
/** Normalize an unknown thrown value to a readable message. */
export function errorMessage(err: unknown): string {
return err instanceof Error ? err.message : String(err);
}
/**
* True when an error code is a transient stream-teardown failure
* (EPIPE / stream destroyed / write-after-end / socket reset).
*
* These are NOT fatal: crashing the gateway on them (e.g. voice stop races,
* ffmpeg stdin closed while we still write) takes the whole bot offline
* mid-operation. Callers that install process-level handlers use this to
* log-and-continue instead of shutting down.
*/
export function isTransientStreamError(err: unknown): boolean {
const code = (err as NodeJS.ErrnoException)?.code ?? "";
return (
code === "EPIPE" ||
code === "ERR_STREAM_DESTROYED" ||
code === "ERR_STREAM_WRITE_AFTER_END" ||
code === "ECONNRESET"
);
}
@@ -1,9 +0,0 @@
export * from "./config/index.js";
export * from "./database/init.js";
export * from "./database/pool.js";
export * from "./database/schema.js";
export * from "./errors/index.js";
export * from "./logger/index.js";
export * from "./moderation-types.js";
export * from "./redis-channels.js";
export * from "./utils/index.js";