console.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import { domain } from "./stage"
  2. import { EMAILOCTOPUS_API_KEY } from "./app"
  3. ////////////////
  4. // DATABASE
  5. ////////////////
  6. const cluster = planetscale.getDatabaseOutput({
  7. name: "opencode",
  8. organization: "anomalyco",
  9. })
  10. const branch =
  11. $app.stage === "production"
  12. ? planetscale.getBranchOutput({
  13. name: "production",
  14. organization: cluster.organization,
  15. database: cluster.name,
  16. })
  17. : new planetscale.Branch("DatabaseBranch", {
  18. database: cluster.name,
  19. organization: cluster.organization,
  20. name: $app.stage,
  21. parentBranch: "production",
  22. })
  23. const password = new planetscale.Password("DatabasePassword", {
  24. name: $app.stage,
  25. database: cluster.name,
  26. organization: cluster.organization,
  27. branch: branch.name,
  28. })
  29. export const database = new sst.Linkable("Database", {
  30. properties: {
  31. host: password.accessHostUrl,
  32. database: cluster.name,
  33. username: password.username,
  34. password: password.plaintext,
  35. port: 3306,
  36. },
  37. })
  38. new sst.x.DevCommand("Studio", {
  39. link: [database],
  40. dev: {
  41. command: "bun db studio",
  42. directory: "packages/console/core",
  43. autostart: true,
  44. },
  45. })
  46. ////////////////
  47. // AUTH
  48. ////////////////
  49. const GITHUB_CLIENT_ID_CONSOLE = new sst.Secret("GITHUB_CLIENT_ID_CONSOLE")
  50. const GITHUB_CLIENT_SECRET_CONSOLE = new sst.Secret("GITHUB_CLIENT_SECRET_CONSOLE")
  51. const GOOGLE_CLIENT_ID = new sst.Secret("GOOGLE_CLIENT_ID")
  52. const authStorage = new sst.cloudflare.Kv("AuthStorage")
  53. export const auth = new sst.cloudflare.Worker("AuthApi", {
  54. domain: `auth.${domain}`,
  55. handler: "packages/console/function/src/auth.ts",
  56. url: true,
  57. link: [database, authStorage, GITHUB_CLIENT_ID_CONSOLE, GITHUB_CLIENT_SECRET_CONSOLE, GOOGLE_CLIENT_ID],
  58. })
  59. ////////////////
  60. // GATEWAY
  61. ////////////////
  62. export const stripeWebhook = new stripe.WebhookEndpoint("StripeWebhookEndpoint", {
  63. url: $interpolate`https://${domain}/stripe/webhook`,
  64. enabledEvents: [
  65. "checkout.session.async_payment_failed",
  66. "checkout.session.async_payment_succeeded",
  67. "checkout.session.completed",
  68. "checkout.session.expired",
  69. "charge.refunded",
  70. "invoice.payment_succeeded",
  71. "invoice.payment_failed",
  72. "invoice.payment_action_required",
  73. "customer.created",
  74. "customer.deleted",
  75. "customer.updated",
  76. "customer.discount.created",
  77. "customer.discount.deleted",
  78. "customer.discount.updated",
  79. "customer.source.created",
  80. "customer.source.deleted",
  81. "customer.source.expiring",
  82. "customer.source.updated",
  83. "customer.subscription.created",
  84. "customer.subscription.deleted",
  85. "customer.subscription.paused",
  86. "customer.subscription.pending_update_applied",
  87. "customer.subscription.pending_update_expired",
  88. "customer.subscription.resumed",
  89. "customer.subscription.trial_will_end",
  90. "customer.subscription.updated",
  91. ],
  92. })
  93. const zenLiteProduct = new stripe.Product("ZenLite", {
  94. name: "OpenCode Go",
  95. })
  96. const zenLiteCouponFirstMonth50 = new stripe.Coupon("ZenLiteCouponFirstMonth50", {
  97. name: "First month 50% off",
  98. percentOff: 50,
  99. appliesToProducts: [zenLiteProduct.id],
  100. duration: "once",
  101. })
  102. const zenLiteCouponFirstMonth100 = new stripe.Coupon("ZenLiteCouponFirstMonth100", {
  103. name: "First month 100% off",
  104. percentOff: 100,
  105. appliesToProducts: [zenLiteProduct.id],
  106. duration: "once",
  107. })
  108. const zenLitePrice = new stripe.Price("ZenLitePrice", {
  109. product: zenLiteProduct.id,
  110. currency: "usd",
  111. recurring: {
  112. interval: "month",
  113. intervalCount: 1,
  114. },
  115. unitAmount: 1000,
  116. })
  117. const ZEN_LITE_PRICE = new sst.Linkable("ZEN_LITE_PRICE", {
  118. properties: {
  119. product: zenLiteProduct.id,
  120. price: zenLitePrice.id,
  121. priceInr: 92900,
  122. firstMonth50Coupon: zenLiteCouponFirstMonth50.id,
  123. firstMonth100Coupon: zenLiteCouponFirstMonth100.id,
  124. },
  125. })
  126. const zenBlackProduct = new stripe.Product("ZenBlack", {
  127. name: "OpenCode Black",
  128. })
  129. const zenBlackPriceProps = {
  130. product: zenBlackProduct.id,
  131. currency: "usd",
  132. recurring: {
  133. interval: "month",
  134. intervalCount: 1,
  135. },
  136. }
  137. const zenBlackPrice200 = new stripe.Price("ZenBlackPrice", { ...zenBlackPriceProps, unitAmount: 20000 })
  138. const zenBlackPrice100 = new stripe.Price("ZenBlack100Price", { ...zenBlackPriceProps, unitAmount: 10000 })
  139. const zenBlackPrice20 = new stripe.Price("ZenBlack20Price", { ...zenBlackPriceProps, unitAmount: 2000 })
  140. const ZEN_BLACK_PRICE = new sst.Linkable("ZEN_BLACK_PRICE", {
  141. properties: {
  142. product: zenBlackProduct.id,
  143. plan200: zenBlackPrice200.id,
  144. plan100: zenBlackPrice100.id,
  145. plan20: zenBlackPrice20.id,
  146. },
  147. })
  148. const ZEN_MODELS = [
  149. new sst.Secret("ZEN_MODELS1"),
  150. new sst.Secret("ZEN_MODELS2"),
  151. new sst.Secret("ZEN_MODELS3"),
  152. new sst.Secret("ZEN_MODELS4"),
  153. new sst.Secret("ZEN_MODELS5"),
  154. new sst.Secret("ZEN_MODELS6"),
  155. new sst.Secret("ZEN_MODELS7"),
  156. new sst.Secret("ZEN_MODELS8"),
  157. new sst.Secret("ZEN_MODELS9"),
  158. new sst.Secret("ZEN_MODELS10"),
  159. new sst.Secret("ZEN_MODELS11"),
  160. new sst.Secret("ZEN_MODELS12"),
  161. new sst.Secret("ZEN_MODELS13"),
  162. new sst.Secret("ZEN_MODELS14"),
  163. new sst.Secret("ZEN_MODELS15"),
  164. new sst.Secret("ZEN_MODELS16"),
  165. new sst.Secret("ZEN_MODELS17"),
  166. new sst.Secret("ZEN_MODELS18"),
  167. new sst.Secret("ZEN_MODELS19"),
  168. new sst.Secret("ZEN_MODELS20"),
  169. new sst.Secret("ZEN_MODELS21"),
  170. new sst.Secret("ZEN_MODELS22"),
  171. new sst.Secret("ZEN_MODELS23"),
  172. new sst.Secret("ZEN_MODELS24"),
  173. new sst.Secret("ZEN_MODELS25"),
  174. new sst.Secret("ZEN_MODELS26"),
  175. new sst.Secret("ZEN_MODELS27"),
  176. new sst.Secret("ZEN_MODELS28"),
  177. new sst.Secret("ZEN_MODELS29"),
  178. new sst.Secret("ZEN_MODELS30"),
  179. ]
  180. const STRIPE_SECRET_KEY = new sst.Secret("STRIPE_SECRET_KEY")
  181. const STRIPE_PUBLISHABLE_KEY = new sst.Secret("STRIPE_PUBLISHABLE_KEY")
  182. const AUTH_API_URL = new sst.Linkable("AUTH_API_URL", {
  183. properties: { value: auth.url.apply((url) => url!) },
  184. })
  185. const STRIPE_WEBHOOK_SECRET = new sst.Linkable("STRIPE_WEBHOOK_SECRET", {
  186. properties: { value: stripeWebhook.secret },
  187. })
  188. const gatewayKv = new sst.cloudflare.Kv("GatewayKv")
  189. ////////////////
  190. // CONSOLE
  191. ////////////////
  192. const bucket = new sst.cloudflare.Bucket("ZenData")
  193. const bucketNew = new sst.cloudflare.Bucket("ZenDataNew")
  194. const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID")
  195. const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY")
  196. const SALESFORCE_CLIENT_ID = new sst.Secret("SALESFORCE_CLIENT_ID")
  197. const SALESFORCE_CLIENT_SECRET = new sst.Secret("SALESFORCE_CLIENT_SECRET")
  198. const SALESFORCE_INSTANCE_URL = new sst.Secret("SALESFORCE_INSTANCE_URL")
  199. const logProcessor = new sst.cloudflare.Worker("LogProcessor", {
  200. handler: "packages/console/function/src/log-processor.ts",
  201. link: [new sst.Secret("HONEYCOMB_API_KEY")],
  202. })
  203. new sst.cloudflare.x.SolidStart("Console", {
  204. domain,
  205. path: "packages/console/app",
  206. link: [
  207. bucket,
  208. bucketNew,
  209. database,
  210. AUTH_API_URL,
  211. STRIPE_WEBHOOK_SECRET,
  212. STRIPE_SECRET_KEY,
  213. EMAILOCTOPUS_API_KEY,
  214. AWS_SES_ACCESS_KEY_ID,
  215. AWS_SES_SECRET_ACCESS_KEY,
  216. SALESFORCE_CLIENT_ID,
  217. SALESFORCE_CLIENT_SECRET,
  218. SALESFORCE_INSTANCE_URL,
  219. ZEN_BLACK_PRICE,
  220. ZEN_LITE_PRICE,
  221. new sst.Secret("ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES"),
  222. new sst.Secret("ZEN_LIMITS"),
  223. new sst.Secret("ZEN_SESSION_SECRET"),
  224. ...ZEN_MODELS,
  225. ...($dev
  226. ? [
  227. new sst.Secret("CLOUDFLARE_DEFAULT_ACCOUNT_ID", process.env.CLOUDFLARE_DEFAULT_ACCOUNT_ID!),
  228. new sst.Secret("CLOUDFLARE_API_TOKEN", process.env.CLOUDFLARE_API_TOKEN!),
  229. ]
  230. : []),
  231. gatewayKv,
  232. ],
  233. environment: {
  234. //VITE_DOCS_URL: web.url.apply((url) => url!),
  235. //VITE_API_URL: gateway.url.apply((url) => url!),
  236. VITE_AUTH_URL: auth.url.apply((url) => url!),
  237. VITE_STRIPE_PUBLISHABLE_KEY: STRIPE_PUBLISHABLE_KEY.value,
  238. },
  239. transform: {
  240. server: {
  241. placement: { region: "aws:us-east-1" },
  242. transform: {
  243. worker: {
  244. tailConsumers: [{ service: logProcessor.nodes.worker.scriptName }],
  245. },
  246. },
  247. },
  248. },
  249. })