From 5f6578c8cd8e8ff5f4a97b72b54d2c1c796d061f Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Tue, 30 Sep 2025 22:07:52 -0400 Subject: [PATCH] fix circular dependency caused by is-retryable-error, render-inline-error, and render-full-error --- packages/backend/src/core/CaptchaService.ts | 12 +----------- packages/backend/src/misc/captcha-error.ts | 10 +++++++++- packages/backend/src/misc/errors/ConflictError.ts | 6 ++++++ packages/backend/src/misc/is-retryable-error.ts | 4 ++-- packages/backend/src/misc/render-full-error.ts | 2 +- packages/backend/src/server/SkRateLimiterService.ts | 3 +-- 6 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 packages/backend/src/misc/errors/ConflictError.ts diff --git a/packages/backend/src/core/CaptchaService.ts b/packages/backend/src/core/CaptchaService.ts index 020984a37f..a0ea909cf2 100644 --- a/packages/backend/src/core/CaptchaService.ts +++ b/packages/backend/src/core/CaptchaService.ts @@ -10,23 +10,13 @@ import { MetaService } from '@/core/MetaService.js'; import { MiMeta } from '@/models/Meta.js'; import Logger from '@/logger.js'; import { LoggerService } from '@/core/LoggerService.js'; -import { CaptchaError } from '@/misc/captcha-error.js'; +import { CaptchaError, captchaErrorCodes } from '@/misc/captcha-error.js'; export { CaptchaError } from '@/misc/captcha-error.js'; export const supportedCaptchaProviders = ['none', 'hcaptcha', 'mcaptcha', 'recaptcha', 'turnstile', 'fc', 'testcaptcha'] as const; export type CaptchaProvider = typeof supportedCaptchaProviders[number]; -export const captchaErrorCodes = { - invalidProvider: Symbol('invalidProvider'), - invalidParameters: Symbol('invalidParameters'), - noResponseProvided: Symbol('noResponseProvided'), - requestFailed: Symbol('requestFailed'), - verificationFailed: Symbol('verificationFailed'), - unknown: Symbol('unknown'), -} as const; -export type CaptchaErrorCode = typeof captchaErrorCodes[keyof typeof captchaErrorCodes]; - export type CaptchaSetting = { provider: CaptchaProvider; hcaptcha: { diff --git a/packages/backend/src/misc/captcha-error.ts b/packages/backend/src/misc/captcha-error.ts index 217018ec68..7da8e386d9 100644 --- a/packages/backend/src/misc/captcha-error.ts +++ b/packages/backend/src/misc/captcha-error.ts @@ -3,7 +3,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import type { CaptchaErrorCode } from '@/core/CaptchaService.js'; +export const captchaErrorCodes = { + invalidProvider: Symbol('invalidProvider'), + invalidParameters: Symbol('invalidParameters'), + noResponseProvided: Symbol('noResponseProvided'), + requestFailed: Symbol('requestFailed'), + verificationFailed: Symbol('verificationFailed'), + unknown: Symbol('unknown'), +} as const; +export type CaptchaErrorCode = typeof captchaErrorCodes[keyof typeof captchaErrorCodes]; export class CaptchaError extends Error { public readonly code: CaptchaErrorCode; diff --git a/packages/backend/src/misc/errors/ConflictError.ts b/packages/backend/src/misc/errors/ConflictError.ts new file mode 100644 index 0000000000..b63afb8efe --- /dev/null +++ b/packages/backend/src/misc/errors/ConflictError.ts @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class ConflictError extends Error {} diff --git a/packages/backend/src/misc/is-retryable-error.ts b/packages/backend/src/misc/is-retryable-error.ts index 63b561b280..be09b4b838 100644 --- a/packages/backend/src/misc/is-retryable-error.ts +++ b/packages/backend/src/misc/is-retryable-error.ts @@ -7,9 +7,9 @@ import { AbortError, FetchError } from 'node-fetch'; import { UnrecoverableError } from 'bullmq'; import { StatusError } from '@/misc/status-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; -import { CaptchaError, captchaErrorCodes } from '@/core/CaptchaService.js'; +import { CaptchaError, captchaErrorCodes } from '@/misc/captcha-error.js'; import { FastifyReplyError } from '@/misc/fastify-reply-error.js'; -import { ConflictError } from '@/server/SkRateLimiterService.js'; +import { ConflictError } from '@/misc/errors/ConflictError.js'; /** * Returns false if the provided value represents a "permanent" error that cannot be retried. diff --git a/packages/backend/src/misc/render-full-error.ts b/packages/backend/src/misc/render-full-error.ts index 5f0a09bba9..7433c7ac34 100644 --- a/packages/backend/src/misc/render-full-error.ts +++ b/packages/backend/src/misc/render-full-error.ts @@ -8,7 +8,7 @@ import { AbortError, FetchError } from 'node-fetch'; import { StatusError } from '@/misc/status-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; import { renderInlineError } from '@/misc/render-inline-error.js'; -import { CaptchaError, captchaErrorCodes } from '@/core/CaptchaService.js'; +import { CaptchaError, captchaErrorCodes } from '@/misc/captcha-error.js'; export function renderFullError(e?: unknown): unknown { if (e === undefined) return 'undefined'; diff --git a/packages/backend/src/server/SkRateLimiterService.ts b/packages/backend/src/server/SkRateLimiterService.ts index a53c58ba5a..e9a4a061ad 100644 --- a/packages/backend/src/server/SkRateLimiterService.ts +++ b/packages/backend/src/server/SkRateLimiterService.ts @@ -8,6 +8,7 @@ import Redis from 'ioredis'; import type { TimeService } from '@/core/TimeService.js'; import type { EnvService } from '@/core/EnvService.js'; import { BucketRateLimit, LegacyRateLimit, LimitInfo, RateLimit, hasMinLimit, isLegacyRateLimit, Keyed, hasMaxLimit, disabledLimitInfo, MaxLegacyLimit, MinLegacyLimit } from '@/misc/rate-limit-utils.js'; +import { ConflictError } from '@/misc/errors/ConflictError.js'; import { DI } from '@/di-symbols.js'; import { MemoryKVCache } from '@/misc/cache.js'; import type { MiUser } from '@/models/_.js'; @@ -389,8 +390,6 @@ function createLimitKey(limit: ParsedLimit, actor: string, value: string): strin return `rl_${actor}_${limit.key}_${value}`; } -export class ConflictError extends Error {} - interface LimitCounter { timestamp: number; counter: number;