refactor: move into api/db packages
This commit is contained in:
@@ -48,14 +48,12 @@
|
||||
"@trpc/server": "catalog:",
|
||||
"date-fns": "^4.1.0",
|
||||
"geist": "^1.3.1",
|
||||
"ioredis": "^5.9.2",
|
||||
"jose": "^6.1.2",
|
||||
"next": "15.5.9",
|
||||
"next-runtime-env": "^1.7.2",
|
||||
"next-themes": "^0.4.6",
|
||||
"nextjs-cors": "^2.2.0",
|
||||
"posthog-js": "^1.254.0",
|
||||
"rate-limiter-flexible": "^9.0.1",
|
||||
"react": "catalog:react18",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-contenteditable": "^3.3.7",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { toNodeHandler } from "better-auth/node";
|
||||
|
||||
import { initAuth } from "@kan/auth/server";
|
||||
import { createDrizzleClient } from "@kan/db/client";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export const config = { api: { bodyParser: false } };
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export default withRateLimit(
|
||||
{ points: 100, duration: 60 },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export default withRateLimit(
|
||||
{ points: 100, duration: 60 },
|
||||
|
||||
@@ -3,7 +3,7 @@ import { env } from "next-runtime-env";
|
||||
|
||||
import { createNextApiContext } from "@kan/api/trpc";
|
||||
import { createStripeClient } from "@kan/stripe";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export default withRateLimit(
|
||||
{ points: 100, duration: 60 },
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createNextApiContext } from "@kan/api/trpc";
|
||||
import * as subscriptionRepo from "@kan/db/repository/subscription.repo";
|
||||
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
|
||||
import { createStripeClient } from "@kan/stripe";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
const workspaceSlugSchema = z
|
||||
.string()
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createNextApiContext } from "@kan/api/trpc";
|
||||
import { integrations } from "@kan/db/schema";
|
||||
import { addYears } from "date-fns";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export default withRateLimit(
|
||||
{ points: 100, duration: 60 },
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createNextApiHandler } from "@trpc/server/adapters/next";
|
||||
import { appRouter } from "@kan/api/root";
|
||||
import { createTRPCContext } from "@kan/api/trpc";
|
||||
import { env } from "~/env";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
const nextApiHandler = createNextApiHandler({
|
||||
router: appRouter,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { jwtVerify } from "jose";
|
||||
import { z } from "zod";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
const requestSchema = z.object({
|
||||
token: z.string().min(1),
|
||||
|
||||
@@ -6,7 +6,7 @@ import { env as nextRuntimeEnv } from "next-runtime-env";
|
||||
import { createNextApiContext } from "@kan/api/trpc";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
const allowedContentTypes = ["image/jpeg", "image/png"];
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { appRouter } from "@kan/api";
|
||||
import { createRESTContext } from "@kan/api/trpc";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export default withRateLimit(
|
||||
{ points: 100, duration: 60 },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { openApiDocument } from "@kan/api/openapi";
|
||||
import { withRateLimit } from "~/utils/rateLimit";
|
||||
import { withRateLimit } from "@kan/api/utils/rateLimit";
|
||||
|
||||
export default withRateLimit(
|
||||
{ points: 100, duration: 60 },
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
"./openapi": {
|
||||
"types": "./dist/openapi.d.ts",
|
||||
"default": "./src/openapi.ts"
|
||||
},
|
||||
"./utils/rateLimit": {
|
||||
"types": "./dist/utils/rateLimit.d.ts",
|
||||
"default": "./src/utils/rateLimit.ts"
|
||||
}
|
||||
},
|
||||
"license": "GPL-3.0",
|
||||
@@ -43,6 +47,7 @@
|
||||
"@kan/shared": "workspace:^",
|
||||
"@kan/stripe": "workspace:^",
|
||||
"@trpc/server": "catalog:",
|
||||
"rate-limiter-flexible": "^9.0.1",
|
||||
"superjson": "2.2.1",
|
||||
"trpc-to-openapi": "^2.3.2",
|
||||
"zod": "catalog:"
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
RateLimiterMemory,
|
||||
} from "rate-limiter-flexible";
|
||||
|
||||
import { getRedisClient } from "./redis";
|
||||
import { getRedisClient } from "@kan/db/redis";
|
||||
|
||||
export interface RateLimitOptions {
|
||||
points?: number;
|
||||
@@ -13,7 +13,6 @@ export interface RateLimitOptions {
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
|
||||
const defaultIdentifier = (req: NextApiRequest): string => {
|
||||
// Try to identify the IP address of the request
|
||||
const forwardedFor = req.headers["x-forwarded-for"];
|
||||
@@ -32,7 +31,6 @@ const defaultIdentifier = (req: NextApiRequest): string => {
|
||||
return ip;
|
||||
};
|
||||
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
points: 100,
|
||||
duration: 60,
|
||||
@@ -40,7 +38,6 @@ const DEFAULT_OPTIONS = {
|
||||
identifier: defaultIdentifier,
|
||||
} as const;
|
||||
|
||||
|
||||
function createRateLimiter(options: RateLimitOptions = {}) {
|
||||
const redis = getRedisClient();
|
||||
const points = options.points ?? DEFAULT_OPTIONS.points;
|
||||
@@ -48,6 +45,7 @@ function createRateLimiter(options: RateLimitOptions = {}) {
|
||||
|
||||
// Use Redis if available, otherwise fall back to in-memory storage
|
||||
if (redis) {
|
||||
console.log("Using Redis for rate limiting");
|
||||
return new RateLimiterRedis({
|
||||
storeClient: redis,
|
||||
points,
|
||||
@@ -55,6 +53,7 @@ function createRateLimiter(options: RateLimitOptions = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Using in-memory for rate limiting");
|
||||
return new RateLimiterMemory({
|
||||
points,
|
||||
duration,
|
||||
@@ -97,3 +96,4 @@ export function withRateLimit(
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
"./repository/*": {
|
||||
"types": "./dist/repository/*.d.ts",
|
||||
"default": "./src/repository/*.ts"
|
||||
},
|
||||
"./redis": {
|
||||
"types": "./dist/redis.d.ts",
|
||||
"default": "./src/redis.ts"
|
||||
}
|
||||
},
|
||||
"license": "GPL-3.0",
|
||||
@@ -43,6 +47,7 @@
|
||||
"@kan/shared": "workspace:^",
|
||||
"drizzle-orm": "^0.42.0",
|
||||
"drizzle-zod": "^0.5.1",
|
||||
"ioredis": "^5.9.2",
|
||||
"pg": "^8.11.3",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "catalog:"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import Redis from "ioredis";
|
||||
|
||||
import { env } from "~/env";
|
||||
|
||||
let redisClient: Redis | null = null;
|
||||
|
||||
export function getRedisClient(): Redis | null {
|
||||
@@ -9,7 +7,7 @@ export function getRedisClient(): Redis | null {
|
||||
return redisClient;
|
||||
}
|
||||
|
||||
const redisUrl = env.REDIS_URL;
|
||||
const redisUrl = process.env.REDIS_URL;
|
||||
|
||||
if (!redisUrl) {
|
||||
return null;
|
||||
@@ -31,4 +29,3 @@ export async function closeRedisClient(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -166,9 +166,6 @@ importers:
|
||||
geist:
|
||||
specifier: ^1.3.1
|
||||
version: 1.4.2(next@15.5.9(@babel/core@7.28.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||
ioredis:
|
||||
specifier: ^5.9.2
|
||||
version: 5.9.2
|
||||
jose:
|
||||
specifier: ^6.1.2
|
||||
version: 6.1.2
|
||||
@@ -187,9 +184,6 @@ importers:
|
||||
posthog-js:
|
||||
specifier: ^1.254.0
|
||||
version: 1.261.0
|
||||
rate-limiter-flexible:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
react:
|
||||
specifier: catalog:react18
|
||||
version: 18.3.1
|
||||
@@ -320,6 +314,9 @@ importers:
|
||||
'@trpc/server':
|
||||
specifier: 'catalog:'
|
||||
version: 11.5.0(typescript@5.9.2)
|
||||
rate-limiter-flexible:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
superjson:
|
||||
specifier: 2.2.1
|
||||
version: 2.2.1
|
||||
@@ -403,6 +400,9 @@ importers:
|
||||
drizzle-zod:
|
||||
specifier: ^0.5.1
|
||||
version: 0.5.1(drizzle-orm@0.42.0(@electric-sql/pglite@0.3.7)(@types/pg@8.15.5)(kysely@0.28.8)(pg@8.16.3))(zod@3.25.76)
|
||||
ioredis:
|
||||
specifier: ^5.9.2
|
||||
version: 5.9.2
|
||||
pg:
|
||||
specifier: ^8.11.3
|
||||
version: 8.16.3
|
||||
|
||||
Reference in New Issue
Block a user