cloudaxe-opencode/infra/console.ts

296 lines
8.8 KiB
TypeScript
Raw Normal View History

2025-08-08 17:22:54 +00:00
import { domain } from "./stage"
2025-09-29 18:17:53 +00:00
import { EMAILOCTOPUS_API_KEY } from "./app"
import { SECRET } from "./secret"
2025-08-08 17:22:54 +00:00
2025-08-10 05:17:48 +00:00
////////////////
// DATABASE
////////////////
2025-08-08 17:22:54 +00:00
2025-09-02 07:14:56 +00:00
const cluster = planetscale.getDatabaseOutput({
name: "opencode",
2025-09-08 19:46:57 +00:00
organization: "anomalyco",
2025-09-02 07:14:56 +00:00
})
const branch =
$app.stage === "production"
? planetscale.getBranchOutput({
name: "production",
organization: cluster.organization,
database: cluster.name,
})
: new planetscale.Branch("DatabaseBranch", {
database: cluster.name,
organization: cluster.organization,
name: $app.stage,
parentBranch: "production",
})
const password = new planetscale.Password("DatabasePassword", {
name: $app.stage,
database: cluster.name,
organization: cluster.organization,
branch: branch.name,
})
2025-08-08 17:22:54 +00:00
export const database = new sst.Linkable("Database", {
properties: {
2025-09-02 07:14:56 +00:00
host: password.accessHostUrl,
database: cluster.name,
username: password.username,
password: password.plaintext,
port: 3306,
2025-08-08 17:22:54 +00:00
},
})
new sst.x.DevCommand("Studio", {
link: [database],
dev: {
command: "bun db studio",
2025-09-18 14:59:01 +00:00
directory: "packages/console/core",
2025-08-08 17:22:54 +00:00
autostart: true,
},
})
2025-08-10 05:17:48 +00:00
////////////////
// AUTH
////////////////
2025-08-08 17:22:54 +00:00
const GITHUB_CLIENT_ID_CONSOLE = new sst.Secret("GITHUB_CLIENT_ID_CONSOLE")
const GITHUB_CLIENT_SECRET_CONSOLE = new sst.Secret("GITHUB_CLIENT_SECRET_CONSOLE")
2025-08-09 05:28:27 +00:00
const GOOGLE_CLIENT_ID = new sst.Secret("GOOGLE_CLIENT_ID")
2025-08-08 17:22:54 +00:00
const authStorage = new sst.cloudflare.Kv("AuthStorage")
export const auth = new sst.cloudflare.Worker("AuthApi", {
domain: `auth.${domain}`,
2025-09-18 14:59:01 +00:00
handler: "packages/console/function/src/auth.ts",
2025-08-08 17:22:54 +00:00
url: true,
2025-11-08 01:59:02 +00:00
link: [database, authStorage, GITHUB_CLIENT_ID_CONSOLE, GITHUB_CLIENT_SECRET_CONSOLE, GOOGLE_CLIENT_ID],
2025-08-08 17:22:54 +00:00
})
2025-08-10 05:17:48 +00:00
////////////////
// GATEWAY
////////////////
2025-09-26 11:54:30 +00:00
export const stripeWebhook = new stripe.WebhookEndpoint("StripeWebhookEndpoint", {
2025-09-03 15:40:59 +00:00
url: $interpolate`https://${domain}/stripe/webhook`,
2025-08-10 05:17:48 +00:00
enabledEvents: [
"checkout.session.async_payment_failed",
"checkout.session.async_payment_succeeded",
"checkout.session.completed",
"checkout.session.expired",
2025-09-23 21:58:26 +00:00
"charge.refunded",
2026-01-07 06:55:36 +00:00
"invoice.payment_succeeded",
2026-01-24 13:33:47 +00:00
"invoice.payment_failed",
"invoice.payment_action_required",
2025-08-10 05:17:48 +00:00
"customer.created",
"customer.deleted",
"customer.updated",
"customer.discount.created",
"customer.discount.deleted",
"customer.discount.updated",
"customer.source.created",
"customer.source.deleted",
"customer.source.expiring",
"customer.source.updated",
"customer.subscription.created",
"customer.subscription.deleted",
"customer.subscription.paused",
"customer.subscription.pending_update_applied",
"customer.subscription.pending_update_expired",
"customer.subscription.resumed",
"customer.subscription.trial_will_end",
"customer.subscription.updated",
],
})
2026-02-22 23:41:34 +00:00
const zenLiteProduct = new stripe.Product("ZenLite", {
2026-02-25 17:39:48 +00:00
name: "OpenCode Go",
2026-02-22 23:41:34 +00:00
})
2026-03-11 14:46:16 +00:00
const zenLiteCouponFirstMonth50 = new stripe.Coupon("ZenLiteCouponFirstMonth50", {
name: "First month 50% off",
percentOff: 50,
appliesToProducts: [zenLiteProduct.id],
duration: "once",
})
2026-04-07 14:08:57 +00:00
const zenLiteCouponFirstMonth100 = new stripe.Coupon("ZenLiteCouponFirstMonth100", {
name: "First month 100% off",
percentOff: 100,
appliesToProducts: [zenLiteProduct.id],
duration: "once",
})
2026-04-27 05:36:26 +00:00
const zenLiteCouponThreeMonths100 = new stripe.Coupon("ZenLiteCoupon3Months100", {
name: "3 months 100% off",
percentOff: 100,
appliesToProducts: [zenLiteProduct.id],
duration: "repeating",
durationInMonths: 3,
})
const zenLiteCouponSixMonths100 = new stripe.Coupon("ZenLiteCoupon6Months100", {
name: "6 months 100% off",
percentOff: 100,
appliesToProducts: [zenLiteProduct.id],
duration: "repeating",
durationInMonths: 6,
})
const zenLiteCouponTwelveMonths100 = new stripe.Coupon("ZenLiteCoupon12Months100", {
name: "12 months 100% off",
percentOff: 100,
appliesToProducts: [zenLiteProduct.id],
duration: "repeating",
durationInMonths: 12,
})
2026-02-22 23:41:34 +00:00
const zenLitePrice = new stripe.Price("ZenLitePrice", {
product: zenLiteProduct.id,
currency: "usd",
recurring: {
interval: "month",
intervalCount: 1,
},
unitAmount: 1000,
})
const ZEN_LITE_PRICE = new sst.Linkable("ZEN_LITE_PRICE", {
properties: {
product: zenLiteProduct.id,
price: zenLitePrice.id,
2026-03-19 22:44:21 +00:00
priceInr: 92900,
2026-03-11 14:46:16 +00:00
firstMonth50Coupon: zenLiteCouponFirstMonth50.id,
2026-04-07 14:08:57 +00:00
firstMonth100Coupon: zenLiteCouponFirstMonth100.id,
2026-04-27 05:36:26 +00:00
threeMonths100Coupon: zenLiteCouponThreeMonths100.id,
sixMonths100Coupon: zenLiteCouponSixMonths100.id,
twelveMonths100Coupon: zenLiteCouponTwelveMonths100.id,
2026-02-22 23:41:34 +00:00
},
})
const zenBlackProduct = new stripe.Product("ZenBlack", {
2026-01-06 19:22:52 +00:00
name: "OpenCode Black",
})
2026-02-22 23:41:34 +00:00
const zenBlackPriceProps = {
product: zenBlackProduct.id,
2026-01-06 19:22:52 +00:00
currency: "usd",
recurring: {
interval: "month",
intervalCount: 1,
},
2026-01-22 17:40:42 +00:00
}
2026-02-22 23:41:34 +00:00
const zenBlackPrice200 = new stripe.Price("ZenBlackPrice", { ...zenBlackPriceProps, unitAmount: 20000 })
const zenBlackPrice100 = new stripe.Price("ZenBlack100Price", { ...zenBlackPriceProps, unitAmount: 10000 })
const zenBlackPrice20 = new stripe.Price("ZenBlack20Price", { ...zenBlackPriceProps, unitAmount: 2000 })
2026-01-22 17:40:42 +00:00
const ZEN_BLACK_PRICE = new sst.Linkable("ZEN_BLACK_PRICE", {
properties: {
2026-02-22 23:41:34 +00:00
product: zenBlackProduct.id,
plan200: zenBlackPrice200.id,
plan100: zenBlackPrice100.id,
plan20: zenBlackPrice20.id,
2026-01-22 17:40:42 +00:00
},
2026-01-06 19:22:52 +00:00
})
2025-11-21 17:50:51 +00:00
const ZEN_MODELS = [
new sst.Secret("ZEN_MODELS1"),
new sst.Secret("ZEN_MODELS2"),
new sst.Secret("ZEN_MODELS3"),
new sst.Secret("ZEN_MODELS4"),
2025-12-12 04:41:04 +00:00
new sst.Secret("ZEN_MODELS5"),
2025-12-24 01:36:52 +00:00
new sst.Secret("ZEN_MODELS6"),
2026-01-04 05:58:06 +00:00
new sst.Secret("ZEN_MODELS7"),
2026-01-15 23:21:01 +00:00
new sst.Secret("ZEN_MODELS8"),
2026-01-30 17:19:36 +00:00
new sst.Secret("ZEN_MODELS9"),
new sst.Secret("ZEN_MODELS10"),
2026-02-08 15:31:07 +00:00
new sst.Secret("ZEN_MODELS11"),
new sst.Secret("ZEN_MODELS12"),
new sst.Secret("ZEN_MODELS13"),
new sst.Secret("ZEN_MODELS14"),
new sst.Secret("ZEN_MODELS15"),
new sst.Secret("ZEN_MODELS16"),
new sst.Secret("ZEN_MODELS17"),
new sst.Secret("ZEN_MODELS18"),
new sst.Secret("ZEN_MODELS19"),
new sst.Secret("ZEN_MODELS20"),
2026-02-17 06:32:57 +00:00
new sst.Secret("ZEN_MODELS21"),
new sst.Secret("ZEN_MODELS22"),
new sst.Secret("ZEN_MODELS23"),
new sst.Secret("ZEN_MODELS24"),
new sst.Secret("ZEN_MODELS25"),
new sst.Secret("ZEN_MODELS26"),
new sst.Secret("ZEN_MODELS27"),
new sst.Secret("ZEN_MODELS28"),
new sst.Secret("ZEN_MODELS29"),
new sst.Secret("ZEN_MODELS30"),
2025-11-21 17:50:51 +00:00
]
2025-08-08 17:22:54 +00:00
const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY")
2026-01-13 22:51:20 +00:00
const STRIPE_PUBLISHABLE_KEY = new sst.Secret("STRIPE_PUBLISHABLE_KEY")
2025-08-08 17:22:54 +00:00
const AUTH_API_URL = new sst.Linkable("AUTH_API_URL", {
properties: { value: auth.url.apply((url) => url!) },
})
const STRIPE_WEBHOOK_SECRET = new sst.Linkable("STRIPE_WEBHOOK_SECRET", {
properties: { value: stripeWebhook.secret },
})
2025-11-08 15:15:35 +00:00
const gatewayKv = new sst.cloudflare.Kv("GatewayKv")
2025-08-08 17:22:54 +00:00
2025-08-10 05:17:48 +00:00
////////////////
// CONSOLE
////////////////
2025-12-02 19:51:25 +00:00
const bucket = new sst.cloudflare.Bucket("ZenData")
2025-12-23 00:36:04 +00:00
const bucketNew = new sst.cloudflare.Bucket("ZenDataNew")
2025-11-23 20:21:47 +00:00
const DISCORD_INCIDENT_WEBHOOK_URL = new sst.Secret("DISCORD_INCIDENT_WEBHOOK_URL")
2025-10-01 23:34:37 +00:00
const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID")
const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY")
const SALESFORCE_CLIENT_ID = new sst.Secret("SALESFORCE_CLIENT_ID")
const SALESFORCE_CLIENT_SECRET = new sst.Secret("SALESFORCE_CLIENT_SECRET")
const SALESFORCE_INSTANCE_URL = new sst.Secret("SALESFORCE_INSTANCE_URL")
2026-02-10 20:55:31 +00:00
const logProcessor = new sst.cloudflare.Worker("LogProcessor", {
handler: "packages/console/function/src/log-processor.ts",
link: [new sst.Secret("HONEYCOMB_API_KEY")],
})
2025-09-08 19:46:57 +00:00
2025-09-02 07:14:56 +00:00
new sst.cloudflare.x.SolidStart("Console", {
2025-09-03 03:56:10 +00:00
domain,
2025-09-18 14:59:01 +00:00
path: "packages/console/app",
2025-10-01 23:34:37 +00:00
link: [
2025-11-23 20:21:47 +00:00
bucket,
2025-12-23 00:36:04 +00:00
bucketNew,
2025-10-01 23:34:37 +00:00
database,
AUTH_API_URL,
STRIPE_WEBHOOK_SECRET,
DISCORD_INCIDENT_WEBHOOK_URL,
SECRET.HoneycombWebhookSecret,
2025-10-01 23:34:37 +00:00
STRIPE_SECRET_KEY,
EMAILOCTOPUS_API_KEY,
AWS_SES_ACCESS_KEY_ID,
AWS_SES_SECRET_ACCESS_KEY,
SALESFORCE_CLIENT_ID,
SALESFORCE_CLIENT_SECRET,
SALESFORCE_INSTANCE_URL,
2026-01-22 17:40:42 +00:00
ZEN_BLACK_PRICE,
2026-02-22 23:41:34 +00:00
ZEN_LITE_PRICE,
2026-03-03 05:25:03 +00:00
new sst.Secret("ZEN_LIMITS"),
2026-01-13 03:33:57 +00:00
new sst.Secret("ZEN_SESSION_SECRET"),
2025-11-21 17:50:51 +00:00
...ZEN_MODELS,
2025-11-08 15:15:35 +00:00
...($dev
? [
2025-11-08 15:20:53 +00:00
new sst.Secret("CLOUDFLARE_DEFAULT_ACCOUNT_ID", process.env.CLOUDFLARE_DEFAULT_ACCOUNT_ID!),
2025-11-08 15:15:35 +00:00
new sst.Secret("CLOUDFLARE_API_TOKEN", process.env.CLOUDFLARE_API_TOKEN!),
]
: []),
gatewayKv,
2025-10-01 23:34:37 +00:00
],
2025-08-20 20:52:43 +00:00
environment: {
2025-08-29 23:34:56 +00:00
//VITE_DOCS_URL: web.url.apply((url) => url!),
//VITE_API_URL: gateway.url.apply((url) => url!),
2025-08-20 20:52:43 +00:00
VITE_AUTH_URL: auth.url.apply((url) => url!),
2026-01-13 22:51:20 +00:00
VITE_STRIPE_PUBLISHABLE_KEY: STRIPE_PUBLISHABLE_KEY.value,
2025-08-20 20:52:43 +00:00
},
2025-09-03 17:52:01 +00:00
transform: {
server: {
2026-02-18 18:54:23 +00:00
placement: { region: "aws:us-east-1" },
2025-09-03 17:52:01 +00:00
transform: {
worker: {
2026-02-10 20:55:31 +00:00
tailConsumers: [{ service: logProcessor.nodes.worker.scriptName }],
2025-09-03 17:52:01 +00:00
},
},
},
},
2025-08-20 20:52:43 +00:00
})