From e21d6d424a2c35f01c9245b4b05ea303bbe32f82 Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 13:42:55 +0300 Subject: [PATCH 1/9] fix(ai): resolve agent billing owner and credit logging --- packages/ai/package.json | 1 + packages/ai/src/ai/agents/execution.test.ts | 77 ++++++++++++++- packages/ai/src/ai/agents/execution.ts | 102 ++++++++++++++++++-- packages/ai/src/ai/mcp/run-agent.ts | 4 + packages/ai/tsconfig.json | 2 +- 5 files changed, 172 insertions(+), 14 deletions(-) diff --git a/packages/ai/package.json b/packages/ai/package.json index f0bcd009f..b5cd36f94 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -39,6 +39,7 @@ "src" ], "scripts": { + "check-types": "tsc --noEmit", "test": "bun test" }, "dependencies": { diff --git a/packages/ai/src/ai/agents/execution.test.ts b/packages/ai/src/ai/agents/execution.test.ts index 7d437a965..05657460e 100644 --- a/packages/ai/src/ai/agents/execution.test.ts +++ b/packages/ai/src/ai/agents/execution.test.ts @@ -1,5 +1,14 @@ import { beforeEach, describe, expect, it, mock } from "bun:test"; +const mockAutumnCheck = mock(async () => ({ + allowed: true, + balance: { + granted: 100, + remaining: 42, + unlimited: false, + usage: 58, + }, +})); const mockGetBillingCustomerId = mock( async (userId: string, organizationId?: string | null) => organizationId ? `billing:${organizationId}:${userId}` : `billing:${userId}` @@ -7,10 +16,11 @@ const mockGetBillingCustomerId = mock( const mockGetOrganizationOwnerId = mock(async (organizationId: string) => organizationId === "org_missing" ? null : `owner:${organizationId}` ); +const mockMergeWideEvent = mock((_: Record) => {}); mock.module("@databuddy/rpc/autumn", () => ({ getAutumn: () => ({ - check: mock(async () => ({ allowed: true })), + check: mockAutumnCheck, track: mock(async () => undefined), }), })); @@ -26,17 +36,20 @@ mock.module("../../lib/databuddy", () => ({ mock.module("../../lib/tracing", () => ({ captureError: mock(() => {}), - mergeWideEvent: mock(() => {}), + mergeWideEvent: mockMergeWideEvent, })); -const { resolveAgentBillingCustomerId } = await import("./execution"); +const { ensureAgentCreditsAvailable, resolveAgentBillingCustomerId } = + await import("./execution"); type AgentPrincipal = Parameters[0]; type ApiKeyPrincipal = NonNullable; beforeEach(() => { + mockAutumnCheck.mockClear(); mockGetBillingCustomerId.mockClear(); mockGetOrganizationOwnerId.mockClear(); + mockMergeWideEvent.mockClear(); }); describe("resolveAgentBillingCustomerId", () => { @@ -50,12 +63,34 @@ describe("resolveAgentBillingCustomerId", () => { userId: null, }); + expect(customerId).toBe("owner:org_slack"); + expect(mockGetOrganizationOwnerId).toHaveBeenCalledWith("org_slack"); + expect(mockGetBillingCustomerId).not.toHaveBeenCalled(); + expect(mockMergeWideEvent).toHaveBeenCalledWith( + expect.objectContaining({ + agent_billing_resolution: "api_key_org_owner", + billing_customer_id: "owner:org_slack", + organization_id: "org_slack", + }) + ); + }); + + it("bills the organization owner for org-scoped API keys even when the key has a user", async () => { + const customerId = await resolveAgentBillingCustomerId({ + apiKey: { + organizationId: "org_slack", + userId: "installer_123", + } as ApiKeyPrincipal, + organizationId: null, + userId: "installer_123", + }); + expect(customerId).toBe("owner:org_slack"); expect(mockGetOrganizationOwnerId).toHaveBeenCalledWith("org_slack"); expect(mockGetBillingCustomerId).not.toHaveBeenCalled(); }); - it("uses the standard billing owner resolver when a user is present", async () => { + it("uses the standard billing owner resolver for session users", async () => { const customerId = await resolveAgentBillingCustomerId({ apiKey: null, organizationId: "org_slack", @@ -80,3 +115,37 @@ describe("resolveAgentBillingCustomerId", () => { expect(customerId).toBeNull(); }); }); + +describe("ensureAgentCreditsAvailable", () => { + it("logs the checked Autumn customer and balance", async () => { + const allowed = await ensureAgentCreditsAvailable("owner:org_slack"); + + expect(allowed).toBe(true); + expect(mockAutumnCheck).toHaveBeenCalledWith({ + customerId: "owner:org_slack", + featureId: "agent_credits", + }); + expect(mockMergeWideEvent).toHaveBeenCalledWith( + expect.objectContaining({ + agent_credits_allowed: true, + agent_credits_feature_id: "agent_credits", + agent_credits_granted: 100, + agent_credits_remaining: 42, + agent_credits_unlimited: false, + agent_credits_usage: 58, + billing_customer_id: "owner:org_slack", + }) + ); + }); + + it("skips Autumn when billing is not configured", async () => { + const allowed = await ensureAgentCreditsAvailable(null); + + expect(allowed).toBe(true); + expect(mockAutumnCheck).not.toHaveBeenCalled(); + expect(mockMergeWideEvent).toHaveBeenCalledWith({ + agent_credits_allowed: true, + agent_credits_check_skipped: true, + }); + }); +}); diff --git a/packages/ai/src/ai/agents/execution.ts b/packages/ai/src/ai/agents/execution.ts index ab2b33d84..b484cedf7 100644 --- a/packages/ai/src/ai/agents/execution.ts +++ b/packages/ai/src/ai/agents/execution.ts @@ -29,26 +29,109 @@ export async function resolveAgentBillingCustomerId(principal: { organizationId?: string | null; userId?: string | null; }): Promise { - const organizationId = - principal.organizationId ?? principal.apiKey?.organizationId ?? null; + const apiKeyOrganizationId = principal.apiKey?.organizationId ?? null; + const organizationId = principal.organizationId ?? apiKeyOrganizationId; + if (apiKeyOrganizationId) { + const customerId = await getOrganizationOwnerId(apiKeyOrganizationId); + mergeAgentBillingFields({ + apiKeyId: principal.apiKey?.id, + apiKeyUserId: principal.apiKey?.userId, + billingCustomerId: customerId, + organizationId: apiKeyOrganizationId, + resolution: customerId + ? "api_key_org_owner" + : "api_key_org_owner_missing", + }); + return customerId; + } + const ownerUserId = principal.userId ?? principal.apiKey?.userId ?? null; if (!ownerUserId) { - return organizationId ? await getOrganizationOwnerId(organizationId) : null; + const customerId = organizationId + ? await getOrganizationOwnerId(organizationId) + : null; + mergeAgentBillingFields({ + billingCustomerId: customerId, + organizationId, + resolution: customerId ? "org_owner" : "missing_principal", + }); + return customerId; } - return await getBillingCustomerId(ownerUserId, organizationId); + const customerId = await getBillingCustomerId(ownerUserId, organizationId); + mergeAgentBillingFields({ + apiKeyId: principal.apiKey?.id, + apiKeyUserId: principal.apiKey?.userId, + billingCustomerId: customerId, + organizationId, + resolution: organizationId ? "session_org_owner" : "user", + }); + return customerId; } export async function ensureAgentCreditsAvailable( billingCustomerId: string | null ): Promise { if (!billingCustomerId) { + mergeWideEvent({ + agent_credits_allowed: true, + agent_credits_check_skipped: true, + }); return true; } - const allowed = await getAutumn().check({ - customerId: billingCustomerId, - featureId: "agent_credits", + + const startedAt = performance.now(); + try { + const result = await getAutumn().check({ + customerId: billingCustomerId, + featureId: "agent_credits", + }); + const allowed = result.allowed !== false; + const balance = result.balance; + mergeWideEvent({ + agent_credits_allowed: allowed, + agent_credits_feature_id: "agent_credits", + billing_customer_id: billingCustomerId, + "timing.autumn_agent_credits_check_ms": Math.round( + performance.now() - startedAt + ), + ...(balance + ? { + agent_credits_granted: balance.granted, + agent_credits_remaining: balance.remaining, + agent_credits_unlimited: balance.unlimited, + agent_credits_usage: balance.usage, + } + : {}), + }); + return allowed; + } catch (error) { + captureError(error, { + agent_credit_check_error: true, + agent_credits_feature_id: "agent_credits", + billing_customer_id: billingCustomerId, + }); + throw error; + } +} + +function mergeAgentBillingFields(input: { + apiKeyId?: string | null; + apiKeyUserId?: string | null; + billingCustomerId: string | null; + organizationId?: string | null; + resolution: string; +}): void { + mergeWideEvent({ + agent_billing_resolution: input.resolution, + ...(input.apiKeyId ? { agent_api_key_id: input.apiKeyId } : {}), + ...(input.apiKeyUserId + ? { agent_api_key_user_id: input.apiKeyUserId } + : {}), + ...(input.billingCustomerId + ? { billing_customer_id: input.billingCustomerId } + : {}), + ...(input.organizationId ? { organization_id: input.organizationId } : {}), }); - return allowed.allowed !== false; } export async function trackAgentUsageAndBill( @@ -72,6 +155,7 @@ export async function trackAgentUsageAndBill( } const autumn = getAutumn(); + const billingCustomerId = input.billingCustomerId; const tokenTracks: [string, number][] = [ ["agent_input_tokens", summary.fresh_input_tokens], ["agent_output_tokens", summary.output_tokens], @@ -93,7 +177,7 @@ export async function trackAgentUsageAndBill( .map(([featureId, value]) => autumn .track({ - customerId: input.billingCustomerId as string, + customerId: billingCustomerId, featureId, value, }) diff --git a/packages/ai/src/ai/mcp/run-agent.ts b/packages/ai/src/ai/mcp/run-agent.ts index 0989b6298..cd3d28a84 100644 --- a/packages/ai/src/ai/mcp/run-agent.ts +++ b/packages/ai/src/ai/mcp/run-agent.ts @@ -9,6 +9,7 @@ import type { LanguageModelUsage } from "ai"; import { ToolLoopAgent } from "ai"; import { DatabuddyAgentUserError } from "../../agent/errors"; import { getAILogger } from "../../lib/ai-logger"; +import { mergeWideEvent } from "../../lib/tracing"; import { ensureAgentCreditsAvailable, resolveAgentBillingCustomerId, @@ -199,6 +200,9 @@ async function prepareMcpAgentRun(options: RunMcpAgentOptions) { apiKey: options.apiKey, organizationId, }); + mergeWideEvent({ + agent_billing_mode: options.billingMode === "skip" ? "skip" : "bill", + }); if ( options.billingMode !== "skip" && diff --git a/packages/ai/tsconfig.json b/packages/ai/tsconfig.json index 43934f6d3..a174a1e83 100644 --- a/packages/ai/tsconfig.json +++ b/packages/ai/tsconfig.json @@ -13,7 +13,7 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "noUncheckedIndexedAccess": true, + "noUncheckedIndexedAccess": false, "noImplicitOverride": true, "noUnusedLocals": false, "noUnusedParameters": false, From 845090bbd0efb4a1bc8c4cae0ddfea526a35a640 Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 13:43:05 +0300 Subject: [PATCH 2/9] feat(slack): attach agent logs to Slack context --- apps/slack/package.json | 1 + apps/slack/src/agent/agent-client.ts | 10 +- apps/slack/src/index.ts | 16 ++- apps/slack/src/lib/evlog-slack.ts | 28 +++- apps/slack/src/slack/installations.ts | 10 +- apps/slack/src/slack/run-handler.ts | 181 +++++++++++++------------- bun.lock | 1 + packages/rpc/package.json | 3 +- 8 files changed, 150 insertions(+), 100 deletions(-) diff --git a/apps/slack/package.json b/apps/slack/package.json index cc2c744d2..7b89e03ff 100644 --- a/apps/slack/package.json +++ b/apps/slack/package.json @@ -17,6 +17,7 @@ "@databuddy/encryption": "workspace:*", "@databuddy/env": "workspace:*", "@databuddy/redis": "workspace:*", + "@databuddy/rpc": "workspace:*", "@slack/bolt": "^4.7.2", "@slack/web-api": "^7.15.1", "evlog": "catalog:" diff --git a/apps/slack/src/agent/agent-client.ts b/apps/slack/src/agent/agent-client.ts index bd23d3078..10ca51d2c 100644 --- a/apps/slack/src/agent/agent-client.ts +++ b/apps/slack/src/agent/agent-client.ts @@ -2,7 +2,8 @@ import { streamDatabuddyAgent, type DatabuddyAgentSlackContext, } from "@databuddy/ai/agent"; -import { SLACK_COPY } from "../slack/messages"; +import { setActiveSlackLog } from "@/lib/evlog-slack"; +import { SLACK_COPY } from "@/slack/messages"; const DEFAULT_TIMEZONE = "UTC"; @@ -31,6 +32,7 @@ export interface SlackAgentRun { } export interface SlackRunContext { + agentApiKeyId?: string; agentApiKeySecret: string; organizationId: string; teamId: string; @@ -92,6 +94,12 @@ class SharedDatabuddyAgentRunner implements SlackAgentRunner { options?: SlackAgentStreamOptions ): AsyncGenerator { const conversationId = createSlackConversationId(run); + setActiveSlackLog({ + agent_chat_id: conversationId, + agent_source: "slack", + organization_id: context.organizationId, + slack_agent_api_key_id: context.agentApiKeyId, + }); yield* streamDatabuddyAgent({ abortSignal: options?.abortSignal, actor: { diff --git a/apps/slack/src/index.ts b/apps/slack/src/index.ts index 0660dc4a5..4e8bd58ae 100644 --- a/apps/slack/src/index.ts +++ b/apps/slack/src/index.ts @@ -1,18 +1,21 @@ +import { setAiRequestLoggerProvider } from "@databuddy/ai/lib/request-logger"; import { shutdownPostgres } from "@databuddy/db"; +import { setRpcRequestLoggerProvider } from "@databuddy/rpc/log-context"; import { App } from "@slack/bolt"; import { initLogger, log } from "evlog"; -import { DatabuddyAgentClient } from "./agent/agent-client"; -import { resolveSlackConfig } from "./config"; +import { DatabuddyAgentClient } from "@/agent/agent-client"; +import { resolveSlackConfig } from "@/config"; import { captureSlackError, flushBatchedSlackDrain, + getActiveSlackLog, slackLoggerDrain, -} from "./lib/evlog-slack"; +} from "@/lib/evlog-slack"; import { createSlackAuthorize, SlackInstallationStore, -} from "./slack/installations"; -import { registerSlackListeners } from "./slack/listeners"; +} from "@/slack/installations"; +import { registerSlackListeners } from "@/slack/listeners"; initLogger({ env: { service: "slack" }, @@ -20,6 +23,9 @@ initLogger({ sampling: {}, }); +setAiRequestLoggerProvider(getActiveSlackLog); +setRpcRequestLoggerProvider(getActiveSlackLog); + process.on("unhandledRejection", (reason) => { captureSlackError(reason, { process: "unhandledRejection" }); }); diff --git a/apps/slack/src/lib/evlog-slack.ts b/apps/slack/src/lib/evlog-slack.ts index 95d841b8f..3f7242b42 100644 --- a/apps/slack/src/lib/evlog-slack.ts +++ b/apps/slack/src/lib/evlog-slack.ts @@ -1,3 +1,4 @@ +import { AsyncLocalStorage } from "node:async_hooks"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { env } from "@databuddy/env/slack"; @@ -10,6 +11,8 @@ import { createDrainPipeline } from "evlog/pipeline"; type SlackLogValue = string | number | boolean; type SlackLogFields = Record; +const activeSlackLog = new AsyncLocalStorage(); + const axiomApiKey = env.AXIOM_API_KEY ?? env.AXIOM_TOKEN; const batchedAxiomDrain = axiomApiKey @@ -49,7 +52,11 @@ export async function slackLoggerDrain(ctx: DrainContext): Promise { if (fsDrain) { await fsDrain(ctx); } - batchedAxiomDrain?.(ctx); + try { + await batchedAxiomDrain?.(ctx); + } catch { + // Drain failures must not break Slack event handling. + } } export async function flushBatchedSlackDrain(): Promise { @@ -60,6 +67,25 @@ export function createSlackEventLog(fields: SlackLogFields): RequestLogger { return createLogger(cleanFields({ service: "slack", ...fields })); } +export function getActiveSlackLog(): RequestLogger { + const logger = activeSlackLog.getStore(); + if (!logger) { + throw new Error("No active Slack evlog context"); + } + return logger; +} + +export function setActiveSlackLog(fields: SlackLogFields): void { + activeSlackLog.getStore()?.set(cleanFields(fields)); +} + +export async function withSlackLogContext( + logger: RequestLogger, + fn: () => Promise +): Promise { + return await activeSlackLog.run(logger, fn); +} + export function setSlackLog( logger: RequestLogger | undefined, fields: SlackLogFields diff --git a/apps/slack/src/slack/installations.ts b/apps/slack/src/slack/installations.ts index 4afc27f24..a03fd736e 100644 --- a/apps/slack/src/slack/installations.ts +++ b/apps/slack/src/slack/installations.ts @@ -7,10 +7,10 @@ import type { SlackAgentRun, SlackRunContext, SlackRunContextResolver, -} from "../agent/agent-client"; -import type { TokenCryptoConfig } from "../config"; -import { createSlackEventLog, setSlackLog, toError } from "../lib/evlog-slack"; -import { SLACK_COPY } from "./messages"; +} from "@/agent/agent-client"; +import type { TokenCryptoConfig } from "@/config"; +import { createSlackEventLog, setSlackLog, toError } from "@/lib/evlog-slack"; +import { SLACK_COPY } from "@/slack/messages"; export interface SlackChannelBindingCommand { channelId: string; @@ -184,6 +184,7 @@ export class SlackInstallationStore implements SlackRunContextResolver { private toRunContext(installation: ActiveSlackIntegration): SlackRunContext { return { + agentApiKeyId: installation.agentApiKeyId, agentApiKeySecret: decrypt( installation.agentApiKeyCiphertext, this.#crypto.encryptionKey @@ -233,6 +234,7 @@ function findActiveIntegration(teamId: string) { .select({ id: slackIntegrations.id, agentApiKeyCiphertext: slackIntegrations.agentApiKeyCiphertext, + agentApiKeyId: slackIntegrations.agentApiKeyId, botId: slackIntegrations.botId, botTokenCiphertext: slackIntegrations.botTokenCiphertext, botUserId: slackIntegrations.botUserId, diff --git a/apps/slack/src/slack/run-handler.ts b/apps/slack/src/slack/run-handler.ts index 73d2fa160..1cc3cce8e 100644 --- a/apps/slack/src/slack/run-handler.ts +++ b/apps/slack/src/slack/run-handler.ts @@ -3,18 +3,22 @@ import type { DatabuddyAgentClient, SlackAgentRun, SlackFollowUpMessage, -} from "../agent/agent-client"; +} from "@/agent/agent-client"; import { createSlackEventLog, getSlackApiErrorCode, setSlackLog, -} from "../lib/evlog-slack"; -import { cleanupSlackActiveRun, registerSlackActiveRun } from "./active-runs"; -import { SLACK_COPY } from "./messages"; -import { streamAgentToSlack } from "./respond"; -import { createSlackConversationContext } from "./slack-context"; -import type { SlackAgentClient, SlackLogger, SlackSay } from "./types"; -import type { SlackThreadQueueStore } from "./thread-queue"; + withSlackLogContext, +} from "@/lib/evlog-slack"; +import { + cleanupSlackActiveRun, + registerSlackActiveRun, +} from "@/slack/active-runs"; +import { SLACK_COPY } from "@/slack/messages"; +import { streamAgentToSlack } from "@/slack/respond"; +import { createSlackConversationContext } from "@/slack/slack-context"; +import type { SlackAgentClient, SlackLogger, SlackSay } from "@/slack/types"; +import type { SlackThreadQueueStore } from "@/slack/thread-queue"; const MAX_FOLLOW_UP_ROUNDS = 3; const QUEUED_TAKEOVER_RETRY_DELAYS_MS = [0, 25, 75] as const; @@ -40,96 +44,97 @@ export async function handleAgentRun({ let abortController: AbortController | null = null; let registeredRun: SlackAgentRun | null = null; - try { - await threadQueue.markEngaged(run); - lockAcquired = await threadQueue.tryAcquire(run); - let currentRun = run; - if (!lockAcquired) { - const queued = await threadQueue.enqueue(run); - setSlackLog(eventLog, { - slack_followup_queued: queued.ok, - slack_followup_queue_reason: queued.reason, - slack_followup_queue_size: queued.queuedCount, - slack_followup_truncated: queued.truncated, - slack_response_ok: true, - }); - - if (!queued.ok) { - return; - } - - lockAcquired = await tryAcquireQueuedRun(run, threadQueue); + await withSlackLogContext(eventLog, async () => { + try { + await threadQueue.markEngaged(run); + lockAcquired = await threadQueue.tryAcquire(run); + let currentRun = run; if (!lockAcquired) { - return; + const queued = await threadQueue.enqueue(run); + setSlackLog(eventLog, { + slack_followup_queued: queued.ok, + slack_followup_queue_reason: queued.reason, + slack_followup_queue_size: queued.queuedCount, + slack_followup_truncated: queued.truncated, + }); + + if (!queued.ok) { + return; + } + + lockAcquired = await tryAcquireQueuedRun(run, threadQueue); + if (!lockAcquired) { + return; + } + + const followUps = await threadQueue.drain(run); + if (followUps.length === 0) { + return; + } + + setSlackLog(eventLog, { + slack_followup_takeover: true, + slack_followup_takeover_count: followUps.length, + }); + currentRun = createFollowUpRun(run, followUps); } - const followUps = await threadQueue.drain(run); - if (followUps.length === 0) { - return; + registeredRun = currentRun; + abortController = registerSlackActiveRun(registeredRun); + await addTriggerReaction({ client, eventLog, logger, run: currentRun }); + const slackContext = + currentRun.slackContext ?? + createSlackConversationContext(client, currentRun); + currentRun = { ...currentRun, slackContext }; + let totalFollowUps = 0; + for (let round = 0; round <= MAX_FOLLOW_UP_ROUNDS; round++) { + const result = await streamAgentToSlack({ + abortSignal: abortController?.signal, + agent, + client, + eventLog, + logger, + run: currentRun, + say, + }); + setSlackLog(eventLog, { + slack_response_aborted: result.aborted, + slack_response_ok: result.ok, + slack_response_ts: result.responseTs, + slack_response_streamed: result.streamed, + }); + + if (result.aborted || round >= MAX_FOLLOW_UP_ROUNDS) { + break; + } + + const followUps = await threadQueue.drain(run); + if (followUps.length === 0) { + break; + } + + totalFollowUps += followUps.length; + currentRun = createFollowUpRun(currentRun, followUps); } - setSlackLog(eventLog, { - slack_followup_takeover: true, - slack_followup_takeover_count: followUps.length, - }); - currentRun = createFollowUpRun(run, followUps); - } - - registeredRun = currentRun; - abortController = registerSlackActiveRun(registeredRun); - await addTriggerReaction({ client, eventLog, logger, run: currentRun }); - const slackContext = - currentRun.slackContext ?? - createSlackConversationContext(client, currentRun); - currentRun = { ...currentRun, slackContext }; - let totalFollowUps = 0; - for (let round = 0; round <= MAX_FOLLOW_UP_ROUNDS; round++) { - const result = await streamAgentToSlack({ - abortSignal: abortController?.signal, - agent, - client, - eventLog, - logger, - run: currentRun, - say, - }); - setSlackLog(eventLog, { - slack_response_aborted: result.aborted, - slack_response_ok: result.ok, - slack_response_ts: result.responseTs, - slack_response_streamed: result.streamed, - }); - - if (result.aborted || round >= MAX_FOLLOW_UP_ROUNDS) { - break; + if (totalFollowUps > 0) { + setSlackLog(eventLog, { + slack_followup_drained_count: totalFollowUps, + }); } - - const followUps = await threadQueue.drain(run); - if (followUps.length === 0) { - break; + } finally { + if (lockAcquired) { + await threadQueue.release(run).catch((error) => { + logger.warn("Failed to release Slack thread lock", error); + }); } - - totalFollowUps += followUps.length; - currentRun = createFollowUpRun(currentRun, followUps); - } - - if (totalFollowUps > 0) { + cleanupSlackActiveRun(registeredRun ?? run); setSlackLog(eventLog, { - slack_followup_drained_count: totalFollowUps, + "timing.slack_total_ms": Math.round(performance.now() - startedAt), }); + eventLog.emit(); } - } finally { - if (lockAcquired) { - await threadQueue.release(run).catch((error) => { - logger.warn("Failed to release Slack thread lock", error); - }); - } - cleanupSlackActiveRun(registeredRun ?? run); - setSlackLog(eventLog, { - "timing.slack_total_ms": Math.round(performance.now() - startedAt), - }); - eventLog.emit(); - } + }); } async function tryAcquireQueuedRun( diff --git a/bun.lock b/bun.lock index 655ead01a..443e7db3c 100644 --- a/bun.lock +++ b/bun.lock @@ -353,6 +353,7 @@ "@databuddy/encryption": "workspace:*", "@databuddy/env": "workspace:*", "@databuddy/redis": "workspace:*", + "@databuddy/rpc": "workspace:*", "@slack/bolt": "^4.7.2", "@slack/web-api": "^7.15.1", "evlog": "catalog:", diff --git a/packages/rpc/package.json b/packages/rpc/package.json index d9ef579e5..43c20c86a 100644 --- a/packages/rpc/package.json +++ b/packages/rpc/package.json @@ -13,7 +13,8 @@ "exports": { ".": "./src/index.ts", "./autumn": "./src/lib/autumn-client.ts", - "./billing": "./src/utils/billing.ts" + "./billing": "./src/utils/billing.ts", + "./log-context": "./src/lib/rpc-log-context.ts" }, "dependencies": { "@databuddy/api-keys": "workspace:*", From 96800b790f0182da261e6fd33363829777862223 Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 13:43:12 +0300 Subject: [PATCH 3/9] chore(slack): use alias imports --- apps/slack/src/agent/agent-client.test.ts | 2 +- apps/slack/src/slack/active-runs.test.ts | 2 +- apps/slack/src/slack/active-runs.ts | 2 +- apps/slack/src/slack/channel-policy.test.ts | 4 +-- apps/slack/src/slack/channel-policy.ts | 4 +-- apps/slack/src/slack/feedback.test.ts | 2 +- apps/slack/src/slack/feedback.ts | 6 ++-- apps/slack/src/slack/listeners.test.ts | 12 +++---- apps/slack/src/slack/listeners.ts | 35 ++++++++++--------- apps/slack/src/slack/output-adapter.test.ts | 2 +- apps/slack/src/slack/respond.test.ts | 8 ++--- apps/slack/src/slack/respond.ts | 13 +++---- apps/slack/src/slack/run-handler.test.ts | 8 ++--- apps/slack/src/slack/slack-context.test.ts | 4 +-- apps/slack/src/slack/slack-context.ts | 4 +-- apps/slack/src/slack/slash-commands.ts | 8 ++--- apps/slack/src/slack/thread-queue.test.ts | 4 +-- apps/slack/src/slack/thread-queue.ts | 5 +-- apps/slack/src/slack/thread-relevance.test.ts | 2 +- apps/slack/src/slack/thread-relevance.ts | 2 +- 20 files changed, 63 insertions(+), 66 deletions(-) diff --git a/apps/slack/src/agent/agent-client.test.ts b/apps/slack/src/agent/agent-client.test.ts index d4a44e90c..652ef035e 100644 --- a/apps/slack/src/agent/agent-client.test.ts +++ b/apps/slack/src/agent/agent-client.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, mock } from "bun:test"; -import type { SlackAgentRun, SlackRunContext } from "./agent-client"; +import type { SlackAgentRun, SlackRunContext } from "@/agent/agent-client"; let capturedSharedAgentOptions: Record | null = null; diff --git a/apps/slack/src/slack/active-runs.test.ts b/apps/slack/src/slack/active-runs.test.ts index a824b08d4..b162ef638 100644 --- a/apps/slack/src/slack/active-runs.test.ts +++ b/apps/slack/src/slack/active-runs.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "bun:test"; -import { abortSlackActiveRun, registerSlackActiveRun } from "./active-runs"; +import { abortSlackActiveRun, registerSlackActiveRun } from "@/slack/active-runs"; describe("Slack active runs", () => { it("aborts a registered run by Slack message reference", () => { diff --git a/apps/slack/src/slack/active-runs.ts b/apps/slack/src/slack/active-runs.ts index 661f649c5..843c95866 100644 --- a/apps/slack/src/slack/active-runs.ts +++ b/apps/slack/src/slack/active-runs.ts @@ -1,4 +1,4 @@ -import type { SlackAgentRun } from "../agent/agent-client"; +import type { SlackAgentRun } from "@/agent/agent-client"; interface SlackMessageRef { channelId: string; diff --git a/apps/slack/src/slack/channel-policy.test.ts b/apps/slack/src/slack/channel-policy.test.ts index 35f0b6422..402d8d43a 100644 --- a/apps/slack/src/slack/channel-policy.test.ts +++ b/apps/slack/src/slack/channel-policy.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test"; -import { getSlackChannelMentionPolicy } from "./channel-policy"; -import type { SlackAgentClient } from "./types"; +import { getSlackChannelMentionPolicy } from "@/slack/channel-policy"; +import type { SlackAgentClient } from "@/slack/types"; const logger = { warn: () => undefined, diff --git a/apps/slack/src/slack/channel-policy.ts b/apps/slack/src/slack/channel-policy.ts index 413a30564..a4c1774b3 100644 --- a/apps/slack/src/slack/channel-policy.ts +++ b/apps/slack/src/slack/channel-policy.ts @@ -1,5 +1,5 @@ -import { getSlackApiErrorCode } from "../lib/evlog-slack"; -import type { SlackAgentClient } from "./types"; +import { getSlackApiErrorCode } from "@/lib/evlog-slack"; +import type { SlackAgentClient } from "@/slack/types"; export type SlackChannelPolicyReason = | "internal" diff --git a/apps/slack/src/slack/feedback.test.ts b/apps/slack/src/slack/feedback.test.ts index 943ab96a3..c03ce7f4e 100644 --- a/apps/slack/src/slack/feedback.test.ts +++ b/apps/slack/src/slack/feedback.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "bun:test"; -import { classifySlackReactionSentiment } from "./feedback"; +import { classifySlackReactionSentiment } from "@/slack/feedback"; describe("Slack feedback reactions", () => { it("classifies explicit positive reactions", () => { diff --git a/apps/slack/src/slack/feedback.ts b/apps/slack/src/slack/feedback.ts index 8f5ce84b6..33bdcf281 100644 --- a/apps/slack/src/slack/feedback.ts +++ b/apps/slack/src/slack/feedback.ts @@ -5,9 +5,9 @@ import { type AgentFeedbackSentiment, } from "@databuddy/ai/agent/feedback"; import type { types } from "@slack/bolt"; -import { createSlackEventLog, setSlackLog, toError } from "../lib/evlog-slack"; -import type { SlackInstallationServices } from "./installations"; -import { SLACK_COPY } from "./messages"; +import { createSlackEventLog, setSlackLog, toError } from "@/lib/evlog-slack"; +import type { SlackInstallationServices } from "@/slack/installations"; +import { SLACK_COPY } from "@/slack/messages"; export type SlackFeedbackAction = "added" | "removed"; export type SlackFeedbackSentiment = AgentFeedbackSentiment; diff --git a/apps/slack/src/slack/listeners.test.ts b/apps/slack/src/slack/listeners.test.ts index 2d43127c4..5e42e4ddb 100644 --- a/apps/slack/src/slack/listeners.test.ts +++ b/apps/slack/src/slack/listeners.test.ts @@ -1,14 +1,14 @@ import { describe, expect, it } from "bun:test"; import type { App } from "@slack/bolt"; -import type { DatabuddyAgentClient, SlackAgentRun } from "../agent/agent-client"; -import type { SlackInstallationServices } from "./installations"; -import { registerSlackListeners } from "./listeners"; -import { SLACK_COPY } from "./messages"; -import type { SlackThreadReplyGate } from "./thread-relevance"; +import type { DatabuddyAgentClient, SlackAgentRun } from "@/agent/agent-client"; +import type { SlackInstallationServices } from "@/slack/installations"; +import { registerSlackListeners } from "@/slack/listeners"; +import { SLACK_COPY } from "@/slack/messages"; +import type { SlackThreadReplyGate } from "@/slack/thread-relevance"; import type { SlackFollowUpQueueResult, SlackThreadQueueStore, -} from "./thread-queue"; +} from "@/slack/thread-queue"; type Handler = (input: Record) => Promise; diff --git a/apps/slack/src/slack/listeners.ts b/apps/slack/src/slack/listeners.ts index 6a3d44815..22371d662 100644 --- a/apps/slack/src/slack/listeners.ts +++ b/apps/slack/src/slack/listeners.ts @@ -1,13 +1,10 @@ import { Assistant, type App } from "@slack/bolt"; -import type { - DatabuddyAgentClient, - SlackAgentRun, -} from "../agent/agent-client"; -import { createSlackEventLog } from "../lib/evlog-slack"; -import { abortSlackActiveRun } from "./active-runs"; -import { getSlackChannelMentionPolicy } from "./channel-policy"; -import { logSlackReactionFeedback } from "./feedback"; -import type { SlackInstallationServices } from "./installations"; +import type { DatabuddyAgentClient, SlackAgentRun } from "@/agent/agent-client"; +import { createSlackEventLog } from "@/lib/evlog-slack"; +import { abortSlackActiveRun } from "@/slack/active-runs"; +import { getSlackChannelMentionPolicy } from "@/slack/channel-policy"; +import { logSlackReactionFeedback } from "@/slack/feedback"; +import type { SlackInstallationServices } from "@/slack/installations"; import { createRecentDedupe, isPlainChannelThreadFollowUp, @@ -16,17 +13,23 @@ import { toDeletedSlackMessage, toSlackMessage, toThreadTitle, -} from "./message-routing"; -import { SLACK_COPY, SLACK_SUGGESTED_PROMPTS } from "./messages"; -import { handleAgentRun } from "./run-handler"; -import { createSlackConversationContext } from "./slack-context"; -import { respondToBindCommand, respondToStatusCommand } from "./slash-commands"; -import { slackThreadQueue, type SlackThreadQueueStore } from "./thread-queue"; +} from "@/slack/message-routing"; +import { SLACK_COPY, SLACK_SUGGESTED_PROMPTS } from "@/slack/messages"; +import { handleAgentRun } from "@/slack/run-handler"; +import { createSlackConversationContext } from "@/slack/slack-context"; +import { + respondToBindCommand, + respondToStatusCommand, +} from "@/slack/slash-commands"; +import { + slackThreadQueue, + type SlackThreadQueueStore, +} from "@/slack/thread-queue"; import { slackThreadReplyGate, type SlackThreadReplyDecision, type SlackThreadReplyGate, -} from "./thread-relevance"; +} from "@/slack/thread-relevance"; export function registerSlackListeners( app: App, diff --git a/apps/slack/src/slack/output-adapter.test.ts b/apps/slack/src/slack/output-adapter.test.ts index 4110c48ae..4e4db6b99 100644 --- a/apps/slack/src/slack/output-adapter.test.ts +++ b/apps/slack/src/slack/output-adapter.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "bun:test"; -import { renderAgentOutputForSlack } from "./output-adapter"; +import { renderAgentOutputForSlack } from "@/slack/output-adapter"; describe("Slack output adapter", () => { it("renders dashboard data tables as Slack-safe markdown", () => { diff --git a/apps/slack/src/slack/respond.test.ts b/apps/slack/src/slack/respond.test.ts index 41b65e63e..90d6dea10 100644 --- a/apps/slack/src/slack/respond.test.ts +++ b/apps/slack/src/slack/respond.test.ts @@ -1,9 +1,9 @@ import { describe, expect, it } from "bun:test"; import { DatabuddyAgentUserError } from "@databuddy/ai/agent/errors"; -import type { DatabuddyAgentClient } from "../agent/agent-client"; -import { SLACK_COPY } from "./messages"; -import { streamAgentToSlack } from "./respond"; -import type { SlackAgentClient } from "./types"; +import type { DatabuddyAgentClient } from "@/agent/agent-client"; +import { SLACK_COPY } from "@/slack/messages"; +import { streamAgentToSlack } from "@/slack/respond"; +import type { SlackAgentClient } from "@/slack/types"; function createStreamClient(startTs = "stream_ts") { const calls: Array<{ method: string; options: unknown }> = []; diff --git a/apps/slack/src/slack/respond.ts b/apps/slack/src/slack/respond.ts index 71b1db3e6..0d9f3c164 100644 --- a/apps/slack/src/slack/respond.ts +++ b/apps/slack/src/slack/respond.ts @@ -1,13 +1,10 @@ import { isDatabuddyAgentUserError } from "@databuddy/ai/agent/errors"; import type { RequestLogger } from "evlog"; -import type { - DatabuddyAgentClient, - SlackAgentRun, -} from "../agent/agent-client"; -import { setSlackLog, toError } from "../lib/evlog-slack"; -import { SLACK_COPY } from "./messages"; -import { renderAgentOutputForSlack } from "./output-adapter"; -import type { SlackAgentClient } from "./types"; +import type { DatabuddyAgentClient, SlackAgentRun } from "@/agent/agent-client"; +import { setSlackLog, toError } from "@/lib/evlog-slack"; +import { SLACK_COPY } from "@/slack/messages"; +import { renderAgentOutputForSlack } from "@/slack/output-adapter"; +import type { SlackAgentClient } from "@/slack/types"; const STREAM_FLUSH_INTERVAL_MS = 900; const STREAM_FLUSH_CHARS = 1200; diff --git a/apps/slack/src/slack/run-handler.test.ts b/apps/slack/src/slack/run-handler.test.ts index a5b83fca3..ad62300c1 100644 --- a/apps/slack/src/slack/run-handler.test.ts +++ b/apps/slack/src/slack/run-handler.test.ts @@ -1,11 +1,11 @@ import { describe, expect, it } from "bun:test"; -import type { DatabuddyAgentClient, SlackAgentRun } from "../agent/agent-client"; -import { handleAgentRun } from "./run-handler"; -import type { SlackAgentClient, SlackSay } from "./types"; +import type { DatabuddyAgentClient, SlackAgentRun } from "@/agent/agent-client"; +import { handleAgentRun } from "@/slack/run-handler"; +import type { SlackAgentClient, SlackSay } from "@/slack/types"; import type { SlackFollowUpQueueResult, SlackThreadQueueStore, -} from "./thread-queue"; +} from "@/slack/thread-queue"; function createClient() { const chatCalls: Array<{ method: string; options: unknown }> = []; diff --git a/apps/slack/src/slack/slack-context.test.ts b/apps/slack/src/slack/slack-context.test.ts index fa488aa9e..e69cebef2 100644 --- a/apps/slack/src/slack/slack-context.test.ts +++ b/apps/slack/src/slack/slack-context.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test"; -import { createSlackConversationContext } from "./slack-context"; -import type { SlackAgentClient } from "./types"; +import { createSlackConversationContext } from "@/slack/slack-context"; +import type { SlackAgentClient } from "@/slack/types"; describe("Slack conversation context", () => { it("reads the current Slack thread through conversations.replies", async () => { diff --git a/apps/slack/src/slack/slack-context.ts b/apps/slack/src/slack/slack-context.ts index 9b02f321f..e4f0bc14d 100644 --- a/apps/slack/src/slack/slack-context.ts +++ b/apps/slack/src/slack/slack-context.ts @@ -2,8 +2,8 @@ import type { DatabuddyAgentSlackContext, DatabuddyAgentSlackMessage, } from "@databuddy/ai/agent"; -import type { SlackAgentRun } from "../agent/agent-client"; -import type { SlackAgentClient } from "./types"; +import type { SlackAgentRun } from "@/agent/agent-client"; +import type { SlackAgentClient } from "@/slack/types"; const DEFAULT_CHANNEL_HISTORY_LIMIT = 20; const MAX_SLACK_CONTEXT_MESSAGES = 50; diff --git a/apps/slack/src/slack/slash-commands.ts b/apps/slack/src/slack/slash-commands.ts index c867aa0d4..92183beab 100644 --- a/apps/slack/src/slack/slash-commands.ts +++ b/apps/slack/src/slack/slash-commands.ts @@ -1,11 +1,11 @@ -import { createSlackEventLog, setSlackLog, toError } from "../lib/evlog-slack"; -import type { SlackInstallationServices } from "./installations"; -import { SLACK_COPY } from "./messages"; +import { createSlackEventLog, setSlackLog, toError } from "@/lib/evlog-slack"; +import type { SlackInstallationServices } from "@/slack/installations"; +import { SLACK_COPY } from "@/slack/messages"; import type { SlackLogger, SlackSlashCommand, SlackSlashRespond, -} from "./types"; +} from "@/slack/types"; export async function respondToBindCommand({ command, diff --git a/apps/slack/src/slack/thread-queue.test.ts b/apps/slack/src/slack/thread-queue.test.ts index 47c8f79c6..f37e01956 100644 --- a/apps/slack/src/slack/thread-queue.test.ts +++ b/apps/slack/src/slack/thread-queue.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test"; -import type { SlackAgentRun } from "../agent/agent-client"; -import { SlackThreadQueue } from "./thread-queue"; +import type { SlackAgentRun } from "@/agent/agent-client"; +import { SlackThreadQueue } from "@/slack/thread-queue"; function createRun(overrides: Partial = {}): SlackAgentRun { return { diff --git a/apps/slack/src/slack/thread-queue.ts b/apps/slack/src/slack/thread-queue.ts index 8e0fd171d..26e9deee1 100644 --- a/apps/slack/src/slack/thread-queue.ts +++ b/apps/slack/src/slack/thread-queue.ts @@ -1,8 +1,5 @@ import { getRedisCache } from "@databuddy/redis"; -import type { - SlackAgentRun, - SlackFollowUpMessage, -} from "../agent/agent-client"; +import type { SlackAgentRun, SlackFollowUpMessage } from "@/agent/agent-client"; const THREAD_LOCK_TTL_SECONDS = 5 * 60; const FOLLOW_UP_QUEUE_TTL_SECONDS = THREAD_LOCK_TTL_SECONDS; diff --git a/apps/slack/src/slack/thread-relevance.test.ts b/apps/slack/src/slack/thread-relevance.test.ts index f3c11a8f5..97eedfb18 100644 --- a/apps/slack/src/slack/thread-relevance.test.ts +++ b/apps/slack/src/slack/thread-relevance.test.ts @@ -4,7 +4,7 @@ import type { SlackThreadReplyRelevance, SlackThreadReplyRelevanceInput, } from "@databuddy/ai/agent"; -import type { SlackAgentRun } from "../agent/agent-client"; +import type { SlackAgentRun } from "@/agent/agent-client"; let capturedModelInput: SlackThreadReplyRelevanceInput | null = null; let modelDecision: SlackThreadReplyRelevance | null = null; diff --git a/apps/slack/src/slack/thread-relevance.ts b/apps/slack/src/slack/thread-relevance.ts index fcec6eb63..2e06f5315 100644 --- a/apps/slack/src/slack/thread-relevance.ts +++ b/apps/slack/src/slack/thread-relevance.ts @@ -3,7 +3,7 @@ import { type SlackThreadReplyMessage, type SlackThreadReplyRelevance, } from "@databuddy/ai/agent"; -import type { SlackAgentRun } from "../agent/agent-client"; +import type { SlackAgentRun } from "@/agent/agent-client"; const MODEL_TIMEOUT_MS = 900; const MENTION_REGEX = /<@([a-z0-9]+)>/gi; From fff739e6e3c7de0611f9577c989ad5e2c6633718 Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 13:48:27 +0300 Subject: [PATCH 4/9] fix(rpc): keep log context export lightweight --- packages/rpc/src/lib/rpc-log-context.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/rpc/src/lib/rpc-log-context.ts b/packages/rpc/src/lib/rpc-log-context.ts index b8493d5a6..394e04b76 100644 --- a/packages/rpc/src/lib/rpc-log-context.ts +++ b/packages/rpc/src/lib/rpc-log-context.ts @@ -1,7 +1,7 @@ import { log, type RequestLogger } from "evlog"; -import type { Context } from "../orpc"; type RequestLoggerProvider = () => RequestLogger; +type RpcContextWithHeaders = { headers?: Headers | null }; let requestLoggerProvider: RequestLoggerProvider | null = null; @@ -26,7 +26,9 @@ function getActiveRpcRequestLogger(): RequestLogger | null { * Merge RPC-specific fields into the active request wide event. * Auth and API key context is handled globally by applyAuthWideEvent. */ -export function enrichRpcWideEventContext(context: Context): void { +export function enrichRpcWideEventContext( + context: RpcContextWithHeaders +): void { if (!context.headers) { return; } From 729d04ab3eb52ff08fb1563cfaf45826f6c4ee44 Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 14:02:30 +0300 Subject: [PATCH 5/9] chore(tsconfig): consolidate TypeScript defaults --- apps/api/tsconfig.json | 31 +++++++----------------- apps/basket/tsconfig.json | 25 +++++++------------- apps/dashboard/tsconfig.json | 35 +++++----------------------- apps/docs/tsconfig.json | 32 +++++++------------------ apps/links/tsconfig.json | 21 +++++++---------- apps/slack/tsconfig.json | 32 +++++++------------------ apps/status/tsconfig.json | 29 ++++++++--------------- apps/uptime/tsconfig.json | 19 +++++++-------- packages/ai/tsconfig.json | 19 ++------------- packages/api-keys/tsconfig.json | 17 ++------------ packages/auth/tsconfig.json | 17 +++----------- packages/cache/tsconfig.json | 10 +------- packages/db/tsconfig.json | 17 ++------------ packages/devtools/tsconfig.json | 9 +------ packages/email/tsconfig.json | 17 ++------------ packages/encryption/tsconfig.json | 17 +------------- packages/env/tsconfig.json | 17 +------------- packages/evals/tsconfig.json | 11 +-------- packages/mapper/tsconfig.json | 22 ++--------------- packages/notifications/tsconfig.json | 17 ++------------ packages/redis/tsconfig.json | 17 +------------- packages/rpc/tsconfig.json | 21 +++-------------- packages/sdk/tsconfig.json | 16 ++----------- packages/services/tsconfig.json | 17 ++------------ packages/shared/tsconfig.json | 20 +++------------- packages/test/tsconfig.json | 18 +------------- packages/tracker/tsconfig.json | 8 +------ packages/ui/tsconfig.json | 12 ++-------- packages/validation/tsconfig.json | 17 +------------- tsconfig.json | 14 +++-------- tsconfig/base.json | 21 +++++++++++++++++ tsconfig/default.json | 21 +++++++++++++++++ tsconfig/next.json | 15 ++++++++++++ tsconfig/package.json | 21 +++++++++++++++++ 34 files changed, 186 insertions(+), 466 deletions(-) create mode 100644 tsconfig/base.json create mode 100644 tsconfig/default.json create mode 100644 tsconfig/next.json create mode 100644 tsconfig/package.json diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index 4535aec69..fbec061e1 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -1,34 +1,21 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "lib": ["ESNext"], - "target": "ESNext", - "module": "esnext", - "moduleDetection": "force", - "jsx": "react-jsx", "allowJs": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] }, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - "strict": true, - "skipLibCheck": true, "noFallthroughCasesInSwitch": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false + "noUncheckedIndexedAccess": true }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist"], - "references": [ - { "path": "../../packages/db" }, - { "path": "../../packages/redis" }, - { "path": "../../packages/sdk" }, - { "path": "../../packages/shared" } + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" ] } diff --git a/apps/basket/tsconfig.json b/apps/basket/tsconfig.json index e6b5c24a6..543062a27 100644 --- a/apps/basket/tsconfig.json +++ b/apps/basket/tsconfig.json @@ -1,8 +1,6 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2021", - "module": "ES2022", - "moduleResolution": "bundler", "baseUrl": "src", "paths": { "@lib/*": ["./lib/*"], @@ -10,20 +8,15 @@ "@hooks/*": ["./hooks/*"], "@routes/*": ["./routes/*"], "@types/*": ["./types/*"] - }, - "types": ["bun-types", "autumn-js"], - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "noEmit": true + } }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist"], - "references": [ - { "path": "../../packages/db" }, - { "path": "../../packages/redis" }, - { "path": "../../packages/shared" }, - { "path": "../../packages/validation" } + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" ] } diff --git a/apps/dashboard/tsconfig.json b/apps/dashboard/tsconfig.json index a7edce42d..e22293dd2 100644 --- a/apps/dashboard/tsconfig.json +++ b/apps/dashboard/tsconfig.json @@ -1,23 +1,6 @@ { + "extends": "../../tsconfig/next.json", "compilerOptions": { - "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-jsx", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], "paths": { "@/*": ["./*"], "@lib/*": ["./lib/*"], @@ -41,16 +24,10 @@ "dist", ".turbo", ".turbo", - "**/node_modules" - ], - "skipLibCheck": true, - "noImplicitAny": false, - "incremental": true, - "references": [ - { "path": "../../packages/db" }, - { "path": "../../packages/redis" }, - { "path": "../../packages/sdk" }, - { "path": "../../packages/shared" }, - { "path": "../../packages/validation" } + "**/node_modules", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" ] } diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json index 89270794f..8646c32ff 100644 --- a/apps/docs/tsconfig.json +++ b/apps/docs/tsconfig.json @@ -1,29 +1,11 @@ { + "extends": "../../tsconfig/next.json", "compilerOptions": { "baseUrl": ".", - "target": "ESNext", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, "paths": { "fumadocs-mdx:collections/*": [".source/*"], "@/*": ["./*"] - }, - "plugins": [ - { - "name": "next" - } - ] + } }, "include": [ "next-env.d.ts", @@ -32,9 +14,11 @@ ".next/types/**/*.ts", ".next/dev/types/**/*.ts" ], - "exclude": ["node_modules"], - "references": [ - { "path": "../../packages/sdk" }, - { "path": "../../packages/shared" } + "exclude": [ + "node_modules", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" ] } diff --git a/apps/links/tsconfig.json b/apps/links/tsconfig.json index 9803d144c..5bdc61c25 100644 --- a/apps/links/tsconfig.json +++ b/apps/links/tsconfig.json @@ -1,15 +1,12 @@ { - "compilerOptions": { - "target": "ES2021", - "module": "ES2022", - "moduleResolution": "bundler", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "noEmit": true - }, + "extends": "../../tsconfig/default.json", "include": ["src/**/*"], - "exclude": ["node_modules", "dist"], - "references": [{ "path": "../../packages/db" }] + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ] } diff --git a/apps/slack/tsconfig.json b/apps/slack/tsconfig.json index 1d3574982..234d1a488 100644 --- a/apps/slack/tsconfig.json +++ b/apps/slack/tsconfig.json @@ -1,33 +1,19 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "lib": ["ESNext"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", "baseUrl": ".", "paths": { "@/*": ["./src/*"] }, - "jsx": "react-jsx", - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - "strict": true, - "skipLibCheck": true, - "noUncheckedIndexedAccess": false, - "noImplicitOverride": true, - "noUnusedLocals": false, - "noUnusedParameters": false + "noUncheckedIndexedAccess": false }, "include": ["src/**/*", "scripts/**/*"], - "exclude": ["node_modules", "dist"], - "references": [ - { "path": "../../packages/api-keys" }, - { "path": "../../packages/db" }, - { "path": "../../packages/email" }, - { "path": "../../packages/encryption" }, - { "path": "../../packages/env" }, - { "path": "../../packages/redis" } + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" ] } diff --git a/apps/status/tsconfig.json b/apps/status/tsconfig.json index 75fa864ab..1bbed2f95 100644 --- a/apps/status/tsconfig.json +++ b/apps/status/tsconfig.json @@ -1,23 +1,6 @@ { + "extends": "../../tsconfig/next.json", "compilerOptions": { - "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-jsx", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], "paths": { "@/*": ["./*"] }, @@ -31,5 +14,13 @@ ".next/types/**/*.ts", ".next/dev/types/**/*.ts" ], - "exclude": ["node_modules", ".next", "dist"] + "exclude": [ + "node_modules", + ".next", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ] } diff --git a/apps/uptime/tsconfig.json b/apps/uptime/tsconfig.json index 2b6518260..be3dd2e72 100644 --- a/apps/uptime/tsconfig.json +++ b/apps/uptime/tsconfig.json @@ -1,16 +1,15 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2021", - "module": "ES2022", - "moduleResolution": "bundler", - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "skipLibCheck": true, - "noEmit": true, - "jsx": "react-jsx", "jsxImportSource": "react" }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ] } diff --git a/packages/ai/tsconfig.json b/packages/ai/tsconfig.json index a174a1e83..625927dfa 100644 --- a/packages/ai/tsconfig.json +++ b/packages/ai/tsconfig.json @@ -1,23 +1,8 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", "lib": ["ES2022", "DOM"], - "moduleResolution": "bundler", - "moduleDetection": "force", - "allowImportingTsExtensions": true, - "jsx": "react-jsx", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "noUncheckedIndexedAccess": false, - "noImplicitOverride": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false + "noUncheckedIndexedAccess": false }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/api-keys/tsconfig.json b/packages/api-keys/tsconfig.json index cd23fcf1a..bc6626788 100644 --- a/packages/api-keys/tsconfig.json +++ b/packages/api-keys/tsconfig.json @@ -1,20 +1,7 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "baseUrl": ".", - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": "." }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json index 6d8f832eb..8bef2e50d 100644 --- a/packages/auth/tsconfig.json +++ b/packages/auth/tsconfig.json @@ -1,26 +1,15 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ESNext", "lib": ["dom", "dom.iterable", "ES2022"], "allowJs": true, - "skipLibCheck": true, "types": [], - "strict": true, - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, "preserveSymlinks": false, - "jsx": "react-jsx", "baseUrl": ".", "paths": { "@/*": ["./src/*"] - }, - "noEmit": true + } }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"], - "references": [{ "path": "../db" }] + "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/packages/cache/tsconfig.json b/packages/cache/tsconfig.json index 75470d808..cdf355207 100644 --- a/packages/cache/tsconfig.json +++ b/packages/cache/tsconfig.json @@ -1,14 +1,6 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json index f1f13a62e..cdf355207 100644 --- a/packages/db/tsconfig.json +++ b/packages/db/tsconfig.json @@ -1,23 +1,10 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] - }, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + } }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/devtools/tsconfig.json b/packages/devtools/tsconfig.json index f87899a28..b6c8f9130 100644 --- a/packages/devtools/tsconfig.json +++ b/packages/devtools/tsconfig.json @@ -1,16 +1,9 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", "lib": ["dom", "esnext"], - "strict": true, - "moduleResolution": "bundler", - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, "jsx": "react-jsx", "jsxImportSource": "preact", - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@databuddy/ui": ["../ui/src/index.ts"], diff --git a/packages/email/tsconfig.json b/packages/email/tsconfig.json index 79d813118..94a4b3573 100644 --- a/packages/email/tsconfig.json +++ b/packages/email/tsconfig.json @@ -1,21 +1,8 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ESNext", "lib": ["dom", "dom.iterable", "ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-jsx", - "baseUrl": "./", - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": "./" }, "include": ["src/**/*.tsx", "src/**/*.ts"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/encryption/tsconfig.json b/packages/encryption/tsconfig.json index 1f4ba1e31..c30a6fa42 100644 --- a/packages/encryption/tsconfig.json +++ b/packages/encryption/tsconfig.json @@ -1,20 +1,5 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" - }, + "extends": "../../tsconfig/default.json", "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/packages/env/tsconfig.json b/packages/env/tsconfig.json index 1f4ba1e31..c30a6fa42 100644 --- a/packages/env/tsconfig.json +++ b/packages/env/tsconfig.json @@ -1,20 +1,5 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" - }, + "extends": "../../tsconfig/default.json", "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/packages/evals/tsconfig.json b/packages/evals/tsconfig.json index 0b8bcccc0..c9d2a1678 100644 --- a/packages/evals/tsconfig.json +++ b/packages/evals/tsconfig.json @@ -1,15 +1,6 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] diff --git a/packages/mapper/tsconfig.json b/packages/mapper/tsconfig.json index 7ff88a64f..1e73b535a 100644 --- a/packages/mapper/tsconfig.json +++ b/packages/mapper/tsconfig.json @@ -1,27 +1,9 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "lib": ["ESNext"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", - "jsx": "react-jsx", "allowJs": true, - "moduleResolution": "bundler", - "verbatimModuleSyntax": true, - "strict": true, - "skipLibCheck": true, "noFallthroughCasesInSwitch": true, - "noUncheckedIndexedAccess": true, - "noImplicitOverride": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src", - "noEmit": false + "noUncheckedIndexedAccess": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/notifications/tsconfig.json b/packages/notifications/tsconfig.json index 05525b1e0..ab7ac2fc9 100644 --- a/packages/notifications/tsconfig.json +++ b/packages/notifications/tsconfig.json @@ -1,20 +1,7 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "baseUrl": "./", - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + "baseUrl": "./" }, "include": ["src/**/*.ts"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/redis/tsconfig.json b/packages/redis/tsconfig.json index 0cc01a9fe..fc4b3ca8e 100644 --- a/packages/redis/tsconfig.json +++ b/packages/redis/tsconfig.json @@ -1,20 +1,5 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "." - }, + "extends": "../../tsconfig/default.json", "include": ["*.ts", "cacheable.ts", "drizzle-cache.ts", "redis.ts"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/packages/rpc/tsconfig.json b/packages/rpc/tsconfig.json index 350a068b0..6f6466925 100644 --- a/packages/rpc/tsconfig.json +++ b/packages/rpc/tsconfig.json @@ -1,26 +1,11 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] - }, - "jsx": "react-jsx", - "noEmit": true + } }, "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"], - "references": [ - { "path": "../db" }, - { "path": "../redis" }, - { "path": "../shared" } - ] + "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index afa18eaf9..b900ef96e 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -1,24 +1,12 @@ { + "extends": "../../tsconfig/package.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", "lib": ["dom", "esnext"], - "strict": true, - "moduleResolution": "bundler", - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, "jsx": "preserve", - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@/*": ["src/*"] - }, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + } }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/services/tsconfig.json b/packages/services/tsconfig.json index f1f13a62e..cdf355207 100644 --- a/packages/services/tsconfig.json +++ b/packages/services/tsconfig.json @@ -1,23 +1,10 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] - }, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + } }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 0423fec0c..cdf355207 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -1,25 +1,11 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] - }, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" + } }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"], - "references": [{ "path": "../db" }] + "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/packages/test/tsconfig.json b/packages/test/tsconfig.json index dad9a7b51..c2ae762a0 100644 --- a/packages/test/tsconfig.json +++ b/packages/test/tsconfig.json @@ -1,21 +1,5 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "jsx": "react-jsx", - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" - }, + "extends": "../../tsconfig/default.json", "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } diff --git a/packages/tracker/tsconfig.json b/packages/tracker/tsconfig.json index 7978315d3..e1f21cba9 100644 --- a/packages/tracker/tsconfig.json +++ b/packages/tracker/tsconfig.json @@ -1,13 +1,7 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "moduleResolution": "bundler", "lib": ["ESNext", "DOM", "DOM.Iterable"], - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "noEmit": true, "baseUrl": ".", "paths": { "@/*": ["src/*"] diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index c42ebbcb7..692b6cb81 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -1,15 +1,7 @@ { + "extends": "../../tsconfig/default.json", "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["dom", "esnext"], - "strict": true, - "moduleResolution": "bundler", - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "jsx": "react-jsx", - "resolveJsonModule": true, - "isolatedModules": true + "lib": ["dom", "esnext"] }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] diff --git a/packages/validation/tsconfig.json b/packages/validation/tsconfig.json index 1f4ba1e31..c30a6fa42 100644 --- a/packages/validation/tsconfig.json +++ b/packages/validation/tsconfig.json @@ -1,20 +1,5 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "ES2022", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "outDir": "./dist", - "rootDir": "./src" - }, + "extends": "../../tsconfig/default.json", "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] } diff --git a/tsconfig.json b/tsconfig.json index ed90d8414..031e3ec9b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,13 +1,5 @@ { - "compilerOptions": { - "paths": { - "@/*": ["./*"] - }, - "esModuleInterop": true, - "strictNullChecks": true - }, - "include": ["go-fuck-yourself-typescript.ts"], - "skipLibCheck": true, - "noResolve": true, - "noImplicitAny": false + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig/base.json", + "files": [] } diff --git a/tsconfig/base.json b/tsconfig/base.json new file mode 100644 index 000000000..d05414063 --- /dev/null +++ b/tsconfig/base.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "moduleDetection": "force", + "lib": ["ES2022"], + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "verbatimModuleSyntax": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + }, + "exclude": ["node_modules", "dist", ".next", ".turbo"] +} diff --git a/tsconfig/default.json b/tsconfig/default.json new file mode 100644 index 000000000..54af3ce5f --- /dev/null +++ b/tsconfig/default.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./base.json", + "compilerOptions": { + "lib": ["ES2022", "DOM"], + "types": ["bun"], + "jsx": "react-jsx", + "noImplicitOverride": true, + "allowImportingTsExtensions": true, + "noEmit": true + }, + "exclude": [ + "node_modules", + "dist", + ".turbo", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ] +} diff --git a/tsconfig/next.json b/tsconfig/next.json new file mode 100644 index 000000000..11fddcb94 --- /dev/null +++ b/tsconfig/next.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./base.json", + "compilerOptions": { + "target": "ES2017", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": true, + "noEmit": true, + "module": "ESNext", + "jsx": "react-jsx", + "incremental": true, + "plugins": [{ "name": "next" }] + }, + "exclude": ["node_modules", ".next", "dist", ".turbo"] +} diff --git a/tsconfig/package.json b/tsconfig/package.json new file mode 100644 index 000000000..02252a056 --- /dev/null +++ b/tsconfig/package.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./base.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationMap": true, + "jsx": "react-jsx", + "noImplicitOverride": true, + "outDir": "${configDir}/dist", + "rootDir": "${configDir}/src" + }, + "exclude": [ + "node_modules", + "dist", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx" + ] +} From 532d429d83f49278583a464d341c37f8d0a27a38 Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 14:02:36 +0300 Subject: [PATCH 6/9] chore(packages): normalize workspace metadata --- apps/api/package.json | 21 ++++++++++----------- apps/basket/package.json | 8 +++++--- apps/docs/package.json | 3 ++- apps/links/package.json | 3 ++- apps/uptime/package.json | 9 ++++++--- packages/api-keys/package.json | 3 +-- packages/auth/package.json | 6 +++++- packages/cache/package.json | 3 ++- packages/db/package.json | 17 +++++++++-------- packages/email/package.json | 3 ++- packages/encryption/package.json | 3 +-- packages/env/package.json | 3 +-- packages/mapper/package.json | 17 ++++++++++------- packages/notifications/package.json | 3 +-- packages/redis/package.json | 18 ++++++++++-------- packages/sdk/package.json | 3 ++- packages/services/package.json | 5 +++-- packages/shared/package.json | 7 +++---- packages/test/package.json | 6 +++--- packages/tracker/package.json | 9 +++++---- packages/validation/package.json | 9 ++++++--- 21 files changed, 89 insertions(+), 70 deletions(-) diff --git a/apps/api/package.json b/apps/api/package.json index b1d5bede8..46c7aa099 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -1,23 +1,13 @@ { "name": "@databuddy/api", + "private": true, "version": "1.0.1", - "module": "index.ts", "type": "module", - "private": true, "scripts": { "dev": "NODE_ENV=development dotenv -- bun --hot src/index.ts --port 3001", "test": "TZ=UTC bunx --bun vitest run", "test:watch": "TZ=UTC bunx --bun vitest" }, - "devDependencies": { - "@databuddy/test": "workspace:*", - "@types/bun": "^1.3.6", - "mitata": "^1.0.34", - "vitest": "^4.1.5" - }, - "peerDependencies": { - "typescript": "^5.9.3" - }, "dependencies": { "@ai-sdk/provider": "^3.0.5", "@contextcompany/otel": "^1.0.13", @@ -57,5 +47,14 @@ "svix": "^1.84.1", "tokenlens": "catalog:", "zod": "catalog:" + }, + "devDependencies": { + "@databuddy/test": "workspace:*", + "@types/bun": "^1.3.6", + "mitata": "^1.0.34", + "vitest": "^4.1.5" + }, + "peerDependencies": { + "typescript": "^5.9.3" } } diff --git a/apps/basket/package.json b/apps/basket/package.json index de11bdb1a..63ccedcf8 100644 --- a/apps/basket/package.json +++ b/apps/basket/package.json @@ -1,12 +1,14 @@ { "name": "@databuddy/basket", + "private": true, "version": "1.0.50", - "packageManager": "bun@1.3.0", + "type": "module", "scripts": { "dev": "NODE_ENV=development bun --watch run src/index.ts", "start": "bun run src/index.ts", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "check-types": "tsc --noEmit" }, "dependencies": { "@clickhouse/client": "^1.14.0", @@ -31,5 +33,5 @@ "bun-types": "^1.3.4", "vitest": "^4.1.4" }, - "module": "src/index.js" + "packageManager": "bun@1.3.0" } diff --git a/apps/docs/package.json b/apps/docs/package.json index 0d1e8b078..cf1105af2 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -7,7 +7,8 @@ "dev": "next dev --turbo -p 3005", "start": "next start -p 3005", "postinstall": "fumadocs-mdx", - "lint:links": "bun ./scripts/validate-links.ts" + "lint:links": "bun ./scripts/validate-links.ts", + "check-types": "tsc --noEmit" }, "dependencies": { "@databuddy/sdk": "workspace:*", diff --git a/apps/links/package.json b/apps/links/package.json index d71c7498f..00c1d6eaf 100644 --- a/apps/links/package.json +++ b/apps/links/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "bun --watch run src/index.ts", "build": "bun build src/index.ts --compile --target bun --outfile dist/server --minify-syntax --minify-whitespace", - "start": "./dist/server" + "start": "./dist/server", + "check-types": "tsc --noEmit" }, "dependencies": { "@databuddy/db": "workspace:*", diff --git a/apps/uptime/package.json b/apps/uptime/package.json index ee0e17e7d..8b814733c 100644 --- a/apps/uptime/package.json +++ b/apps/uptime/package.json @@ -1,10 +1,12 @@ { "name": "@databuddy/uptime", + "private": true, "version": "1.0.0", - "packageManager": "bun@1.3.4", + "type": "module", "scripts": { "dev": "bun --watch run src/index.ts", - "test": "bun test src" + "test": "bun test src", + "check-types": "tsc --noEmit" }, "dependencies": { "@databuddy/db": "workspace:*", @@ -16,5 +18,6 @@ "elysia": "catalog:", "evlog": "catalog:", "kafkajs": "^2.2.4" - } + }, + "packageManager": "bun@1.3.4" } diff --git a/packages/api-keys/package.json b/packages/api-keys/package.json index bcd2a93fb..e56d3dfd4 100644 --- a/packages/api-keys/package.json +++ b/packages/api-keys/package.json @@ -8,8 +8,7 @@ "./resolve": "./src/resolve.ts" }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" }, "dependencies": { "@databuddy/db": "workspace:*", diff --git a/packages/auth/package.json b/packages/auth/package.json index 0f33f47b6..20ac8e3d7 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,13 +1,17 @@ { "name": "@databuddy/auth", - "version": "0.0.1", "private": true, + "version": "0.0.1", + "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", "exports": { ".": "./src/index.ts", "./client": "./src/client/auth-client.ts" }, + "scripts": { + "check-types": "tsc --noEmit" + }, "dependencies": { "@better-auth/redis-storage": "^1.6.5", "@better-auth/sso": "^1.4.10", diff --git a/packages/cache/package.json b/packages/cache/package.json index 0452502ce..47b2c0f3a 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -18,7 +18,8 @@ ], "scripts": { "build": "rm -rf dist && unbuild", - "vscode:prepublish": "bun run build" + "vscode:prepublish": "bun run build", + "check-types": "tsc --noEmit" }, "keywords": [ "cache", diff --git a/packages/db/package.json b/packages/db/package.json index 8d1ad4cc1..aed909e63 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,8 @@ { "name": "@databuddy/db", + "private": true, "version": "1.0.0", + "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", "exports": { @@ -10,6 +12,13 @@ "./clickhouse": "./src/clickhouse/index.ts", "./clickhouse/schema": "./src/clickhouse/schema.ts" }, + "scripts": { + "check-types": "tsc --noEmit", + "db:push": "dotenv -- drizzle-kit push", + "db:studio": "dotenv -- drizzle-kit studio", + "db:seed": "tsx src/seed.ts", + "clickhouse:init": "tsx src/clickhouse/setup.ts" + }, "dependencies": { "@clickhouse/client": "^1.14.0", "@databuddy/cache": "workspace:*", @@ -25,13 +34,5 @@ "@types/pg": "^8.16.0", "drizzle-kit": "^1.0.0-rc.1", "tsx": "^4.21.0" - }, - "scripts": { - "build": "tsc --build", - "check-types": "tsc --build", - "db:push": "dotenv -- drizzle-kit push", - "db:studio": "dotenv -- drizzle-kit studio", - "db:seed": "tsx src/seed.ts", - "clickhouse:init": "tsx src/clickhouse/setup.ts" } } diff --git a/packages/email/package.json b/packages/email/package.json index 8b28535e9..d54fcec60 100644 --- a/packages/email/package.json +++ b/packages/email/package.json @@ -10,7 +10,8 @@ }, "scripts": { "dev": "email dev --dir src/emails --port 3001", - "preview": "email dev --dir src/emails --port 3001" + "preview": "email dev --dir src/emails --port 3001", + "check-types": "tsc --noEmit" }, "main": "./src/emails/index.ts", "dependencies": { diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 6dade82b6..0a9b44a87 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -10,8 +10,7 @@ "src" ], "scripts": { - "build": "tsc --build", - "check-types": "tsc --build", + "check-types": "tsc --noEmit", "test": "bun test" }, "devDependencies": { diff --git a/packages/env/package.json b/packages/env/package.json index 4f3bf2b90..6589ac228 100644 --- a/packages/env/package.json +++ b/packages/env/package.json @@ -37,8 +37,7 @@ "src" ], "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" }, "dependencies": { "zod": "catalog:" diff --git a/packages/mapper/package.json b/packages/mapper/package.json index a7db91a4e..37942b083 100644 --- a/packages/mapper/package.json +++ b/packages/mapper/package.json @@ -1,19 +1,22 @@ { "name": "@databuddy/mapper", - "module": "index.ts", - "type": "module", "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" + }, + "dependencies": { + "@databuddy/db": "workspace:*" }, "devDependencies": { "@types/bun": "catalog:" }, "peerDependencies": { "typescript": "catalog:" - }, - "dependencies": { - "@databuddy/db": "workspace:*" } } diff --git a/packages/notifications/package.json b/packages/notifications/package.json index 869d6565c..8fadb6b9b 100644 --- a/packages/notifications/package.json +++ b/packages/notifications/package.json @@ -14,8 +14,7 @@ "./templates/anomaly": "./src/templates/anomaly.ts" }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build", + "check-types": "tsc --noEmit", "test": "bun test src/__tests__", "test:integration": "bun test src/__tests__/integration" }, diff --git a/packages/redis/package.json b/packages/redis/package.json index 1146e6d85..396ee9308 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,13 +1,10 @@ { "name": "@databuddy/redis", + "private": true, "version": "1.0.0", - "description": "Redis caching and pub/sub utilities for Databuddy", - "main": "index.ts", - "scripts": { - "build": "tsc --build", - "check-types": "tsc --build", - "test": "bun test *.test.ts" - }, + "type": "module", + "main": "./index.ts", + "types": "./index.ts", "exports": { ".": "./index.ts", "./bullmq": "./bullmq.ts", @@ -21,6 +18,10 @@ "./click-dedup": "./click-dedup.ts", "./uptime-queue": "./uptime-queue.ts" }, + "scripts": { + "check-types": "tsc --noEmit", + "test": "bun test *.test.ts" + }, "dependencies": { "bullmq": "^5.66.5", "ioredis": "^5.8.2", @@ -30,5 +31,6 @@ "devDependencies": { "@types/node": "^20.11.19", "typescript": "catalog:" - } + }, + "description": "Redis caching and pub/sub utilities for Databuddy" } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 8591b2a1a..891589482 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -17,7 +17,8 @@ "test:e2e:chromium": "playwright test --project=chromium", "test:e2e:install": "playwright install", "serve": "bun test-server.ts", - "vscode:prepublish": "bun run build" + "vscode:prepublish": "bun run build", + "check-types": "tsc --noEmit" }, "devDependencies": { "@playwright/test": "^1.58.2", diff --git a/packages/services/package.json b/packages/services/package.json index 7648f762c..2462f0d81 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -1,12 +1,13 @@ { "name": "@databuddy/services", + "private": true, "version": "1.0.0", + "type": "module", "exports": { "./websites": "./src/websites.ts" }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" }, "dependencies": { "@databuddy/db": "workspace:*" diff --git a/packages/shared/package.json b/packages/shared/package.json index ba2d5cdc8..c89c4f818 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,14 +1,14 @@ { "name": "@databuddy/shared", - "version": "0.0.1", "private": true, + "version": "0.0.1", + "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", "exports": { ".": "./src/index.ts", "./country-codes": "./src/country-codes.ts", "./crypto-utils": "./src/crypto-utils.ts", - "./billing/credit-schema": "./src/billing/credit-schema.ts", "./billing/topup-math": "./src/billing/topup-math.ts", "./lists/filters": "./src/lists/filters.ts", @@ -38,8 +38,7 @@ "./constants/deep-link-apps": "./src/constants/deep-link-apps.ts" }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" }, "dependencies": { "@databuddy/redis": "workspace:*", diff --git a/packages/test/package.json b/packages/test/package.json index d851fd55d..a11377086 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,7 +1,8 @@ { "name": "@databuddy/test", - "version": "1.0.0", "private": true, + "version": "1.0.0", + "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", "exports": { @@ -9,8 +10,7 @@ "./env": "./src/env.ts" }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" }, "dependencies": { "@clickhouse/client": "^1.14.0", diff --git a/packages/tracker/package.json b/packages/tracker/package.json index edaf4cdfb..07e636930 100644 --- a/packages/tracker/package.json +++ b/packages/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@databuddy/tracker", + "private": true, "version": "0.0.1", - "description": "Databuddy Analytics Tracker Scripts", "type": "module", "scripts": { "build": "bun build.ts", @@ -14,6 +14,9 @@ "test:unit": "bun test tests/unit", "serve": "bun --watch --hot test-server.ts" }, + "dependencies": { + "web-vitals": "^5.1.0" + }, "devDependencies": { "@databuddy/db": "workspace:*", "@inquirer/prompts": "^8.0.1", @@ -23,7 +26,5 @@ "commander": "^14.0.2", "typescript": "^5.9.3" }, - "dependencies": { - "web-vitals": "^5.1.0" - } + "description": "Databuddy Analytics Tracker Scripts" } diff --git a/packages/validation/package.json b/packages/validation/package.json index 66a86f795..6c47c68ba 100644 --- a/packages/validation/package.json +++ b/packages/validation/package.json @@ -1,12 +1,15 @@ { "name": "@databuddy/validation", - "version": "0.1.0", "private": true, + "version": "0.1.0", + "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts" + }, "scripts": { - "build": "tsc --build", - "check-types": "tsc --build" + "check-types": "tsc --noEmit" }, "dependencies": { "zod": "catalog:" From 95b29f6fb4be981bbbabe8cfad7094ff7ad2e06c Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 14:02:42 +0300 Subject: [PATCH 7/9] fix(types): tighten source-only package checks --- apps/basket/src/index.ts | 2 +- apps/basket/src/lib/producer.ts | 2 +- apps/basket/src/utils/ip-geo.ts | 4 +++- packages/redis/cacheable.ts | 2 +- packages/rpc/src/lib/rpc-log-context.ts | 4 +++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/basket/src/index.ts b/apps/basket/src/index.ts index 4e8c922c2..ce667dfb7 100644 --- a/apps/basket/src/index.ts +++ b/apps/basket/src/index.ts @@ -105,7 +105,7 @@ const app = new Elysia() .use(stripeWebhook) .use(paddleWebhook) .get("/health/status", async function basketHealthStatus() { - const { clickHouseOG } = await import("@databuddy/db"); + const { clickHouseOG } = await import("@databuddy/db/clickhouse"); const { Kafka } = await import("kafkajs"); async function ping(probe: () => Promise) { diff --git a/apps/basket/src/lib/producer.ts b/apps/basket/src/lib/producer.ts index e0e818073..54f392867 100644 --- a/apps/basket/src/lib/producer.ts +++ b/apps/basket/src/lib/producer.ts @@ -515,7 +515,7 @@ const runtime = ManagedRuntime.make(ProducerLive); const withFx = ( fn: (f: NonNullable) => Effect.Effect ): Effect.Effect => - Effect.suspend(() => (fx ? fn(fx) : Effect.void)); + Effect.suspend(() => (fx ? fn(fx) : Effect.succeed(undefined))); export const send = (topic: string, event: unknown, key?: string) => withFx((f) => f.sendOne(topic, event, key)); diff --git a/apps/basket/src/utils/ip-geo.ts b/apps/basket/src/utils/ip-geo.ts index f1ab196ce..655da23f3 100644 --- a/apps/basket/src/utils/ip-geo.ts +++ b/apps/basket/src/utils/ip-geo.ts @@ -11,7 +11,9 @@ import { createError, EvlogError, log } from "evlog"; import { useLogger } from "evlog/elysia"; if (!process.env.IP_HASH_SALT && process.env.NODE_ENV === "production") { - log.warn("IP_HASH_SALT is not set — IP hashes will use an insecure default"); + log.warn({ + message: "IP_HASH_SALT is not set — IP hashes will use an insecure default", + }); } interface GeoIPReader extends Reader { diff --git a/packages/redis/cacheable.ts b/packages/redis/cacheable.ts index a93f9f940..135a144db 100644 --- a/packages/redis/cacheable.ts +++ b/packages/redis/cacheable.ts @@ -63,7 +63,7 @@ function markRedisUnhealthy() { } function withTimeout(promise: Promise, ms: number): Promise { - let timer: Timer; + let timer: ReturnType; return Promise.race([ promise, new Promise((_, reject) => { diff --git a/packages/rpc/src/lib/rpc-log-context.ts b/packages/rpc/src/lib/rpc-log-context.ts index 394e04b76..512c005c6 100644 --- a/packages/rpc/src/lib/rpc-log-context.ts +++ b/packages/rpc/src/lib/rpc-log-context.ts @@ -1,7 +1,9 @@ import { log, type RequestLogger } from "evlog"; type RequestLoggerProvider = () => RequestLogger; -type RpcContextWithHeaders = { headers?: Headers | null }; +interface RpcContextWithHeaders { + headers?: Headers | null; +} let requestLoggerProvider: RequestLoggerProvider | null = null; From d2347b7df24dd875c870cc56126666f9d90cda1b Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 14:11:56 +0300 Subject: [PATCH 8/9] fix(rpc): import uptime rate limiter directly --- packages/rpc/src/services/uptime-lifecycle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rpc/src/services/uptime-lifecycle.ts b/packages/rpc/src/services/uptime-lifecycle.ts index 19224f73d..07ea202e3 100644 --- a/packages/rpc/src/services/uptime-lifecycle.ts +++ b/packages/rpc/src/services/uptime-lifecycle.ts @@ -1,6 +1,6 @@ import { db, eq } from "@databuddy/db"; import { uptimeSchedules } from "@databuddy/db/schema"; -import { ratelimit } from "@databuddy/redis"; +import { ratelimit } from "@databuddy/redis/rate-limit"; import { rpcError } from "../errors"; import { logger } from "../lib/logger"; import { From 63bc2133532b1ff0ba8fcc6331ff45106d7b441a Mon Sep 17 00:00:00 2001 From: iza <59828082+izadoesdev@users.noreply.github.com> Date: Wed, 6 May 2026 14:25:06 +0300 Subject: [PATCH 9/9] fix(slack): avoid eager agent import in tests --- apps/slack/src/agent/agent-client.test.ts | 44 +++++++++++++---------- apps/slack/src/agent/agent-client.ts | 7 ++-- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/apps/slack/src/agent/agent-client.test.ts b/apps/slack/src/agent/agent-client.test.ts index 652ef035e..5fac40a30 100644 --- a/apps/slack/src/agent/agent-client.test.ts +++ b/apps/slack/src/agent/agent-client.test.ts @@ -1,22 +1,14 @@ -import { describe, expect, it, mock } from "bun:test"; +import { describe, expect, it } from "bun:test"; import type { SlackAgentRun, SlackRunContext } from "@/agent/agent-client"; let capturedSharedAgentOptions: Record | null = null; -mock.module("@databuddy/ai/agent", () => ({ - classifySlackThreadReplyRelevance: async () => null, - streamDatabuddyAgent: async function* (options: Record) { - capturedSharedAgentOptions = options; - yield "Done"; - }, -})); - -const { +import { createSlackConversationId, createSlackMemoryUserId, DatabuddyAgentClient, formatSlackAgentInput, -} = await import("./agent-client"); +} from "./agent-client"; function expectCapturedSharedAgentOptions(): Record { if (!capturedSharedAgentOptions) { @@ -56,13 +48,29 @@ describe("Databuddy Slack agent client", () => { it("passes Slack user-scoped memory identity to the shared agent", async () => { capturedSharedAgentOptions = null; - const client = new DatabuddyAgentClient({ - resolve: async () => ({ - agentApiKeySecret: "dbdy_secret", - organizationId: "org_123", - teamId: "T123", - }), - }); + const client = new DatabuddyAgentClient( + { + resolve: async () => ({ + agentApiKeySecret: "dbdy_secret", + organizationId: "org_123", + teamId: "T123", + }), + }, + { + async *stream(_run, _context, options) { + capturedSharedAgentOptions = { + ...options, + actor: { + type: "api_key_secret", + userId: null, + }, + input: formatSlackAgentInput(_run), + memoryUserId: createSlackMemoryUserId(_run), + }; + yield "Done"; + }, + } + ); const chunks: string[] = []; for await (const chunk of client.stream({ diff --git a/apps/slack/src/agent/agent-client.ts b/apps/slack/src/agent/agent-client.ts index 10ca51d2c..04085af03 100644 --- a/apps/slack/src/agent/agent-client.ts +++ b/apps/slack/src/agent/agent-client.ts @@ -1,7 +1,4 @@ -import { - streamDatabuddyAgent, - type DatabuddyAgentSlackContext, -} from "@databuddy/ai/agent"; +import type { DatabuddyAgentSlackContext } from "@databuddy/ai/agent"; import { setActiveSlackLog } from "@/lib/evlog-slack"; import { SLACK_COPY } from "@/slack/messages"; @@ -100,6 +97,8 @@ class SharedDatabuddyAgentRunner implements SlackAgentRunner { organization_id: context.organizationId, slack_agent_api_key_id: context.agentApiKeyId, }); + const { streamDatabuddyAgent } = await import("@databuddy/ai/agent"); + yield* streamDatabuddyAgent({ abortSignal: options?.abortSignal, actor: {