set up docker files for OSS self hosting and deving
This commit is contained in:
55
.dockerignore
Normal file
55
.dockerignore
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
# Dependencies
|
||||
node_modules/
|
||||
**/node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Build outputs
|
||||
**/dist/
|
||||
**/build/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids/
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage/
|
||||
|
||||
# Docker
|
||||
Dockerfile*
|
||||
docker-compose*
|
||||
.dockerignore
|
||||
|
||||
# Tests
|
||||
**/tests/
|
||||
**/*.test.*
|
||||
**/*.spec.*
|
||||
15
commands.sh
Normal file
15
commands.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
RESTART EVERYTHING
|
||||
docker system prune -a --volumes
|
||||
|
||||
# DB
|
||||
docker compose -f docker-compose.db.yml up --build
|
||||
|
||||
# Dev
|
||||
docker compose -f docker-compose.dev.yml down
|
||||
docker volume rm main-repo_shared-node-modules main-repo_root-node-modules main-repo_vite-node-modules
|
||||
docker compose -f docker-compose.dev.yml build --no-cache
|
||||
docker compose -f docker-compose.dev.yml up
|
||||
|
||||
# Prod
|
||||
docker compose -f docker-compose.prod.yml up --build
|
||||
---
|
||||
95
docker-compose.dev.yml
Normal file
95
docker-compose.dev.yml
Normal file
@@ -0,0 +1,95 @@
|
||||
services:
|
||||
valkey:
|
||||
image: docker.io/bitnami/valkey:8.0
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
- VALKEY_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
volumes:
|
||||
- valkey-data:/bitnami/valkey/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
# ports:
|
||||
# - "6379:6379"
|
||||
restart: unless-stopped
|
||||
|
||||
shared:
|
||||
build:
|
||||
dockerfile: docker/dev.dockerfile
|
||||
context: .
|
||||
target: shared
|
||||
volumes:
|
||||
# - ./shared:/app/shared
|
||||
- shared-dist:/app/shared/dist
|
||||
- root-node-modules:/app/node_modules
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
restart: unless-stopped
|
||||
|
||||
# Vite frontend
|
||||
vite:
|
||||
build:
|
||||
dockerfile: docker/dev.dockerfile
|
||||
context: .
|
||||
target: vite
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
# - ./vite:/app/vite
|
||||
- shared-dist:/app/shared/dist
|
||||
- root-node-modules:/app/node_modules
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
depends_on:
|
||||
- shared
|
||||
restart: unless-stopped
|
||||
|
||||
# Main Express server
|
||||
server:
|
||||
build:
|
||||
dockerfile: docker/dev.dockerfile
|
||||
context: .
|
||||
target: server
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./server:/app/server
|
||||
- shared-dist:/app/shared/dist
|
||||
- root-node-modules:/app/node_modules
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- REDIS_URL=redis://valkey:6379
|
||||
depends_on:
|
||||
- shared
|
||||
restart: unless-stopped
|
||||
|
||||
# BullMQ Workers
|
||||
workers:
|
||||
build:
|
||||
dockerfile: docker/dev.dockerfile
|
||||
context: .
|
||||
target: workers
|
||||
volumes:
|
||||
# Mount server source for hot reload (workers use server code)
|
||||
- ./server:/app/server
|
||||
- shared-dist:/app/shared/dist
|
||||
- root-node-modules:/app/node_modules
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- REDIS_URL=redis://valkey:6379
|
||||
depends_on:
|
||||
- shared
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
# Shared package dist output
|
||||
shared-dist:
|
||||
valkey-data:
|
||||
|
||||
# Node modules volumes to avoid host/container conflicts
|
||||
shared-node-modules:
|
||||
server-node-modules:
|
||||
vite-node-modules:
|
||||
root-node-modules:
|
||||
46
docker-compose.prod.yml
Normal file
46
docker-compose.prod.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
valkey:
|
||||
image: docker.io/bitnami/valkey:8.0
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
- VALKEY_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
volumes:
|
||||
- valkey-data:/bitnami/valkey/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
ports:
|
||||
- "6379:6379"
|
||||
restart: unless-stopped
|
||||
|
||||
vite:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/prod.dockerfile
|
||||
target: vite-prod
|
||||
ports:
|
||||
- "3000:3000"
|
||||
restart: always
|
||||
|
||||
server:
|
||||
environment:
|
||||
- REDIS_URL=redis://valkey:6379
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/prod.dockerfile
|
||||
target: server-prod
|
||||
ports:
|
||||
- "8080:8080"
|
||||
restart: always
|
||||
|
||||
workers:
|
||||
environment:
|
||||
- REDIS_URL=redis://valkey:6379
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/prod.dockerfile
|
||||
target: workers-prod
|
||||
restart: always
|
||||
35
docker/dev.dockerfile
Normal file
35
docker/dev.dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# Multi-stage Dockerfile for Autumn development
|
||||
FROM node:18-alpine AS base
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install -g pnpm
|
||||
|
||||
COPY package*.json pnpm-workspace.yaml pnpm-lock.yaml ./
|
||||
COPY shared/ ./shared/
|
||||
COPY server/ ./server/
|
||||
COPY vite/ ./vite/
|
||||
RUN pnpm install
|
||||
RUN npm install -g nodemon tsx
|
||||
|
||||
# Stage 2: /shared
|
||||
FROM base AS shared
|
||||
WORKDIR /app/shared
|
||||
CMD ["pnpm", "run", "dev"]
|
||||
|
||||
# Stage 3: /vite
|
||||
FROM base AS vite
|
||||
WORKDIR /app/vite
|
||||
EXPOSE 3000
|
||||
CMD ["pnpm", "run", "dev"]
|
||||
|
||||
# Stage 4: /server
|
||||
FROM base AS server
|
||||
WORKDIR /app/server
|
||||
EXPOSE 8080
|
||||
CMD ["pnpm", "run", "dev"]
|
||||
|
||||
# Stage 5: Workers
|
||||
FROM base AS workers
|
||||
WORKDIR /app/server
|
||||
CMD ["pnpm", "run", "workers"]
|
||||
42
docker/docker-compose.db.yml
Normal file
42
docker/docker-compose.db.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Redis for caching and BullMQ
|
||||
valkey:
|
||||
image: docker.io/bitnami/valkey:8.0
|
||||
environment:
|
||||
- ALLOW_EMPTY_PASSWORD=yes
|
||||
- VALKEY_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
volumes:
|
||||
- valkey-data:/bitnami/valkey/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'redis-cli', '-h', 'localhost', '-p', '6379', 'ping']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
# PostgreSQL database
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: autumn-postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
POSTGRES_DB: autumn
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: autumn_dev_password
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
valkey-data:
|
||||
postgres-data:
|
||||
|
||||
networks:
|
||||
autumn-network:
|
||||
60
docker/prod.dockerfile
Normal file
60
docker/prod.dockerfile
Normal file
@@ -0,0 +1,60 @@
|
||||
# ---- Base dependencies ----
|
||||
FROM node:18-alpine AS base
|
||||
WORKDIR /app
|
||||
RUN npm install -g pnpm serve typescript tsc tsc-alias tsx
|
||||
|
||||
COPY package*.json pnpm-workspace.yaml pnpm-lock.yaml ./
|
||||
COPY shared/package*.json ./shared/
|
||||
COPY server/package*.json ./server/
|
||||
COPY vite/package*.json ./vite/
|
||||
|
||||
RUN pnpm install
|
||||
|
||||
|
||||
# # ---- Build shared ----
|
||||
# FROM base AS shared-build
|
||||
# COPY shared/ ./shared/
|
||||
# RUN pnpm -F shared build
|
||||
|
||||
# # ---- Build frontend (vite) ----
|
||||
FROM base AS vite-build
|
||||
COPY . .
|
||||
WORKDIR /app
|
||||
RUN pnpm run vite:build
|
||||
|
||||
# ---- Build backend (server) ----
|
||||
FROM base AS server-build
|
||||
COPY . .
|
||||
WORKDIR /app
|
||||
RUN pnpm run server:build
|
||||
|
||||
# ---- Production frontend image ----
|
||||
FROM vite-build AS vite-prod
|
||||
EXPOSE 3000
|
||||
WORKDIR /app
|
||||
CMD ["pnpm", "run", "vite:start"]
|
||||
|
||||
FROM server-build AS server-prod
|
||||
EXPOSE 8080
|
||||
WORKDIR /app
|
||||
CMD ["pnpm", "run", "server:start"]
|
||||
|
||||
FROM server-build AS workers-prod
|
||||
EXPOSE 8080
|
||||
WORKDIR /app
|
||||
CMD ["pnpm", "run", "server:workers"]
|
||||
|
||||
# # ---- Production backend image ----
|
||||
# FROM node:18-alpine AS server-prod
|
||||
# COPY --from=server-build /app/server/dist ./dist
|
||||
# COPY --from=server-build /app/server/package.json ./
|
||||
# COPY --from=server-build /app/server/node_modules ./node_modules
|
||||
# EXPOSE 8080
|
||||
# CMD ["pnpm", "run", "server:start"]
|
||||
|
||||
# # ---- Production workers image ----
|
||||
# FROM node:18-alpine AS workers-prod
|
||||
# COPY --from=server-build /app/server/dist ./dist
|
||||
# COPY --from=server-build /app/server/package.json ./
|
||||
# COPY --from=server-build /app/server/node_modules ./node_modules
|
||||
# CMD ["pnpm", "run", "server:workers"]
|
||||
@@ -1,5 +0,0 @@
|
||||
https://docs.fontawesome.com/web/use-with/react
|
||||
|
||||
https://docs.fontawesome.com/web/setup/packages#1-configure-access
|
||||
|
||||
In frontend, ran `npm link @useautumn/react`
|
||||
12923
package-lock.json
generated
12923
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -2,20 +2,16 @@
|
||||
"name": "autumn",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"frontend",
|
||||
"server",
|
||||
"shared",
|
||||
"tests",
|
||||
"vite"
|
||||
],
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"frontend:build": "npm run build -w shared && npm run build -w frontend",
|
||||
"frontend:start": "npm run start -w frontend",
|
||||
"vite:build": "npm run build -w shared && npm run build -w vite",
|
||||
"vite:start": "npm run start -w vite",
|
||||
"server:build": "npm run build -w shared && npm run prod:build -w server",
|
||||
"server:start": "npm run prod:start -w server",
|
||||
"vite:build": "pnpm -F shared build && pnpm -F vite build",
|
||||
"vite:start": "pnpm -F vite start",
|
||||
"server:build": "pnpm -F shared build && pnpm -F server prod:build",
|
||||
"server:start": "pnpm -F server prod:start",
|
||||
"server:cron": "npm run cron:start -w server",
|
||||
"server:workers": "npm run workers:start -w server",
|
||||
"dev": "concurrently \"cd server && npm run dev\" \"cd vite && npm run dev\" \"redis-server\""
|
||||
|
||||
10695
pnpm-lock.yaml
generated
Normal file
10695
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
packages:
|
||||
- 'shared'
|
||||
- 'server'
|
||||
- 'vite'
|
||||
3
run.sh
Executable file
3
run.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
if [[ $1 == *"docker-compose"* ]]; then
|
||||
docker compose -f "$1" up
|
||||
fi
|
||||
@@ -37,7 +37,7 @@
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "^1.2.10",
|
||||
"@anthropic-ai/sdk": "^0.32.1",
|
||||
"@autumn/shared": "*",
|
||||
"@autumn/shared": "workspace:*",
|
||||
"@clerk/express": "^1.3.22",
|
||||
"@date-fns/tz": "^1.2.0",
|
||||
"@date-fns/utc": "^2.1.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"autumn-js": "^0.0.64",
|
||||
"better-auth": "^1.2.9",
|
||||
"body-parser": "^1.20.3",
|
||||
"bullmq": "^5.31.1",
|
||||
"bullmq": "^5.54.0",
|
||||
"chai": "^5.1.2",
|
||||
"chai-http": "^5.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
@@ -78,12 +78,14 @@
|
||||
"pino-pretty": "^13.0.0",
|
||||
"postgres": "^3.4.7",
|
||||
"posthog-node": "^4.17.2",
|
||||
"react": "^18.2.0",
|
||||
"recaseai": "^0.0.37",
|
||||
"resend": "^4.1.1",
|
||||
"stripe": "^17.5.0",
|
||||
"svix": "^1.45.1",
|
||||
"tsc-alias": "^1.8.16",
|
||||
"ws": "^8.18.0"
|
||||
"ws": "^8.18.0",
|
||||
"zod": "^3.25.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^5.0.1",
|
||||
@@ -92,6 +94,9 @@
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "^22.13.4",
|
||||
"@types/pg": "^8.11.10",
|
||||
"@types/react": "^18.3.18",
|
||||
"@types/react-dom": "^18.3.5",
|
||||
"@types/ws": "^8.18.1",
|
||||
"drizzle-kit": "^0.31.1",
|
||||
"mocha": "^11.1.0",
|
||||
"puppeteer": "^24.2.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
import { Webhook } from "svix";
|
||||
|
||||
export const autumnWebhookRouter = express.Router();
|
||||
export const autumnWebhookRouter: Router = express.Router();
|
||||
|
||||
const verifyAutumnWebhook = async (req: any, res: any) => {
|
||||
const wh = new Webhook(process.env.AUTUMN_WEBHOOK_SECRET!);
|
||||
@@ -54,5 +54,5 @@ autumnWebhookRouter.post(
|
||||
success: true,
|
||||
message: "Webhook received",
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -89,7 +89,7 @@ export const createStripeMeteredPrice = async ({
|
||||
const stripePrice = await stripeCli.prices.create({
|
||||
...productData,
|
||||
...priceAmountData,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency || "usd",
|
||||
nickname: `Autumn Price (${feature!.name}) [Placeholder]`,
|
||||
recurring: {
|
||||
...(billingIntervalToStripe(price.config!.interval!) as any),
|
||||
@@ -194,7 +194,7 @@ export const createStripeArrearProrated = async ({
|
||||
|
||||
let stripePrice = await stripeCli.prices.create({
|
||||
...productData,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency || "usd",
|
||||
...priceAmountData,
|
||||
recurring: {
|
||||
...(recurringData as any),
|
||||
|
||||
@@ -26,7 +26,7 @@ export const createStripeFixedPrice = async ({
|
||||
const stripePrice = await stripeCli.prices.create({
|
||||
product: product.processor!.id,
|
||||
unit_amount: amount,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency!,
|
||||
recurring: {
|
||||
...(billingIntervalToStripe(config.interval!) as any),
|
||||
},
|
||||
|
||||
@@ -255,7 +255,7 @@ export const createStripeInArrearPrice = async ({
|
||||
const stripePrice = await stripeCli.prices.create({
|
||||
...productData,
|
||||
...priceAmountData,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency!,
|
||||
recurring: {
|
||||
...(billingIntervalToStripe(price.config!.interval!) as any),
|
||||
meter: meter!.id,
|
||||
|
||||
@@ -110,7 +110,7 @@ export const createStripePrepaid = async ({
|
||||
...productData,
|
||||
// unit_amount_decimal: (amount * 100).toString(),
|
||||
unit_amount_decimal: unitAmountDecimalStr,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency!,
|
||||
});
|
||||
|
||||
config.stripe_product_id = stripePrice.product as string;
|
||||
@@ -133,7 +133,7 @@ export const createStripePrepaid = async ({
|
||||
|
||||
stripePrice = await stripeCli.prices.create({
|
||||
...productData,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency!,
|
||||
...priceAmountData,
|
||||
recurring: {
|
||||
...(recurringData as any),
|
||||
|
||||
10
server/src/external/stripe/stripeWebhooks.ts
vendored
10
server/src/external/stripe/stripeWebhooks.ts
vendored
@@ -1,7 +1,10 @@
|
||||
import express, { Router } from "express";
|
||||
import stripe, { Stripe } from "stripe";
|
||||
import chalk from "chalk";
|
||||
|
||||
import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import { AuthType, LoggerAction, Organization } from "@autumn/shared";
|
||||
import express from "express";
|
||||
import stripe, { Stripe } from "stripe";
|
||||
|
||||
import { handleCheckoutSessionCompleted } from "./webhookHandlers/handleCheckoutCompleted.js";
|
||||
import { handleSubscriptionUpdated } from "./webhookHandlers/handleSubUpdated.js";
|
||||
import { handleSubDeleted } from "./webhookHandlers/handleSubDeleted.js";
|
||||
@@ -10,7 +13,6 @@ import { getStripeWebhookSecret } from "@/internal/orgs/orgUtils.js";
|
||||
import { handleInvoicePaid } from "./webhookHandlers/handleInvoicePaid.js";
|
||||
import { handleRequestError } from "@/utils/errorUtils.js";
|
||||
import { handleInvoiceCreated } from "./webhookHandlers/handleInvoiceCreated/handleInvoiceCreated.js";
|
||||
import chalk from "chalk";
|
||||
import { handleInvoiceFinalized } from "./webhookHandlers/handleInvoiceFinalized.js";
|
||||
import { handleSubscriptionScheduleCanceled } from "./webhookHandlers/handleSubScheduleCanceled.js";
|
||||
import { createLogtailWithContext } from "../logtail/logtailUtils.js";
|
||||
@@ -18,7 +20,7 @@ import { handleCusDiscountDeleted } from "./webhookHandlers/handleCusDiscountDel
|
||||
import { ExtendedRequest } from "@/utils/models/Request.js";
|
||||
import { createStripeCli } from "./utils.js";
|
||||
|
||||
export const stripeWebhookRouter = express.Router();
|
||||
export const stripeWebhookRouter: Router = express.Router();
|
||||
|
||||
const logStripeWebhook = ({
|
||||
req,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
|
||||
import { stripeWebhookRouter } from "../stripe/stripeWebhooks.js";
|
||||
import { autumnWebhookRouter } from "../autumn/autumnWebhookRouter.js";
|
||||
|
||||
const webhooksRouter = express.Router();
|
||||
const webhooksRouter: Router = express.Router();
|
||||
|
||||
webhooksRouter.use("/stripe", stripeWebhookRouter);
|
||||
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
import { handleFrontendReqError } from "@/utils/errorUtils.js";
|
||||
import { ExtendedRequest } from "@/utils/models/Request.js";
|
||||
import { member, organizations, user } from "@autumn/shared";
|
||||
import {
|
||||
and,
|
||||
desc,
|
||||
eq,
|
||||
gt,
|
||||
gte,
|
||||
ilike,
|
||||
inArray,
|
||||
lt,
|
||||
lte,
|
||||
or,
|
||||
} from "drizzle-orm";
|
||||
import { and, desc, eq, gt, gte, ilike, inArray, lt, or } from "drizzle-orm";
|
||||
import { Router } from "express";
|
||||
import { getUserCount } from "./adminUtils/userAnalytics.js";
|
||||
|
||||
export const adminRouter = Router();
|
||||
export const adminRouter: Router = Router();
|
||||
|
||||
adminRouter.get("/users", async (req: any, res: any) => {
|
||||
try {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { analyticsMiddleware } from "@/middleware/analyticsMiddleware.js";
|
||||
import rewardRouter from "./rewards/rewardRouter.js";
|
||||
import expireRouter from "./customers/products/expireRouter.js";
|
||||
|
||||
const apiRouter = Router();
|
||||
const apiRouter: Router = Router();
|
||||
|
||||
apiRouter.use(apiAuthMiddleware);
|
||||
apiRouter.use(pricingMiddleware);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import { FullCusProduct, CusProductStatus, ProductV2 } from "@autumn/shared";
|
||||
import { Router } from "express";
|
||||
|
||||
export const componentRouter = Router();
|
||||
export const componentRouter: Router = Router();
|
||||
|
||||
componentRouter.get("/pricing_table", async (req: any, res) =>
|
||||
routeHandler({
|
||||
|
||||
@@ -20,9 +20,8 @@ import { handleUpdateCustomer } from "../customers/handlers/handleUpdateCustomer
|
||||
import { handleCreateBillingPortal } from "../customers/handlers/handleCreateBillingPortal.js";
|
||||
import { handleGetCustomer } from "../customers/handlers/handleGetCustomer.js";
|
||||
import { CusSearchService } from "@/internal/customers/CusSearchService.js";
|
||||
import assert from "assert";
|
||||
|
||||
export const cusRouter = Router();
|
||||
export const cusRouter: Router = Router();
|
||||
|
||||
cusRouter.post("/all/search", async (req: any, res: any) => {
|
||||
try {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { CusProductStatus, ErrCode, FullCusProduct } from "@autumn/shared";
|
||||
import { Router } from "express";
|
||||
import { expireCusProduct } from "../../../customers/handlers/handleCusProductExpired.js";
|
||||
|
||||
const expireRouter = Router();
|
||||
const expireRouter: Router = Router();
|
||||
|
||||
expireRouter.post("", async (req, res) =>
|
||||
routeHandler({
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import { Router } from "express";
|
||||
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import { EntityService } from "./EntityService.js";
|
||||
import { CusService } from "@/internal/customers/CusService.js";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { ErrCode } from "@autumn/shared";
|
||||
import { handleGetEntity } from "./handlers/handleGetEntity.js";
|
||||
import { handlePostEntityRequest } from "../../entities/handlers/handleCreateEntity/handleCreateEntity.js";
|
||||
import { handleDeleteEntity } from "./handlers/handleDeleteEntity.js";
|
||||
|
||||
export const entityRouter = Router({ mergeParams: true });
|
||||
export const entityRouter: Router = Router({ mergeParams: true });
|
||||
|
||||
// List entityes
|
||||
entityRouter.get("", (req, res) =>
|
||||
entityRouter.get("", (req: any, res: any) =>
|
||||
routeHandler({
|
||||
req,
|
||||
res,
|
||||
|
||||
@@ -30,7 +30,7 @@ import { getOrCreateCustomer } from "@/internal/customers/cusUtils/getOrCreateCu
|
||||
import { getCheckPreview } from "./getCheckPreview.js";
|
||||
import { orgToVersion } from "@/utils/versionUtils.js";
|
||||
|
||||
export const entitledRouter = Router();
|
||||
export const entitledRouter: Router = Router();
|
||||
|
||||
const getRequiredAndActualBalance = ({
|
||||
cusEnts,
|
||||
|
||||
@@ -30,7 +30,7 @@ import { DrizzleCli } from "@/db/initDrizzle.js";
|
||||
import { ExtendedRequest } from "@/utils/models/Request.js";
|
||||
import { getEventTimestamp } from "./eventUtils.js";
|
||||
|
||||
export const eventsRouter = Router();
|
||||
export const eventsRouter: Router = Router();
|
||||
|
||||
const getEventAndCustomer = async ({
|
||||
req,
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
CusProductStatus,
|
||||
Customer,
|
||||
ErrCode,
|
||||
Event,
|
||||
EventInsert,
|
||||
FeatureType,
|
||||
FeatureUsageType,
|
||||
@@ -12,22 +11,17 @@ import RecaseError, { handleRequestError } from "@/utils/errorUtils.js";
|
||||
import { generateId, nullish } from "@/utils/genUtils.js";
|
||||
|
||||
import { EventService } from "./EventService.js";
|
||||
import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import { FeatureService } from "@/internal/features/FeatureService.js";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { QueueManager } from "@/queue/QueueManager.js";
|
||||
|
||||
import { JobName } from "@/queue/JobName.js";
|
||||
import { getOrCreateCustomer } from "@/internal/customers/cusUtils/getOrCreateCustomer.js";
|
||||
import { creditSystemContainsFeature } from "@/internal/features/creditSystemUtils.js";
|
||||
import { addTaskToQueue } from "@/queue/queueUtils.js";
|
||||
import { getOrgAndFeatures } from "@/internal/orgs/orgUtils.js";
|
||||
import { getEventTimestamp } from "./eventUtils.js";
|
||||
import { ExtendedRequest } from "@/utils/models/Request.js";
|
||||
import { runUpdateBalanceTask } from "@/trigger/updateBalanceTask.js";
|
||||
import { runUpdateUsageTask } from "@/trigger/updateUsageTask.js";
|
||||
export const eventsRouter = Router();
|
||||
export const usageRouter = Router();
|
||||
|
||||
export const eventsRouter: Router = Router();
|
||||
export const usageRouter: Router = Router();
|
||||
|
||||
const getCusFeatureAndOrg = async ({
|
||||
req,
|
||||
|
||||
@@ -6,7 +6,7 @@ import RecaseError, {
|
||||
import { handleUpdateFeature } from "./handlers/handleUpdateFeature.js";
|
||||
import { Feature, FeatureResponseSchema, FeatureType } from "@autumn/shared";
|
||||
import { CreateFeatureSchema } from "@autumn/shared";
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
import { generateId } from "@/utils/genUtils.js";
|
||||
import { ErrCode } from "@/errors/errCodes.js";
|
||||
|
||||
@@ -20,7 +20,7 @@ import { JobName } from "@/queue/JobName.js";
|
||||
import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import { handleDeleteFeature } from "./handlers/handleDeleteFeature.js";
|
||||
|
||||
export const featureApiRouter = express.Router();
|
||||
export const featureApiRouter: Router = express.Router();
|
||||
|
||||
export const validateFeature = (data: any) => {
|
||||
let featureType = data.type;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import { handleRequestError } from "@/utils/errorUtils.js";
|
||||
import { Router } from "express";
|
||||
|
||||
export const invoiceRouter = Router();
|
||||
export const invoiceRouter: Router = Router();
|
||||
|
||||
invoiceRouter.get("/:stripe_invoice_id/stripe", async (req: any, res: any) => {
|
||||
try {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { handleCopyProduct } from "./handlers/handleCopyProduct.js";
|
||||
import { handleCreateProduct } from "./handlers/handleCreateProduct.js";
|
||||
import { handleListProducts } from "./handlers/handleListProducts.js";
|
||||
|
||||
export const productApiRouter = Router();
|
||||
export const productApiRouter: Router = Router();
|
||||
|
||||
productApiRouter.get("", handleListProducts);
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ import { RewardRedemptionService } from "@/internal/rewards/RewardRedemptionServ
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { generateId, notNullish } from "@/utils/genUtils.js";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import { Customer, ErrCode, RewardTriggerEvent } from "@autumn/shared";
|
||||
import express from "express";
|
||||
import { ReferralCode, RewardRedemption } from "@autumn/shared";
|
||||
import { ErrCode, RewardTriggerEvent } from "@autumn/shared";
|
||||
import express, { Router } from "express";
|
||||
import { RewardRedemption } from "@autumn/shared";
|
||||
import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import { RewardProgramService } from "@/internal/rewards/RewardProgramService.js";
|
||||
|
||||
export const referralRouter = express.Router();
|
||||
export const referralRouter: Router = express.Router();
|
||||
|
||||
// 1. Get referral code
|
||||
referralRouter.post("/code", (req, res) =>
|
||||
@@ -238,7 +238,7 @@ referralRouter.post("/redeem", (req, res) =>
|
||||
}),
|
||||
);
|
||||
|
||||
export const redemptionRouter = express.Router();
|
||||
export const redemptionRouter: Router = express.Router();
|
||||
|
||||
redemptionRouter.get("/:redemptionId", (req, res) =>
|
||||
routeHandler({
|
||||
|
||||
@@ -8,9 +8,9 @@ import {
|
||||
ErrCode,
|
||||
RewardTriggerEvent,
|
||||
} from "@autumn/shared";
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
|
||||
export const rewardProgramRouter = express.Router();
|
||||
export const rewardProgramRouter: Router = express.Router();
|
||||
|
||||
rewardProgramRouter.post("", (req, res) =>
|
||||
routeHandler({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
import {
|
||||
CreateRewardSchema,
|
||||
ErrCode,
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
getRewardCat,
|
||||
} from "@/internal/rewards/rewardUtils.js";
|
||||
|
||||
const rewardRouter = express.Router();
|
||||
const rewardRouter: Router = express.Router();
|
||||
|
||||
rewardRouter.post("", async (req: any, res: any) => {
|
||||
try {
|
||||
|
||||
@@ -86,18 +86,18 @@ export const handleOneOffFunction = async ({
|
||||
// Create invoice
|
||||
logger.info("1. Creating invoice");
|
||||
const stripeInvoice = await stripeCli.invoices.create({
|
||||
customer: customer.processor.id,
|
||||
customer: customer.processor.id!,
|
||||
auto_advance: false,
|
||||
currency: org.default_currency,
|
||||
currency: org.default_currency!,
|
||||
});
|
||||
|
||||
logger.info("2. Creating invoice items");
|
||||
for (const invoiceItem of invoiceItems) {
|
||||
await stripeCli.invoiceItems.create({
|
||||
...invoiceItem,
|
||||
customer: customer.processor.id,
|
||||
customer: customer.processor.id!,
|
||||
invoice: stripeInvoice.id,
|
||||
});
|
||||
} as any);
|
||||
}
|
||||
|
||||
// Create invoice items
|
||||
|
||||
@@ -42,7 +42,7 @@ import { processAttachBody } from "./attachUtils/attachParams/processAttachBody.
|
||||
import { handleAttachPreview } from "./handleAttachPreview/handleAttachPreview.js";
|
||||
import { handleAttach } from "./handleAttach.js";
|
||||
|
||||
export const attachRouter = Router();
|
||||
export const attachRouter: Router = Router();
|
||||
|
||||
export const handlePrepaidErrors = async ({
|
||||
attachParams,
|
||||
|
||||
@@ -26,7 +26,7 @@ import { StatusCodes } from "http-status-codes";
|
||||
import { cusProductToProduct } from "./cusProducts/cusProductUtils/convertCusProduct.js";
|
||||
import { createOrgResponse } from "../orgs/orgUtils.js";
|
||||
|
||||
export const cusRouter = Router();
|
||||
export const cusRouter: Router = Router();
|
||||
|
||||
cusRouter.get("/:customer_id/data", async (req: any, res: any) => {
|
||||
try {
|
||||
|
||||
@@ -30,7 +30,7 @@ export const getProductChargeText = ({
|
||||
itemStrs.push(
|
||||
formatCurrency({
|
||||
amount: total,
|
||||
defaultCurrency: org.default_currency,
|
||||
defaultCurrency: org.default_currency!,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,17 +26,17 @@ export const formatTiers = ({
|
||||
if (tiers.length == 1) {
|
||||
return formatCurrency({
|
||||
amount: tiers[0].amount,
|
||||
defaultCurrency: org.default_currency,
|
||||
defaultCurrency: org.default_currency!,
|
||||
});
|
||||
}
|
||||
|
||||
let tiersStart = formatCurrency({
|
||||
amount: tiers[0].amount,
|
||||
defaultCurrency: org.default_currency,
|
||||
defaultCurrency: org.default_currency!,
|
||||
});
|
||||
let tiersEnd = formatCurrency({
|
||||
amount: tiers[tiers.length - 1].amount,
|
||||
defaultCurrency: org.default_currency,
|
||||
defaultCurrency: org.default_currency!,
|
||||
});
|
||||
|
||||
return `${tiersStart} - ${tiersEnd}`;
|
||||
@@ -58,13 +58,13 @@ export const getItemsHtml = ({
|
||||
if (pricedItems.length == 1) {
|
||||
html += `<br/><p style="font-size: 1.1em;"><strong>${formatCurrency({
|
||||
amount: totalAmount,
|
||||
defaultCurrency: org.default_currency,
|
||||
defaultCurrency: org.default_currency!,
|
||||
})}</strong></p>`;
|
||||
} else {
|
||||
html += `<br/><ul>${itemsToHtml({ items: pricedItems })}</ul>`;
|
||||
html += `<br/><p style="font-size: 1.1em;">Total: ${formatCurrency({
|
||||
amount: totalAmount,
|
||||
defaultCurrency: org.default_currency,
|
||||
defaultCurrency: org.default_currency!,
|
||||
})}</p>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { CacheManager } from "@/external/caching/CacheManager.js";
|
||||
import { CacheType } from "@/external/caching/cacheActions.js";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
|
||||
export const devRouter = Router();
|
||||
export const devRouter: Router = Router();
|
||||
|
||||
devRouter.get("/data", withOrgAuth, async (req: any, res) => {
|
||||
try {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
|
||||
import { FeatureService } from "./FeatureService.js";
|
||||
|
||||
export const featureRouter = express.Router();
|
||||
export const featureRouter: Router = express.Router();
|
||||
|
||||
featureRouter.get("", async (req: any, res) => {
|
||||
featureRouter.get("", async (req: any, res: any) => {
|
||||
try {
|
||||
let features = await FeatureService.getFromReq(req);
|
||||
res.status(200).json({ features });
|
||||
|
||||
@@ -15,7 +15,7 @@ import { autumnHandler } from "autumn-js/express";
|
||||
import { withAdminAuth } from "./admin/withAdminAuth.js";
|
||||
import { adminRouter } from "./admin/adminRouter.js";
|
||||
|
||||
const mainRouter = Router();
|
||||
const mainRouter: Router = Router();
|
||||
|
||||
mainRouter.get("", async (req: any, res) => {
|
||||
res.status(200).json({ message: "Hello World" });
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
UsagePriceConfig,
|
||||
} from "@autumn/shared";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
import { constructMigrationJob } from "@/internal/migrations/migrationUtils.js";
|
||||
import { MigrationService } from "@/internal/migrations/MigrationService.js";
|
||||
import { JobName } from "@/queue/JobName.js";
|
||||
@@ -20,7 +20,7 @@ import { isFreeProduct } from "@/internal/products/productUtils.js";
|
||||
import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js";
|
||||
import { findPrepaidPrice } from "../products/prices/priceUtils/findPriceUtils.js";
|
||||
|
||||
export const migrationRouter = express.Router();
|
||||
export const migrationRouter: Router = express.Router();
|
||||
|
||||
migrationRouter.post("", async (req: any, res: any) => {
|
||||
return routeHandler({
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import { createClerkCli } from "@/external/clerkUtils.js";
|
||||
import { saveOrgToDB } from "@/external/webhooks/clerkWebhooks.js";
|
||||
import { auth } from "@/utils/auth.js";
|
||||
|
||||
import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Router } from "express";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { routeHandler } from "@/utils/routerUtils.js";
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
import { createClerkCli } from "@/external/clerkUtils.js";
|
||||
import { AppEnv } from "@autumn/shared";
|
||||
import { parseChatResultFeatures } from "./parseChatFeatures.js";
|
||||
import { parseChatProducts } from "./parseChatProducts.js";
|
||||
@@ -14,7 +13,7 @@ import { EntitlementService } from "@/internal/products/entitlements/Entitlement
|
||||
import { PriceService } from "@/internal/products/prices/PriceService.js";
|
||||
import { ExtendedRequest, ExtendedResponse } from "@/utils/models/Request.js";
|
||||
|
||||
export const onboardingRouter = Router();
|
||||
export const onboardingRouter: Router = Router();
|
||||
|
||||
onboardingRouter.post("", async (req: Request, res: any) =>
|
||||
routeHandler({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import express from "express";
|
||||
import express, { Router } from "express";
|
||||
import Stripe from "stripe";
|
||||
|
||||
import RecaseError, { handleRequestError } from "@/utils/errorUtils.js";
|
||||
@@ -22,7 +22,7 @@ import { handleInvite } from "./handlers/handleInvite.js";
|
||||
import { handleGetUploadUrl } from "./handlers/handleGetUploadUrl.js";
|
||||
import { handleDeleteOrg } from "./handlers/handleDeleteOrg.js";
|
||||
|
||||
export const orgRouter = express.Router();
|
||||
export const orgRouter: Router = express.Router();
|
||||
orgRouter.get("/members", handleGetOrgMembers);
|
||||
orgRouter.get("/upload_url", handleGetUploadUrl);
|
||||
orgRouter.post("/invite", handleInvite as any);
|
||||
|
||||
@@ -17,7 +17,7 @@ import { isFeaturePriceItem } from "./product-items/productItemUtils/getItemType
|
||||
import RecaseError, { handleFrontendReqError } from "@/utils/errorUtils.js";
|
||||
import { createOrgResponse } from "../orgs/orgUtils.js";
|
||||
|
||||
export const productRouter = Router({ mergeParams: true });
|
||||
export const productRouter: Router = Router({ mergeParams: true });
|
||||
|
||||
productRouter.get("/data", async (req: any, res) => {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import RecaseError from "@/utils/errorUtils.js";
|
||||
|
||||
import { nullish } from "@/utils/genUtils.js";
|
||||
import { numberWithCommas } from "tests/utils/general/numberUtils.js";
|
||||
import { getFeatureName } from "@/internal/features/utils/displayUtils.js";
|
||||
|
||||
import {
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
ErrCode,
|
||||
Infinite,
|
||||
FullCusProduct,
|
||||
numberWithCommas,
|
||||
} from "@autumn/shared";
|
||||
import { isPriceItem } from "../product-items/productItemUtils/getItemType.js";
|
||||
import { isFeaturePriceItem } from "../product-items/productItemUtils/getItemType.js";
|
||||
|
||||
@@ -1,23 +1,7 @@
|
||||
import { createSupabaseClient } from "@/external/supabaseUtils.js";
|
||||
import { Router } from "express";
|
||||
|
||||
export const userRouter = Router();
|
||||
export const userRouter: Router = Router();
|
||||
|
||||
userRouter.get("", async (req: any, res) => {
|
||||
const supabase = createSupabaseClient();
|
||||
|
||||
res.status(200).json({ userId: req.userId });
|
||||
// const { data, error } = await supabase
|
||||
// .from("users")
|
||||
// .select("id, email, initialized")
|
||||
// .eq("id", req.userId)
|
||||
// .single();
|
||||
|
||||
// if (error) {
|
||||
// console.error("Error fetching user data:", error);
|
||||
// res.status(500).json({ error: error.message });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// res.status(200).json(data);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import "dotenv/config";
|
||||
|
||||
import { Queue } from "bullmq";
|
||||
import { Redis } from "ioredis";
|
||||
|
||||
const BACKUP_REDIS_URL = process.env.REDIS_BACKUP_URL || process.env.REDIS_URL;
|
||||
const MAIN_REDIS_URL = process.env.REDIS_URL;
|
||||
|
||||
export class QueueManager {
|
||||
private static instance: QueueManager;
|
||||
private queue: Queue | null = null;
|
||||
@@ -33,9 +38,7 @@ export class QueueManager {
|
||||
}) {
|
||||
// 1. Connect to redis
|
||||
|
||||
const redisUrl = useBackup
|
||||
? process.env.REDIS_BACKUP_URL
|
||||
: process.env.REDIS_URL;
|
||||
const redisUrl = useBackup ? BACKUP_REDIS_URL : MAIN_REDIS_URL;
|
||||
|
||||
const connection = new Redis(redisUrl!, {
|
||||
retryStrategy: (times) => {
|
||||
@@ -47,7 +50,7 @@ export class QueueManager {
|
||||
console.log(
|
||||
`Redis connection error (${useBackup ? "backup" : "main"}): ${
|
||||
error.message
|
||||
}`
|
||||
}`,
|
||||
);
|
||||
|
||||
if (!keepConnection) {
|
||||
@@ -90,7 +93,7 @@ export class QueueManager {
|
||||
console.log("2. Initializing main & backup queues");
|
||||
const mainQueue = new Queue("autumn", {
|
||||
connection: {
|
||||
url: process.env.REDIS_URL,
|
||||
url: MAIN_REDIS_URL,
|
||||
enableOfflineQueue: false,
|
||||
retryStrategy: (times) => {
|
||||
return 5000;
|
||||
@@ -100,7 +103,7 @@ export class QueueManager {
|
||||
|
||||
const backupQueue = new Queue("autumn", {
|
||||
connection: {
|
||||
url: process.env.REDIS_BACKUP_URL,
|
||||
url: BACKUP_REDIS_URL,
|
||||
enableOfflineQueue: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import sendOTPEmail from "@/internal/emails/sendOTPEmail.js";
|
||||
import { sendOnboardingEmail } from "@/internal/emails/sendOnboardingEmail.js";
|
||||
import { ADMIN_USER_IDs } from "./constants.js";
|
||||
import { afterOrgCreated } from "./authUtils/afterOrgCreated.js";
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: drizzleAdapter(db, {
|
||||
provider: "pg", // or "mysql", "sqlite"
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import { WebSocketServer } from "ws";
|
||||
import http from "http";
|
||||
|
||||
export class WebsocketManager {
|
||||
public channels: Map<string, Set<WebSocket>>;
|
||||
public subscriptions: WeakMap<WebSocket, Set<string>>;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { WebSocketServer } from "ws";
|
||||
import http from "http";
|
||||
|
||||
import { createSupabaseClient } from "@/external/supabaseUtils.js";
|
||||
import { AppEnv, ErrCode } from "@autumn/shared";
|
||||
import { OrgService } from "@/internal/orgs/OrgService.js";
|
||||
import { WebSocketServer, WebSocket } from "ws";
|
||||
|
||||
export enum SbChannelEvent {
|
||||
BalanceUpdated = "balance_updated",
|
||||
@@ -74,7 +71,7 @@ class WebSocketRouter {
|
||||
|
||||
constructor(server: http.Server) {
|
||||
this.wss = new WebSocketServer({ server });
|
||||
this.wss.on("connection", (ws, req) =>
|
||||
this.wss.on("connection", (ws: WebSocket, req: http.IncomingMessage) =>
|
||||
this.handleConnection(ws as any, req as any),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"target": "ES2020",
|
||||
"moduleResolution": "NodeNext",
|
||||
"module": "NodeNext",
|
||||
"declaration": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
"rootDir": ".",
|
||||
"baseUrl": ".",
|
||||
"outDir": "./dist",
|
||||
@@ -17,9 +18,10 @@
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
"@/*": ["src/*"],
|
||||
"@emails/*": ["emails/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"],
|
||||
"include": ["src", "emails"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
},
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"moduleResolution": "NodeNext", // or "node16"/"nodenext"
|
||||
"module": "NodeNext", // or "node16"/"nodenext"
|
||||
"moduleResolution": "NodeNext",
|
||||
"module": "NodeNext",
|
||||
|
||||
// "declaration": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
@@ -12,15 +12,18 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "nodemon --watch . --ext ts --ignore dist --exec 'pnpm run build'",
|
||||
"db:generate": "NODE_OPTIONS='--import tsx' drizzle-kit generate --config drizzle.config.ts",
|
||||
"db:migrate": "NODE_OPTIONS='--import tsx' drizzle-kit migrate --config drizzle.config.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"decimal.js": "^10.5.0",
|
||||
"drizzle-orm": "^0.43.1",
|
||||
"drizzle-zod": "^0.8.1",
|
||||
"drizzle-zod": "^0.8.2",
|
||||
"zod": "^3.25.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.7",
|
||||
"tsx": "^4.19.4",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"name": "@autumn/frontend2",
|
||||
"name": "@autumn/vite",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --port 3000",
|
||||
"dev": "vite --port 3000 --host",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"start": "serve -s dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@autumn/shared": "*",
|
||||
"@autumn/shared": "workspace:*",
|
||||
"@clerk/clerk-react": "^5.24.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
@@ -32,10 +33,12 @@
|
||||
"@wooorm/starry-night": "^3.6.0",
|
||||
"autumn-js": "^0.0.41",
|
||||
"axios": "^1.8.3",
|
||||
"better-auth": "^1.2.9",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"decimal.js": "^10.5.0",
|
||||
"hast-util-to-html": "^9.0.5",
|
||||
"input-otp": "^1.4.2",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -55,10 +58,12 @@
|
||||
"react-router": "^7.3.0",
|
||||
"sonner": "^2.0.1",
|
||||
"svix-react": "^1.13.3",
|
||||
"swr": "^2.3.3",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss": "^4.0.13",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vaul": "^1.1.2"
|
||||
"vaul": "^1.1.2",
|
||||
"zod": "^3.25.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.21.0",
|
||||
@@ -75,11 +80,5 @@
|
||||
"typescript": "~5.7.2",
|
||||
"typescript-eslint": "^8.24.1",
|
||||
"vite": "^6.2.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@rollup/rollup-linux-x64-gnu": "npm:@rollup/rollup-linux-x64-musl"
|
||||
},
|
||||
"overrides": {
|
||||
"@rollup/rollup-linux-x64-gnu": "npm:@rollup/rollup-linux-x64-musl"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Reward, CreateReward } from "@autumn/shared";
|
||||
|
||||
import { SupabaseClient } from "@supabase/supabase-js";
|
||||
import { AxiosInstance } from "axios";
|
||||
|
||||
export class RewardService {
|
||||
|
||||
@@ -76,7 +76,7 @@ export const columns: OrgColumnDef[] = [
|
||||
width: "100%",
|
||||
cell: ({ row }: { row: Row<Org> }) => {
|
||||
const value = row.getValue("users");
|
||||
return <span className="truncate">{value?.join(", ")}</span>;
|
||||
return <span className="truncate">{(value as string[]).join(", ")}</span>;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user