@corgelabs/corge 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/dist/ai/index.d.ts +3 -0
  2. package/dist/ai/index.d.ts.map +1 -0
  3. package/dist/ai/index.js +3 -0
  4. package/dist/ai/index.js.map +1 -0
  5. package/dist/ai/schema.d.ts +83 -0
  6. package/dist/ai/schema.d.ts.map +1 -0
  7. package/dist/ai/schema.js +19 -0
  8. package/dist/ai/schema.js.map +1 -0
  9. package/dist/ai/service.d.ts +14 -0
  10. package/dist/ai/service.d.ts.map +1 -0
  11. package/dist/ai/service.js +266 -0
  12. package/dist/ai/service.js.map +1 -0
  13. package/dist/ai/utils.d.ts +10 -0
  14. package/dist/ai/utils.d.ts.map +1 -0
  15. package/dist/ai/utils.js +27 -0
  16. package/dist/ai/utils.js.map +1 -0
  17. package/dist/attachments/index.d.ts +4 -0
  18. package/dist/attachments/index.d.ts.map +1 -0
  19. package/dist/attachments/index.js +4 -0
  20. package/dist/attachments/index.js.map +1 -0
  21. package/dist/attachments/routes.d.ts +75 -0
  22. package/dist/attachments/routes.d.ts.map +1 -0
  23. package/dist/attachments/routes.js +18 -0
  24. package/dist/attachments/routes.js.map +1 -0
  25. package/dist/attachments/schema.d.ts +61 -0
  26. package/dist/attachments/schema.d.ts.map +1 -0
  27. package/dist/attachments/schema.js +30 -0
  28. package/dist/attachments/schema.js.map +1 -0
  29. package/dist/attachments/service.d.ts +27 -0
  30. package/dist/attachments/service.d.ts.map +1 -0
  31. package/dist/attachments/service.js +224 -0
  32. package/dist/attachments/service.js.map +1 -0
  33. package/dist/attachments/utils.d.ts +9 -0
  34. package/dist/attachments/utils.d.ts.map +1 -0
  35. package/dist/attachments/utils.js +80 -0
  36. package/dist/attachments/utils.js.map +1 -0
  37. package/dist/auth/index.d.ts +4 -0
  38. package/dist/auth/index.d.ts.map +1 -0
  39. package/dist/auth/index.js +4 -0
  40. package/dist/auth/index.js.map +1 -0
  41. package/dist/auth/oidc.d.ts +25 -0
  42. package/dist/auth/oidc.d.ts.map +1 -0
  43. package/dist/auth/oidc.js +298 -0
  44. package/dist/auth/oidc.js.map +1 -0
  45. package/dist/auth/recovery.d.ts +41 -0
  46. package/dist/auth/recovery.d.ts.map +1 -0
  47. package/dist/auth/recovery.js +250 -0
  48. package/dist/auth/recovery.js.map +1 -0
  49. package/dist/auth/routes.d.ts +226 -0
  50. package/dist/auth/routes.d.ts.map +1 -0
  51. package/dist/auth/routes.js +96 -0
  52. package/dist/auth/routes.js.map +1 -0
  53. package/dist/auth/schema.d.ts +158 -0
  54. package/dist/auth/schema.d.ts.map +1 -0
  55. package/dist/auth/schema.js +82 -0
  56. package/dist/auth/schema.js.map +1 -0
  57. package/dist/auth/service.d.ts +96 -0
  58. package/dist/auth/service.d.ts.map +1 -0
  59. package/dist/auth/service.js +129 -0
  60. package/dist/auth/service.js.map +1 -0
  61. package/dist/auth/session.d.ts +51 -0
  62. package/dist/auth/session.d.ts.map +1 -0
  63. package/dist/auth/session.js +344 -0
  64. package/dist/auth/session.js.map +1 -0
  65. package/dist/auth/utils.d.ts +17 -0
  66. package/dist/auth/utils.d.ts.map +1 -0
  67. package/dist/auth/utils.js +96 -0
  68. package/dist/auth/utils.js.map +1 -0
  69. package/dist/bin/corge.js +542 -0
  70. package/dist/chat/context.d.ts +10 -0
  71. package/dist/chat/context.d.ts.map +1 -0
  72. package/dist/chat/context.js +221 -0
  73. package/dist/chat/context.js.map +1 -0
  74. package/dist/chat/index.d.ts +4 -0
  75. package/dist/chat/index.d.ts.map +1 -0
  76. package/dist/chat/index.js +4 -0
  77. package/dist/chat/index.js.map +1 -0
  78. package/dist/chat/routes.d.ts +160 -0
  79. package/dist/chat/routes.d.ts.map +1 -0
  80. package/dist/chat/routes.js +210 -0
  81. package/dist/chat/routes.js.map +1 -0
  82. package/dist/chat/schema.d.ts +285 -0
  83. package/dist/chat/schema.d.ts.map +1 -0
  84. package/dist/chat/schema.js +74 -0
  85. package/dist/chat/schema.js.map +1 -0
  86. package/dist/chat/service.d.ts +64 -0
  87. package/dist/chat/service.d.ts.map +1 -0
  88. package/dist/chat/service.js +279 -0
  89. package/dist/chat/service.js.map +1 -0
  90. package/dist/chat/stream.d.ts +53 -0
  91. package/dist/chat/stream.d.ts.map +1 -0
  92. package/dist/chat/stream.js +339 -0
  93. package/dist/chat/stream.js.map +1 -0
  94. package/dist/chat/utils.d.ts +61 -0
  95. package/dist/chat/utils.d.ts.map +1 -0
  96. package/dist/chat/utils.js +285 -0
  97. package/dist/chat/utils.js.map +1 -0
  98. package/dist/cli/builder.d.ts +6 -0
  99. package/dist/cli/builder.d.ts.map +1 -0
  100. package/dist/cli/builder.js +91 -0
  101. package/dist/cli/builder.js.map +1 -0
  102. package/dist/cli/deployer.d.ts +2 -0
  103. package/dist/cli/deployer.d.ts.map +1 -0
  104. package/dist/cli/deployer.js +152 -0
  105. package/dist/cli/deployer.js.map +1 -0
  106. package/dist/cli/dev-server.d.ts +2 -0
  107. package/dist/cli/dev-server.d.ts.map +1 -0
  108. package/dist/cli/dev-server.js +70 -0
  109. package/dist/cli/dev-server.js.map +1 -0
  110. package/dist/cli/env.d.ts +4 -0
  111. package/dist/cli/env.d.ts.map +1 -0
  112. package/dist/cli/env.js +68 -0
  113. package/dist/cli/env.js.map +1 -0
  114. package/dist/cli/init.d.ts +6 -0
  115. package/dist/cli/init.d.ts.map +1 -0
  116. package/dist/cli/init.js +97 -0
  117. package/dist/cli/init.js.map +1 -0
  118. package/dist/config.d.ts +262 -0
  119. package/dist/config.d.ts.map +1 -0
  120. package/dist/config.js +212 -0
  121. package/dist/config.js.map +1 -0
  122. package/dist/db/index.d.ts +3 -0
  123. package/dist/db/index.d.ts.map +1 -0
  124. package/dist/db/index.js +3 -0
  125. package/dist/db/index.js.map +1 -0
  126. package/dist/db/schema.d.ts +410 -0
  127. package/dist/db/schema.d.ts.map +1 -0
  128. package/dist/db/schema.js +294 -0
  129. package/dist/db/schema.js.map +1 -0
  130. package/dist/db/service.d.ts +42 -0
  131. package/dist/db/service.d.ts.map +1 -0
  132. package/dist/db/service.js +372 -0
  133. package/dist/db/service.js.map +1 -0
  134. package/dist/db/utils.d.ts +25 -0
  135. package/dist/db/utils.d.ts.map +1 -0
  136. package/dist/db/utils.js +188 -0
  137. package/dist/db/utils.js.map +1 -0
  138. package/dist/emails/index.d.ts +4 -0
  139. package/dist/emails/index.d.ts.map +1 -0
  140. package/dist/emails/index.js +4 -0
  141. package/dist/emails/index.js.map +1 -0
  142. package/dist/emails/routes.d.ts +191 -0
  143. package/dist/emails/routes.d.ts.map +1 -0
  144. package/dist/emails/routes.js +39 -0
  145. package/dist/emails/routes.js.map +1 -0
  146. package/dist/emails/schema.d.ts +237 -0
  147. package/dist/emails/schema.d.ts.map +1 -0
  148. package/dist/emails/schema.js +98 -0
  149. package/dist/emails/schema.js.map +1 -0
  150. package/dist/emails/service.d.ts +22 -0
  151. package/dist/emails/service.d.ts.map +1 -0
  152. package/dist/emails/service.js +337 -0
  153. package/dist/emails/service.js.map +1 -0
  154. package/dist/emails/utils.d.ts +49 -0
  155. package/dist/emails/utils.d.ts.map +1 -0
  156. package/dist/emails/utils.js +341 -0
  157. package/dist/emails/utils.js.map +1 -0
  158. package/dist/files/index.d.ts +4 -0
  159. package/dist/files/index.d.ts.map +1 -0
  160. package/dist/files/index.js +4 -0
  161. package/dist/files/index.js.map +1 -0
  162. package/dist/files/routes.d.ts +72 -0
  163. package/dist/files/routes.d.ts.map +1 -0
  164. package/dist/files/routes.js +38 -0
  165. package/dist/files/routes.js.map +1 -0
  166. package/dist/files/schema.d.ts +57 -0
  167. package/dist/files/schema.d.ts.map +1 -0
  168. package/dist/files/schema.js +39 -0
  169. package/dist/files/schema.js.map +1 -0
  170. package/dist/files/service.d.ts +27 -0
  171. package/dist/files/service.d.ts.map +1 -0
  172. package/dist/files/service.js +175 -0
  173. package/dist/files/service.js.map +1 -0
  174. package/dist/files/utils.d.ts +3 -0
  175. package/dist/files/utils.d.ts.map +1 -0
  176. package/dist/files/utils.js +63 -0
  177. package/dist/files/utils.js.map +1 -0
  178. package/dist/index.d.ts +875 -0
  179. package/dist/index.d.ts.map +1 -0
  180. package/dist/index.js +9919 -0
  181. package/dist/index.js.map +7 -0
  182. package/dist/payments/billing.d.ts +29 -0
  183. package/dist/payments/billing.d.ts.map +1 -0
  184. package/dist/payments/billing.js +378 -0
  185. package/dist/payments/billing.js.map +1 -0
  186. package/dist/payments/index.d.ts +4 -0
  187. package/dist/payments/index.d.ts.map +1 -0
  188. package/dist/payments/index.js +4 -0
  189. package/dist/payments/index.js.map +1 -0
  190. package/dist/payments/routes.d.ts +340 -0
  191. package/dist/payments/routes.d.ts.map +1 -0
  192. package/dist/payments/routes.js +56 -0
  193. package/dist/payments/routes.js.map +1 -0
  194. package/dist/payments/schema.d.ts +412 -0
  195. package/dist/payments/schema.d.ts.map +1 -0
  196. package/dist/payments/schema.js +260 -0
  197. package/dist/payments/schema.js.map +1 -0
  198. package/dist/payments/service.d.ts +31 -0
  199. package/dist/payments/service.d.ts.map +1 -0
  200. package/dist/payments/service.js +322 -0
  201. package/dist/payments/service.js.map +1 -0
  202. package/dist/payments/utils.d.ts +61 -0
  203. package/dist/payments/utils.d.ts.map +1 -0
  204. package/dist/payments/utils.js +369 -0
  205. package/dist/payments/utils.js.map +1 -0
  206. package/dist/router/guard.d.ts +19 -0
  207. package/dist/router/guard.d.ts.map +1 -0
  208. package/dist/router/guard.js +243 -0
  209. package/dist/router/guard.js.map +1 -0
  210. package/dist/router/index.d.ts +3 -0
  211. package/dist/router/index.d.ts.map +1 -0
  212. package/dist/router/index.js +3 -0
  213. package/dist/router/index.js.map +1 -0
  214. package/dist/router/schema.d.ts +103 -0
  215. package/dist/router/schema.d.ts.map +1 -0
  216. package/dist/router/schema.js +282 -0
  217. package/dist/router/schema.js.map +1 -0
  218. package/dist/router/service.d.ts +25 -0
  219. package/dist/router/service.d.ts.map +1 -0
  220. package/dist/router/service.js +339 -0
  221. package/dist/router/service.js.map +1 -0
  222. package/dist/tasks/index.d.ts +4 -0
  223. package/dist/tasks/index.d.ts.map +1 -0
  224. package/dist/tasks/index.js +4 -0
  225. package/dist/tasks/index.js.map +1 -0
  226. package/dist/tasks/routes.d.ts +54 -0
  227. package/dist/tasks/routes.d.ts.map +1 -0
  228. package/dist/tasks/routes.js +195 -0
  229. package/dist/tasks/routes.js.map +1 -0
  230. package/dist/tasks/schema.d.ts +261 -0
  231. package/dist/tasks/schema.d.ts.map +1 -0
  232. package/dist/tasks/schema.js +35 -0
  233. package/dist/tasks/schema.js.map +1 -0
  234. package/dist/tasks/service.d.ts +32 -0
  235. package/dist/tasks/service.d.ts.map +1 -0
  236. package/dist/tasks/service.js +201 -0
  237. package/dist/tasks/service.js.map +1 -0
  238. package/dist/tasks/steps.d.ts +18 -0
  239. package/dist/tasks/steps.d.ts.map +1 -0
  240. package/dist/tasks/steps.js +365 -0
  241. package/dist/tasks/steps.js.map +1 -0
  242. package/dist/tasks/utils.d.ts +75 -0
  243. package/dist/tasks/utils.d.ts.map +1 -0
  244. package/dist/tasks/utils.js +311 -0
  245. package/dist/tasks/utils.js.map +1 -0
  246. package/dist/tasks/watcher.d.ts +13 -0
  247. package/dist/tasks/watcher.d.ts.map +1 -0
  248. package/dist/tasks/watcher.js +255 -0
  249. package/dist/tasks/watcher.js.map +1 -0
  250. package/dist/tasks/worker.d.ts +28 -0
  251. package/dist/tasks/worker.d.ts.map +1 -0
  252. package/dist/tasks/worker.js +326 -0
  253. package/dist/tasks/worker.js.map +1 -0
  254. package/dist/utils/index.d.ts +3 -0
  255. package/dist/utils/index.d.ts.map +1 -0
  256. package/dist/utils/index.js +3 -0
  257. package/dist/utils/index.js.map +1 -0
  258. package/dist/utils/schema.d.ts +79 -0
  259. package/dist/utils/schema.d.ts.map +1 -0
  260. package/dist/utils/schema.js +41 -0
  261. package/dist/utils/schema.js.map +1 -0
  262. package/dist/utils/service.d.ts +32 -0
  263. package/dist/utils/service.d.ts.map +1 -0
  264. package/dist/utils/service.js +384 -0
  265. package/dist/utils/service.js.map +1 -0
  266. package/docs/SDK_SPEC.md +1645 -0
  267. package/infra/firestore.base.indexes.json +138 -0
  268. package/infra/firestore.base.rules +152 -0
  269. package/infra/storage.base.rules +8 -0
  270. package/package.json +58 -13
  271. package/src/ai/index.ts +2 -0
  272. package/src/ai/schema.ts +64 -0
  273. package/src/ai/service.ts +317 -0
  274. package/src/ai/utils.ts +38 -0
  275. package/src/attachments/index.ts +3 -0
  276. package/src/attachments/routes.ts +28 -0
  277. package/src/attachments/schema.ts +45 -0
  278. package/src/attachments/service.ts +315 -0
  279. package/src/attachments/utils.ts +115 -0
  280. package/src/auth/index.ts +3 -0
  281. package/src/auth/oidc.ts +419 -0
  282. package/src/auth/recovery.ts +365 -0
  283. package/src/auth/routes.ts +142 -0
  284. package/src/auth/schema.ts +181 -0
  285. package/src/auth/service.ts +183 -0
  286. package/src/auth/session.ts +414 -0
  287. package/src/auth/utils.ts +106 -0
  288. package/src/chat/context.ts +310 -0
  289. package/src/chat/index.ts +3 -0
  290. package/src/chat/routes.ts +264 -0
  291. package/src/chat/schema.ts +295 -0
  292. package/src/chat/service.ts +360 -0
  293. package/src/chat/stream.ts +481 -0
  294. package/src/chat/utils.ts +370 -0
  295. package/src/cli/builder.ts +93 -0
  296. package/src/cli/deployer.ts +184 -0
  297. package/src/cli/dev-server.ts +77 -0
  298. package/src/cli/env.ts +89 -0
  299. package/src/cli/init.ts +121 -0
  300. package/src/config.ts +447 -0
  301. package/src/db/index.ts +2 -0
  302. package/src/db/schema.ts +409 -0
  303. package/src/db/service.ts +477 -0
  304. package/src/db/utils.ts +250 -0
  305. package/src/emails/index.ts +3 -0
  306. package/src/emails/routes.ts +64 -0
  307. package/src/emails/schema.ts +239 -0
  308. package/src/emails/service.ts +488 -0
  309. package/src/emails/utils.ts +449 -0
  310. package/src/files/index.ts +3 -0
  311. package/src/files/routes.ts +44 -0
  312. package/src/files/schema.ts +76 -0
  313. package/src/files/service.ts +238 -0
  314. package/src/files/utils.ts +77 -0
  315. package/src/index.ts +425 -0
  316. package/src/payments/billing.ts +488 -0
  317. package/src/payments/index.ts +3 -0
  318. package/src/payments/routes.ts +92 -0
  319. package/src/payments/schema.ts +401 -0
  320. package/src/payments/service.ts +445 -0
  321. package/src/payments/utils.ts +472 -0
  322. package/src/router/guard.ts +319 -0
  323. package/src/router/index.ts +2 -0
  324. package/src/router/schema.ts +458 -0
  325. package/src/router/service.ts +453 -0
  326. package/src/tasks/index.ts +11 -0
  327. package/src/tasks/routes.ts +230 -0
  328. package/src/tasks/schema.ts +310 -0
  329. package/src/tasks/service.ts +254 -0
  330. package/src/tasks/steps.ts +472 -0
  331. package/src/tasks/utils.ts +445 -0
  332. package/src/tasks/watcher.ts +307 -0
  333. package/src/tasks/worker.ts +461 -0
  334. package/src/utils/index.ts +2 -0
  335. package/src/utils/schema.ts +69 -0
  336. package/src/utils/service.ts +461 -0
  337. package/tests/e2e.test.ts +2531 -0
  338. package/tsconfig.base.json +12 -0
  339. package/README.md +0 -2
  340. package/index.d.ts +0 -1
  341. package/index.js +0 -1
@@ -0,0 +1,401 @@
1
+ import { z } from 'zod'
2
+ import { CORE_CONFIG, type EnvScopedString, type PaymentProvider, type PaymentsConfig } from '../config'
3
+ import { entryId, type EntryId } from '../db'
4
+
5
+ export type { EnvScopedString, PaymentProvider, PaymentsConfig }
6
+
7
+ export interface ProviderPlanMapping {
8
+ stripe?: {
9
+ priceId: EnvScopedString
10
+ meterEventName?: string
11
+ }
12
+ dodo?: {
13
+ productId: EnvScopedString
14
+ meterEventName?: string
15
+ }
16
+ }
17
+
18
+ export interface PlanQuotaSpec {
19
+ aiTokens?: number | null
20
+ metrics?: Record<string, number>
21
+ overage?: {
22
+ enabled: boolean
23
+ maxOverageTokens?: number
24
+ unitTokens?: number
25
+ rateCents?: number
26
+ }
27
+ }
28
+
29
+ export interface PlanDefinition {
30
+ id?: string
31
+ name: string
32
+ description?: string
33
+ interval: 'month' | 'year' | 'free'
34
+ amount: number
35
+ currency?: Lowercase<string>
36
+ providers?: ProviderPlanMapping
37
+ quota?: PlanQuotaSpec
38
+ quotas?: PlanQuotaSpec
39
+ metadata?: Record<string, string>
40
+ }
41
+
42
+ export type PlansMap = Record<string, PlanDefinition>
43
+
44
+ export interface ProductDefinition {
45
+ id?: string
46
+ name: string
47
+ description?: string
48
+ amount: number
49
+ currency?: Lowercase<string>
50
+ providers?: {
51
+ stripe?: {
52
+ priceId?: EnvScopedString
53
+ productId?: EnvScopedString
54
+ }
55
+ dodo?: {
56
+ productId: EnvScopedString
57
+ }
58
+ }
59
+ grants?: {
60
+ aiTokens?: number
61
+ credits?: number
62
+ metrics?: Record<string, number>
63
+ }
64
+ metadata?: Record<string, string>
65
+ }
66
+
67
+ export type ProductsMap = Record<string, ProductDefinition>
68
+
69
+ const registeredPlans: Record<string, PlanDefinition & { id: string; quota: PlanQuotaSpec }> = {}
70
+ const registeredProducts: Record<string, ProductDefinition & { id: string }> = {}
71
+
72
+ export const registerPlans = (plans?: PlansMap, reset = false): void => {
73
+ if (reset) {
74
+ for (const k of Object.keys(registeredPlans)) delete registeredPlans[k]
75
+ }
76
+ if (!plans) return
77
+ const entries = Object.entries(plans)
78
+ for (const [k, def] of entries) {
79
+ const quota = def.quota ?? def.quotas ?? {}
80
+ registeredPlans[k] = { ...def, id: def.id ?? k, quota, quotas: quota }
81
+ }
82
+ if (entries.length > 0) CORE_CONFIG.payments.enabled = true
83
+ }
84
+
85
+ export const registerProducts = (products?: ProductsMap, reset = false): void => {
86
+ if (reset) {
87
+ for (const k of Object.keys(registeredProducts)) delete registeredProducts[k]
88
+ }
89
+ if (!products) return
90
+ const entries = Object.entries(products)
91
+ for (const [k, def] of entries) {
92
+ registeredProducts[k] = { ...def, id: def.id ?? k }
93
+ }
94
+ if (entries.length > 0) CORE_CONFIG.payments.enabled = true
95
+ }
96
+
97
+ export const clearPaymentDefinitions = (): void => {
98
+ for (const k of Object.keys(registeredPlans)) delete registeredPlans[k]
99
+ for (const k of Object.keys(registeredProducts)) delete registeredProducts[k]
100
+ CORE_CONFIG.payments.enabled = false
101
+ }
102
+
103
+ export const definePlans = <T extends PlansMap>(plans: T): T => {
104
+ const normalized = Object.fromEntries(
105
+ Object.entries(plans).map(([k, def]) => [k, { ...def, id: def.id ?? k }])
106
+ ) as T
107
+ registerPlans(normalized, false)
108
+ return normalized
109
+ }
110
+
111
+ export const defineProducts = <T extends ProductsMap>(products: T): T => {
112
+ const normalized = Object.fromEntries(
113
+ Object.entries(products).map(([k, def]) => [k, { ...def, id: def.id ?? k }])
114
+ ) as T
115
+ registerProducts(normalized, false)
116
+ return normalized
117
+ }
118
+
119
+ export const getPlanDefinition = (id: string): (PlanDefinition & { id: string; quota: PlanQuotaSpec }) | undefined =>
120
+ registeredPlans[id]
121
+
122
+ export const getProductDefinition = (id: string): (ProductDefinition & { id: string }) | undefined =>
123
+ registeredProducts[id]
124
+
125
+ export const getRegisteredPlans = (): Record<string, PlanDefinition & { id: string; quota: PlanQuotaSpec }> => registeredPlans
126
+
127
+ export const getRegisteredProducts = (): Record<string, ProductDefinition & { id: string }> => registeredProducts
128
+
129
+ export const subscriptionStatusSchema = z.enum([
130
+ 'none',
131
+ 'active',
132
+ 'trialing',
133
+ 'past_due',
134
+ 'on_hold',
135
+ 'cancelled',
136
+ 'expired'
137
+ ])
138
+ export type SubscriptionStatus = z.infer<typeof subscriptionStatusSchema>
139
+
140
+ export const paymentTransactionTypeSchema = z.enum([
141
+ 'checkout.completed',
142
+ 'payment.succeeded',
143
+ 'payment.failed',
144
+ 'invoice.created',
145
+ 'invoice.paid',
146
+ 'subscription.active',
147
+ 'subscription.renewed',
148
+ 'subscription.tier_changed',
149
+ 'subscription.cancelled',
150
+ 'subscription.past_due'
151
+ ])
152
+ export type PaymentTransactionType = z.infer<typeof paymentTransactionTypeSchema>
153
+
154
+ export const customLineItemSchema = z.object({
155
+ name: z.string().min(1).max(200),
156
+ description: z.string().max(1000).optional(),
157
+ amount: z.number().int().positive(),
158
+ currency: z.string().length(3).toLowerCase().optional(),
159
+ quantity: z.number().int().positive().default(1)
160
+ })
161
+ export type CustomLineItem = z.input<typeof customLineItemSchema>
162
+
163
+ export const createCheckoutInput = z
164
+ .object({
165
+ product: z.string().optional(),
166
+ plan: z.string().optional(),
167
+ custom: customLineItemSchema.optional(),
168
+ quantity: z.number().int().positive().default(1),
169
+ successUrl: z.string().url().optional(),
170
+ cancelUrl: z.string().url().optional(),
171
+ idempotencyKey: z.string().max(200).optional(),
172
+ metadata: z.record(z.string(), z.string()).optional()
173
+ })
174
+ .refine((v) => Number(Boolean(v.product)) + Number(Boolean(v.plan)) + Number(Boolean(v.custom)) === 1, {
175
+ message: 'Provide exactly one of: product, plan, or custom'
176
+ })
177
+ export type CreateCheckoutInput = z.input<typeof createCheckoutInput>
178
+
179
+ export const checkoutSessionResultSchema = z.object({
180
+ checkoutId: z.string(),
181
+ url: z.string().url(),
182
+ provider: z.enum(['stripe', 'dodo']),
183
+ expiresAt: z.string().datetime().optional()
184
+ })
185
+ export type CheckoutSessionResult = z.infer<typeof checkoutSessionResultSchema>
186
+
187
+ export const createPaymentLinkInput = z
188
+ .object({
189
+ product: z.string().optional(),
190
+ plan: z.string().optional(),
191
+ custom: customLineItemSchema.optional(),
192
+ quantity: z.number().int().positive().default(1),
193
+ returnUrl: z.string().url().optional(),
194
+ idempotencyKey: z.string().max(200).optional(),
195
+ metadata: z.record(z.string(), z.string()).optional()
196
+ })
197
+ .refine((v) => Number(Boolean(v.product)) + Number(Boolean(v.plan)) + Number(Boolean(v.custom)) === 1, {
198
+ message: 'Provide exactly one of: product, plan, or custom'
199
+ })
200
+ export type CreatePaymentLinkInput = z.input<typeof createPaymentLinkInput>
201
+
202
+ export const paymentLinkResultSchema = z.object({
203
+ paymentLinkId: z.string(),
204
+ url: z.string().url(),
205
+ provider: z.enum(['stripe', 'dodo'])
206
+ })
207
+ export type PaymentLinkResult = z.infer<typeof paymentLinkResultSchema>
208
+
209
+ export const createInvoiceInput = z
210
+ .object({
211
+ product: z.string().optional(),
212
+ custom: customLineItemSchema.optional(),
213
+ quantity: z.number().int().positive().default(1),
214
+ daysUntilDue: z.number().int().positive().max(365).default(30),
215
+ idempotencyKey: z.string().max(200).optional(),
216
+ metadata: z.record(z.string(), z.string()).optional()
217
+ })
218
+ .refine((v) => Number(Boolean(v.product)) + Number(Boolean(v.custom)) === 1, {
219
+ message: 'Provide exactly one of: product or custom'
220
+ })
221
+ export type CreateInvoiceInput = z.input<typeof createInvoiceInput>
222
+
223
+ export const invoiceResultSchema = z.object({
224
+ invoiceId: z.string(),
225
+ status: z.enum(['open', 'paid', 'draft', 'void']),
226
+ amount: z.number().int().nonnegative(),
227
+ currency: z.string(),
228
+ hostedInvoiceUrl: z.string().url(),
229
+ pdfUrl: z.string().url().optional(),
230
+ provider: z.enum(['stripe', 'dodo'])
231
+ })
232
+ export type InvoiceResult = z.infer<typeof invoiceResultSchema>
233
+
234
+ export const directChargeInput = z
235
+ .object({
236
+ product: z.string().optional(),
237
+ custom: customLineItemSchema.optional(),
238
+ amount: z.number().int().positive().optional(),
239
+ currency: z.string().length(3).toLowerCase().optional(),
240
+ description: z.string().max(1000).optional(),
241
+ paymentMethodId: z.string().optional(),
242
+ idempotencyKey: z.string().max(200).optional(),
243
+ metadata: z.record(z.string(), z.string()).optional()
244
+ })
245
+ .refine((v) => Boolean(v.product || v.custom || v.amount), {
246
+ message: 'Provide product, custom, or amount'
247
+ })
248
+ export type DirectChargeInput = z.input<typeof directChargeInput>
249
+
250
+ export const chargeResultSchema = z.object({
251
+ chargeId: z.string(),
252
+ status: z.enum(['succeeded', 'requires_action', 'failed']),
253
+ amount: z.number().int().nonnegative(),
254
+ currency: z.string(),
255
+ provider: z.enum(['stripe', 'dodo']),
256
+ checkoutUrl: z.string().url().optional(),
257
+ clientSecret: z.string().optional()
258
+ })
259
+ export type ChargeResult = z.infer<typeof chargeResultSchema>
260
+
261
+ export const subscribeInput = z.object({
262
+ plan: z.string().min(1),
263
+ returnUrl: z.string().url().optional(),
264
+ idempotencyKey: z.string().max(200).optional(),
265
+ metadata: z.record(z.string(), z.string()).optional()
266
+ })
267
+ export type SubscribeInput = z.input<typeof subscribeInput>
268
+
269
+ export const subscribeResultSchema = z.object({
270
+ subscriptionId: z.string(),
271
+ planId: z.string(),
272
+ status: z.enum(['active', 'trialing', 'requires_action']),
273
+ provider: z.enum(['stripe', 'dodo']),
274
+ checkoutUrl: z.string().url().optional()
275
+ })
276
+ export type SubscribeResult = z.infer<typeof subscribeResultSchema>
277
+
278
+ export const changeTierInput = z.object({
279
+ plan: z.string().min(1),
280
+ proration: z.enum(['prorated_immediately', 'next_cycle', 'none']).default('prorated_immediately'),
281
+ idempotencyKey: z.string().max(200).optional()
282
+ })
283
+ export type ChangeTierInput = z.input<typeof changeTierInput>
284
+
285
+ export const cancelSubscriptionInput = z.object({
286
+ immediately: z.boolean().default(false),
287
+ reason: z.string().max(500).optional(),
288
+ idempotencyKey: z.string().max(200).optional()
289
+ })
290
+ export type CancelSubscriptionInput = z.input<typeof cancelSubscriptionInput>
291
+
292
+ export const subscriptionRecordSchema = z.object({
293
+ subscriptionId: z.string(),
294
+ planId: z.string(),
295
+ status: subscriptionStatusSchema,
296
+ provider: z.enum(['stripe', 'dodo']),
297
+ cancelAtPeriodEnd: z.boolean(),
298
+ currentPeriodStart: z.string().datetime().optional(),
299
+ currentPeriodEnd: z.string().datetime().optional()
300
+ })
301
+ export type SubscriptionRecord = z.infer<typeof subscriptionRecordSchema>
302
+
303
+ export const recordUsageInput = z.object({
304
+ metric: z.string().default('ai_tokens'),
305
+ amount: z.number().positive(),
306
+ inputTokens: z.number().int().nonnegative().optional(),
307
+ outputTokens: z.number().int().nonnegative().optional(),
308
+ model: z.string().optional(),
309
+ idempotencyKey: z.string().max(200).optional(),
310
+ metadata: z.record(z.string(), z.string()).optional()
311
+ })
312
+ export type RecordUsageInput = z.input<typeof recordUsageInput>
313
+
314
+ export const usageStatusResultSchema = z.object({
315
+ userId: entryId,
316
+ periodKey: z.string(),
317
+ planId: z.string(),
318
+ aiTokensUsed: z.number().int().nonnegative(),
319
+ aiTokensLimit: z.number().int().nonnegative().nullable(),
320
+ bonusAiTokens: z.number().int().nonnegative(),
321
+ overageTokensReported: z.number().int().nonnegative(),
322
+ overageEnabled: z.boolean(),
323
+ maxOverageTokens: z.number().int().positive().optional(),
324
+ metricsUsed: z.record(z.string(), z.number()),
325
+ metricsLimits: z.record(z.string(), z.number()),
326
+ bonusMetrics: z.record(z.string(), z.number())
327
+ })
328
+ export type UsageStatusResult = z.infer<typeof usageStatusResultSchema>
329
+ export const usageSummarySchema = usageStatusResultSchema
330
+ export type UsageSummary = UsageStatusResult
331
+
332
+ export const quotaCheckResultSchema = z.object({
333
+ allowed: z.boolean(),
334
+ metric: z.string(),
335
+ used: z.number().nonnegative(),
336
+ limit: z.number().nonnegative().nullable(),
337
+ bonusRemaining: z.number().nonnegative(),
338
+ overageEnabled: z.boolean(),
339
+ remaining: z.number().nullable()
340
+ })
341
+ export type QuotaCheckResult = z.infer<typeof quotaCheckResultSchema>
342
+
343
+ export const customerBillingSummarySchema = z.object({
344
+ userId: entryId,
345
+ planId: z.string(),
346
+ plan: z.object({
347
+ id: z.string(),
348
+ name: z.string(),
349
+ interval: z.enum(['month', 'year', 'free']),
350
+ amount: z.number(),
351
+ currency: z.string()
352
+ }),
353
+ status: subscriptionStatusSchema,
354
+ subscriptionId: z.string().optional(),
355
+ activeProvider: z.enum(['stripe', 'dodo']).optional(),
356
+ currentPeriodStart: z.string().datetime().optional(),
357
+ currentPeriodEnd: z.string().datetime().optional(),
358
+ cancelAtPeriodEnd: z.boolean(),
359
+ bonusAiTokens: z.number().int().nonnegative(),
360
+ credits: z.number().nonnegative(),
361
+ bonusMetrics: z.record(z.string(), z.number())
362
+ })
363
+ export type CustomerBillingSummary = z.infer<typeof customerBillingSummarySchema>
364
+
365
+ export const paymentWebhookParamsSchema = z.object({
366
+ provider: z.enum(['stripe', 'dodo'])
367
+ })
368
+ export type PaymentWebhookParams = z.infer<typeof paymentWebhookParamsSchema>
369
+
370
+ export const paymentWebhookResultSchema = z.object({
371
+ received: z.literal(true),
372
+ eventId: z.string(),
373
+ handled: z.boolean(),
374
+ deduplicated: z.boolean().optional()
375
+ })
376
+ export type PaymentWebhookResult = z.infer<typeof paymentWebhookResultSchema>
377
+
378
+ export interface PaymentCallOptions {
379
+ provider?: PaymentProvider
380
+ userId?: EntryId
381
+ idempotencyKey?: string
382
+ }
383
+
384
+ export interface NormalizedPaymentWebhook {
385
+ eventId: string
386
+ paymentId?: string
387
+ rawEventType: string
388
+ txType: PaymentTransactionType | null
389
+ userId?: string
390
+ customerId?: string
391
+ subscriptionId?: string
392
+ subscriptionStatus?: SubscriptionStatus
393
+ planId?: string
394
+ productId?: string
395
+ amount?: number
396
+ currency?: string
397
+ currentPeriodStart?: string
398
+ currentPeriodEnd?: string
399
+ cancelAtPeriodEnd?: boolean
400
+ resetPeriodUsage?: boolean
401
+ }