@soulbatical/tetra-core 0.10.4 → 0.11.0

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 (271) hide show
  1. package/README.md +78 -38
  2. package/dist/core/createApp.d.ts +1 -1
  3. package/dist/core/createApp.d.ts.map +1 -1
  4. package/dist/core/createApp.js +77 -2
  5. package/dist/core/createApp.js.map +1 -1
  6. package/dist/core/dualWriteProxy.d.ts +7 -2
  7. package/dist/core/dualWriteProxy.d.ts.map +1 -1
  8. package/dist/core/dualWriteProxy.js +16 -5
  9. package/dist/core/dualWriteProxy.js.map +1 -1
  10. package/dist/core/routeContext.d.ts +24 -0
  11. package/dist/core/routeContext.d.ts.map +1 -1
  12. package/dist/core/routeContext.js +31 -4
  13. package/dist/core/routeContext.js.map +1 -1
  14. package/dist/core/systemDb.d.ts +2 -2
  15. package/dist/core/systemDb.js +2 -2
  16. package/dist/generators/rls-checker.d.ts +1 -1
  17. package/dist/generators/rls-checker.js +1 -1
  18. package/dist/generators/rls-exec-sql.d.ts +1 -1
  19. package/dist/generators/rls-exec-sql.js +1 -1
  20. package/dist/generators/rpc/index.d.ts +1 -1
  21. package/dist/generators/rpc/index.js +1 -1
  22. package/dist/index.d.ts +3 -31
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +4 -32
  25. package/dist/index.js.map +1 -1
  26. package/dist/middleware/securityMiddleware.d.ts +1 -1
  27. package/dist/middleware/securityMiddleware.d.ts.map +1 -1
  28. package/dist/middleware/validateBody.d.ts.map +1 -1
  29. package/dist/middleware/validateBody.js +51 -8
  30. package/dist/middleware/validateBody.js.map +1 -1
  31. package/dist/shared/rfc7807ErrorResponse.d.ts +7 -0
  32. package/dist/shared/rfc7807ErrorResponse.d.ts.map +1 -1
  33. package/dist/shared/rfc7807ErrorResponse.js +19 -5
  34. package/dist/shared/rfc7807ErrorResponse.js.map +1 -1
  35. package/dist/utils/logger.d.ts.map +1 -1
  36. package/dist/utils/logger.js +16 -1
  37. package/dist/utils/logger.js.map +1 -1
  38. package/package.json +33 -77
  39. package/dist/affiliate.d.ts +0 -11
  40. package/dist/affiliate.d.ts.map +0 -1
  41. package/dist/affiliate.js +0 -10
  42. package/dist/affiliate.js.map +0 -1
  43. package/dist/billing.d.ts +0 -8
  44. package/dist/billing.d.ts.map +0 -1
  45. package/dist/billing.js +0 -7
  46. package/dist/billing.js.map +0 -1
  47. package/dist/email.d.ts +0 -9
  48. package/dist/email.d.ts.map +0 -1
  49. package/dist/email.js +0 -8
  50. package/dist/email.js.map +0 -1
  51. package/dist/generators/rls-exec-sql.sql +0 -57
  52. package/dist/generators.d.ts +0 -15
  53. package/dist/generators.d.ts.map +0 -1
  54. package/dist/generators.js +0 -12
  55. package/dist/generators.js.map +0 -1
  56. package/dist/mcp.d.ts +0 -8
  57. package/dist/mcp.d.ts.map +0 -1
  58. package/dist/mcp.js +0 -7
  59. package/dist/mcp.js.map +0 -1
  60. package/dist/planner.d.ts +0 -8
  61. package/dist/planner.d.ts.map +0 -1
  62. package/dist/planner.js +0 -7
  63. package/dist/planner.js.map +0 -1
  64. package/dist/shared/affiliate/AffiliateAttributionService.d.ts +0 -47
  65. package/dist/shared/affiliate/AffiliateAttributionService.d.ts.map +0 -1
  66. package/dist/shared/affiliate/AffiliateAttributionService.js +0 -308
  67. package/dist/shared/affiliate/AffiliateAttributionService.js.map +0 -1
  68. package/dist/shared/affiliate/AffiliateClickService.d.ts +0 -35
  69. package/dist/shared/affiliate/AffiliateClickService.d.ts.map +0 -1
  70. package/dist/shared/affiliate/AffiliateClickService.js +0 -87
  71. package/dist/shared/affiliate/AffiliateClickService.js.map +0 -1
  72. package/dist/shared/affiliate/affiliateFeatureConfig.d.ts +0 -11
  73. package/dist/shared/affiliate/affiliateFeatureConfig.d.ts.map +0 -1
  74. package/dist/shared/affiliate/affiliateFeatureConfig.js +0 -242
  75. package/dist/shared/affiliate/affiliateFeatureConfig.js.map +0 -1
  76. package/dist/shared/affiliate/index.d.ts +0 -11
  77. package/dist/shared/affiliate/index.d.ts.map +0 -1
  78. package/dist/shared/affiliate/index.js +0 -13
  79. package/dist/shared/affiliate/index.js.map +0 -1
  80. package/dist/shared/affiliate/routes.d.ts +0 -87
  81. package/dist/shared/affiliate/routes.d.ts.map +0 -1
  82. package/dist/shared/affiliate/routes.js +0 -404
  83. package/dist/shared/affiliate/routes.js.map +0 -1
  84. package/dist/shared/affiliate/types.d.ts +0 -170
  85. package/dist/shared/affiliate/types.d.ts.map +0 -1
  86. package/dist/shared/affiliate/types.js +0 -11
  87. package/dist/shared/affiliate/types.js.map +0 -1
  88. package/dist/shared/billing/BillingService.d.ts +0 -56
  89. package/dist/shared/billing/BillingService.d.ts.map +0 -1
  90. package/dist/shared/billing/BillingService.js +0 -588
  91. package/dist/shared/billing/BillingService.js.map +0 -1
  92. package/dist/shared/billing/SeatBillingService.d.ts +0 -106
  93. package/dist/shared/billing/SeatBillingService.d.ts.map +0 -1
  94. package/dist/shared/billing/SeatBillingService.js +0 -292
  95. package/dist/shared/billing/SeatBillingService.js.map +0 -1
  96. package/dist/shared/billing/index.d.ts +0 -30
  97. package/dist/shared/billing/index.d.ts.map +0 -1
  98. package/dist/shared/billing/index.js +0 -27
  99. package/dist/shared/billing/index.js.map +0 -1
  100. package/dist/shared/billing/routes.d.ts +0 -45
  101. package/dist/shared/billing/routes.d.ts.map +0 -1
  102. package/dist/shared/billing/routes.js +0 -184
  103. package/dist/shared/billing/routes.js.map +0 -1
  104. package/dist/shared/billing/seat-pricing.d.ts +0 -53
  105. package/dist/shared/billing/seat-pricing.d.ts.map +0 -1
  106. package/dist/shared/billing/seat-pricing.js +0 -81
  107. package/dist/shared/billing/seat-pricing.js.map +0 -1
  108. package/dist/shared/billing/types.d.ts +0 -109
  109. package/dist/shared/billing/types.d.ts.map +0 -1
  110. package/dist/shared/billing/types.js +0 -8
  111. package/dist/shared/billing/types.js.map +0 -1
  112. package/dist/shared/email/EmailService.d.ts +0 -64
  113. package/dist/shared/email/EmailService.d.ts.map +0 -1
  114. package/dist/shared/email/EmailService.js +0 -300
  115. package/dist/shared/email/EmailService.js.map +0 -1
  116. package/dist/shared/email/adminRoutes.d.ts +0 -30
  117. package/dist/shared/email/adminRoutes.d.ts.map +0 -1
  118. package/dist/shared/email/adminRoutes.js +0 -227
  119. package/dist/shared/email/adminRoutes.js.map +0 -1
  120. package/dist/shared/email/gmail.d.ts +0 -208
  121. package/dist/shared/email/gmail.d.ts.map +0 -1
  122. package/dist/shared/email/gmail.js +0 -626
  123. package/dist/shared/email/gmail.js.map +0 -1
  124. package/dist/shared/email/index.d.ts +0 -15
  125. package/dist/shared/email/index.d.ts.map +0 -1
  126. package/dist/shared/email/index.js +0 -18
  127. package/dist/shared/email/index.js.map +0 -1
  128. package/dist/shared/email/mailgun.d.ts +0 -18
  129. package/dist/shared/email/mailgun.d.ts.map +0 -1
  130. package/dist/shared/email/mailgun.js +0 -76
  131. package/dist/shared/email/mailgun.js.map +0 -1
  132. package/dist/shared/email/sanitize.d.ts +0 -25
  133. package/dist/shared/email/sanitize.d.ts.map +0 -1
  134. package/dist/shared/email/sanitize.js +0 -39
  135. package/dist/shared/email/sanitize.js.map +0 -1
  136. package/dist/shared/email/smtp.d.ts +0 -20
  137. package/dist/shared/email/smtp.d.ts.map +0 -1
  138. package/dist/shared/email/smtp.js +0 -53
  139. package/dist/shared/email/smtp.js.map +0 -1
  140. package/dist/shared/email/types.d.ts +0 -113
  141. package/dist/shared/email/types.d.ts.map +0 -1
  142. package/dist/shared/email/types.js +0 -7
  143. package/dist/shared/email/types.js.map +0 -1
  144. package/dist/shared/email/webhookRoutes.d.ts +0 -29
  145. package/dist/shared/email/webhookRoutes.d.ts.map +0 -1
  146. package/dist/shared/email/webhookRoutes.js +0 -125
  147. package/dist/shared/email/webhookRoutes.js.map +0 -1
  148. package/dist/shared/mcp/index.d.ts +0 -51
  149. package/dist/shared/mcp/index.d.ts.map +0 -1
  150. package/dist/shared/mcp/index.js +0 -51
  151. package/dist/shared/mcp/index.js.map +0 -1
  152. package/dist/shared/mcp/mcp-auth-routes.d.ts +0 -26
  153. package/dist/shared/mcp/mcp-auth-routes.d.ts.map +0 -1
  154. package/dist/shared/mcp/mcp-auth-routes.js +0 -141
  155. package/dist/shared/mcp/mcp-auth-routes.js.map +0 -1
  156. package/dist/shared/mcp/mcp-db.d.ts +0 -99
  157. package/dist/shared/mcp/mcp-db.d.ts.map +0 -1
  158. package/dist/shared/mcp/mcp-db.js +0 -106
  159. package/dist/shared/mcp/mcp-db.js.map +0 -1
  160. package/dist/shared/mcp/mcp-routes.d.ts +0 -29
  161. package/dist/shared/mcp/mcp-routes.d.ts.map +0 -1
  162. package/dist/shared/mcp/mcp-routes.js +0 -171
  163. package/dist/shared/mcp/mcp-routes.js.map +0 -1
  164. package/dist/shared/mcp/mcp-tokens-routes.d.ts +0 -35
  165. package/dist/shared/mcp/mcp-tokens-routes.d.ts.map +0 -1
  166. package/dist/shared/mcp/mcp-tokens-routes.js +0 -94
  167. package/dist/shared/mcp/mcp-tokens-routes.js.map +0 -1
  168. package/dist/shared/mcp/mcp-usage-routes.d.ts +0 -17
  169. package/dist/shared/mcp/mcp-usage-routes.d.ts.map +0 -1
  170. package/dist/shared/mcp/mcp-usage-routes.js +0 -81
  171. package/dist/shared/mcp/mcp-usage-routes.js.map +0 -1
  172. package/dist/shared/mcp/tenant-context.d.ts +0 -59
  173. package/dist/shared/mcp/tenant-context.d.ts.map +0 -1
  174. package/dist/shared/mcp/tenant-context.js +0 -136
  175. package/dist/shared/mcp/tenant-context.js.map +0 -1
  176. package/dist/shared/mcp/types.d.ts +0 -74
  177. package/dist/shared/mcp/types.d.ts.map +0 -1
  178. package/dist/shared/mcp/types.js +0 -7
  179. package/dist/shared/mcp/types.js.map +0 -1
  180. package/dist/shared/planner/GoogleCalendarService.d.ts +0 -137
  181. package/dist/shared/planner/GoogleCalendarService.d.ts.map +0 -1
  182. package/dist/shared/planner/GoogleCalendarService.js +0 -525
  183. package/dist/shared/planner/GoogleCalendarService.js.map +0 -1
  184. package/dist/shared/planner/PlannerService.d.ts +0 -264
  185. package/dist/shared/planner/PlannerService.d.ts.map +0 -1
  186. package/dist/shared/planner/PlannerService.js +0 -1393
  187. package/dist/shared/planner/PlannerService.js.map +0 -1
  188. package/dist/shared/planner/index.d.ts +0 -37
  189. package/dist/shared/planner/index.d.ts.map +0 -1
  190. package/dist/shared/planner/index.js +0 -35
  191. package/dist/shared/planner/index.js.map +0 -1
  192. package/dist/shared/planner/intervals.d.ts +0 -60
  193. package/dist/shared/planner/intervals.d.ts.map +0 -1
  194. package/dist/shared/planner/intervals.js +0 -141
  195. package/dist/shared/planner/intervals.js.map +0 -1
  196. package/dist/shared/planner/routes.d.ts +0 -69
  197. package/dist/shared/planner/routes.d.ts.map +0 -1
  198. package/dist/shared/planner/routes.js +0 -770
  199. package/dist/shared/planner/routes.js.map +0 -1
  200. package/dist/shared/planner/types.d.ts +0 -328
  201. package/dist/shared/planner/types.d.ts.map +0 -1
  202. package/dist/shared/planner/types.js +0 -9
  203. package/dist/shared/planner/types.js.map +0 -1
  204. package/dist/shared/storage/ImageProcessingService.d.ts +0 -32
  205. package/dist/shared/storage/ImageProcessingService.d.ts.map +0 -1
  206. package/dist/shared/storage/ImageProcessingService.js +0 -127
  207. package/dist/shared/storage/ImageProcessingService.js.map +0 -1
  208. package/dist/shared/storage/StorageProxyService.d.ts +0 -47
  209. package/dist/shared/storage/StorageProxyService.d.ts.map +0 -1
  210. package/dist/shared/storage/StorageProxyService.js +0 -196
  211. package/dist/shared/storage/StorageProxyService.js.map +0 -1
  212. package/dist/shared/storage/StorageUploadService.d.ts +0 -126
  213. package/dist/shared/storage/StorageUploadService.d.ts.map +0 -1
  214. package/dist/shared/storage/StorageUploadService.js +0 -206
  215. package/dist/shared/storage/StorageUploadService.js.map +0 -1
  216. package/dist/shared/storage/creative-urls.d.ts +0 -14
  217. package/dist/shared/storage/creative-urls.d.ts.map +0 -1
  218. package/dist/shared/storage/creative-urls.js +0 -30
  219. package/dist/shared/storage/creative-urls.js.map +0 -1
  220. package/dist/shared/storage/index.d.ts +0 -28
  221. package/dist/shared/storage/index.d.ts.map +0 -1
  222. package/dist/shared/storage/index.js +0 -27
  223. package/dist/shared/storage/index.js.map +0 -1
  224. package/dist/shared/storage/routes.d.ts +0 -42
  225. package/dist/shared/storage/routes.d.ts.map +0 -1
  226. package/dist/shared/storage/routes.js +0 -160
  227. package/dist/shared/storage/routes.js.map +0 -1
  228. package/dist/shared/storage/types.d.ts +0 -53
  229. package/dist/shared/storage/types.d.ts.map +0 -1
  230. package/dist/shared/storage/types.js +0 -2
  231. package/dist/shared/storage/types.js.map +0 -1
  232. package/dist/shared/telegram/index.d.ts +0 -4
  233. package/dist/shared/telegram/index.d.ts.map +0 -1
  234. package/dist/shared/telegram/index.js +0 -3
  235. package/dist/shared/telegram/index.js.map +0 -1
  236. package/dist/shared/telegram/routes.d.ts +0 -43
  237. package/dist/shared/telegram/routes.d.ts.map +0 -1
  238. package/dist/shared/telegram/routes.js +0 -868
  239. package/dist/shared/telegram/routes.js.map +0 -1
  240. package/dist/shared/telegram/types.d.ts +0 -168
  241. package/dist/shared/telegram/types.d.ts.map +0 -1
  242. package/dist/shared/telegram/types.js +0 -7
  243. package/dist/shared/telegram/types.js.map +0 -1
  244. package/dist/shared/telegram/utils.d.ts +0 -44
  245. package/dist/shared/telegram/utils.d.ts.map +0 -1
  246. package/dist/shared/telegram/utils.js +0 -121
  247. package/dist/shared/telegram/utils.js.map +0 -1
  248. package/dist/storage.d.ts +0 -9
  249. package/dist/storage.d.ts.map +0 -1
  250. package/dist/storage.js +0 -8
  251. package/dist/storage.js.map +0 -1
  252. package/dist/telemetry.d.ts +0 -9
  253. package/dist/telemetry.d.ts.map +0 -1
  254. package/dist/telemetry.js +0 -8
  255. package/dist/telemetry.js.map +0 -1
  256. package/scripts/postinstall.js +0 -79
  257. package/src/shared/affiliate/migrations/001_create_affiliates.sql +0 -49
  258. package/src/shared/affiliate/migrations/002_create_affiliate_commissions.sql +0 -31
  259. package/src/shared/affiliate/migrations/003_create_affiliate_clicks.sql +0 -26
  260. package/src/shared/affiliate/migrations/004_create_affiliate_payments.sql +0 -34
  261. package/src/shared/affiliate/migrations/005_create_affiliate_tier_history.sql +0 -19
  262. package/src/shared/affiliate/migrations/006_create_affiliate_rpc_functions.sql +0 -209
  263. package/src/shared/affiliate/migrations/007_create_affiliate_rls_policies.sql +0 -123
  264. package/src/shared/billing/migrations/00000000000001_billing.sql +0 -114
  265. package/src/shared/email/migrations/000_create_email_logs.sql +0 -27
  266. package/src/shared/email/migrations/001_create_email_templates.sql +0 -27
  267. package/src/shared/email/migrations/002_add_rls_baseline_policies.sql +0 -37
  268. package/src/shared/email/migrations/003_create_gmail_accounts.sql +0 -82
  269. package/src/shared/email/migrations/004_add_email_logs_tracking_columns.sql +0 -15
  270. package/src/shared/mcp/migrations/001_mcp_api_tokens.sql +0 -21
  271. package/src/shared/mcp/migrations/002_mcp_audit_log.sql +0 -16
@@ -1,184 +0,0 @@
1
- /**
2
- * Billing Route Helpers — factory functions for standard billing endpoints
3
- *
4
- * Usage:
5
- * ```typescript
6
- * import { addBillingRoutes, addBillingWebhookRoutes } from '@soulbatical/tetra-core';
7
- *
8
- * // Authenticated routes (mount behind auth middleware)
9
- * const billingRouter = Router();
10
- * billingRouter.use(authenticateToken);
11
- * addBillingRoutes(billingRouter, { config, getOrgId, getBillingStatus });
12
- *
13
- * // Webhook routes (no auth, raw body for Stripe)
14
- * addBillingWebhookRoutes(app, { config, basePath: '/api/billing/webhook' });
15
- * ```
16
- */
17
- import { BillingService } from './BillingService.js';
18
- import { RFC7807ErrorResponse } from '../rfc7807ErrorResponse.js';
19
- import { createLogger } from '../../utils/logger.js';
20
- const logger = createLogger('billing:routes');
21
- const DEFAULT_MOLLIE_IPS = [
22
- '87.233.217.240', '87.233.217.241', '87.233.217.242', '87.233.217.243',
23
- '87.233.217.244', '87.233.217.245', '87.233.217.246', '87.233.217.247',
24
- ];
25
- /**
26
- * Add authenticated billing routes to a router.
27
- *
28
- * Adds:
29
- * - POST /checkout — Stripe checkout
30
- * - POST /checkout/mollie — Mollie/iDEAL checkout
31
- * - POST /portal — Stripe customer portal
32
- * - GET /status — Billing status
33
- * - GET /invoices — Stripe invoices
34
- */
35
- export function addBillingRoutes(router, options) {
36
- const service = new BillingService(options.config);
37
- // POST /checkout — Stripe
38
- router.post('/checkout', async (req, res) => {
39
- try {
40
- const orgId = options.getOrgId(req);
41
- if (!orgId) {
42
- RFC7807ErrorResponse.badRequest(res, 'No active organization.');
43
- return;
44
- }
45
- const { plan, cycle = 'monthly' } = req.body;
46
- if (!plan || !service.getPlan(plan)) {
47
- RFC7807ErrorResponse.badRequest(res, 'Invalid plan.');
48
- return;
49
- }
50
- const result = await service.createStripeCheckout(orgId, plan, cycle);
51
- res.json({ success: true, data: result });
52
- }
53
- catch (err) {
54
- logger.error({ error: err }, 'Stripe checkout error');
55
- RFC7807ErrorResponse.internalError(res, err.message || 'Checkout failed.');
56
- }
57
- });
58
- // POST /checkout/mollie — iDEAL
59
- router.post('/checkout/mollie', async (req, res) => {
60
- try {
61
- const orgId = options.getOrgId(req);
62
- if (!orgId) {
63
- RFC7807ErrorResponse.badRequest(res, 'No active organization.');
64
- return;
65
- }
66
- const { plan, cycle = 'monthly' } = req.body;
67
- if (!plan || !service.getPlan(plan)) {
68
- RFC7807ErrorResponse.badRequest(res, 'Invalid plan.');
69
- return;
70
- }
71
- const result = await service.createMollieCheckout(orgId, plan, cycle);
72
- res.json({ success: true, data: result });
73
- }
74
- catch (err) {
75
- logger.error({ error: err }, 'Mollie checkout error');
76
- RFC7807ErrorResponse.internalError(res, err.message || 'Checkout failed.');
77
- }
78
- });
79
- // POST /portal — Stripe Customer Portal
80
- router.post('/portal', async (req, res) => {
81
- try {
82
- const orgId = options.getOrgId(req);
83
- if (!orgId) {
84
- RFC7807ErrorResponse.badRequest(res, 'No active organization.');
85
- return;
86
- }
87
- const result = await service.createStripePortal(orgId);
88
- res.json({ success: true, data: result });
89
- }
90
- catch (err) {
91
- logger.error({ error: err }, 'Portal error');
92
- RFC7807ErrorResponse.internalError(res, err.message || 'Portal failed.');
93
- }
94
- });
95
- // GET /status — Billing status
96
- router.get('/status', async (req, res) => {
97
- try {
98
- const orgId = options.getOrgId(req);
99
- if (!orgId) {
100
- RFC7807ErrorResponse.badRequest(res, 'No active organization.');
101
- return;
102
- }
103
- const status = await options.getBillingStatus(orgId);
104
- res.json({ success: true, data: status });
105
- }
106
- catch (err) {
107
- logger.error({ error: err }, 'Status error');
108
- RFC7807ErrorResponse.internalError(res, err.message || 'Status failed.');
109
- }
110
- });
111
- // GET /invoices — Stripe invoices
112
- router.get('/invoices', async (req, res) => {
113
- try {
114
- const orgId = options.getOrgId(req);
115
- if (!orgId) {
116
- RFC7807ErrorResponse.badRequest(res, 'No active organization.');
117
- return;
118
- }
119
- const invoices = await service.getInvoices(orgId);
120
- res.json({ success: true, data: { invoices } });
121
- }
122
- catch (err) {
123
- logger.error({ error: err }, 'Invoices error');
124
- RFC7807ErrorResponse.internalError(res, err.message || 'Invoices failed.');
125
- }
126
- });
127
- return service;
128
- }
129
- /**
130
- * Add webhook routes for Stripe and Mollie.
131
- *
132
- * IMPORTANT: Stripe needs raw body. Configure express.raw() for the Stripe webhook path
133
- * BEFORE mounting these routes.
134
- *
135
- * Adds:
136
- * - POST {basePath}/stripe — Stripe webhook (signature verified)
137
- * - POST {basePath}/mollie — Mollie webhook (IP whitelist in production)
138
- */
139
- export function addBillingWebhookRoutes(router, options) {
140
- const service = new BillingService(options.config);
141
- const basePath = options.basePath || '/webhook';
142
- const mollieIPs = options.config.mollieWebhookIPs || DEFAULT_MOLLIE_IPS;
143
- // POST /webhook/stripe
144
- router.post(`${basePath}/stripe`, async (req, res) => {
145
- try {
146
- const sig = req.headers['stripe-signature'];
147
- if (!sig) {
148
- RFC7807ErrorResponse.badRequest(res, 'Missing signature.');
149
- return;
150
- }
151
- // Return 200 immediately, process async
152
- res.json({ success: true, data: { received: true } });
153
- await service.handleStripeWebhook(req.body, sig);
154
- }
155
- catch (err) {
156
- logger.error({ error: err }, 'Stripe webhook error');
157
- if (!res.headersSent) {
158
- RFC7807ErrorResponse.badRequest(res, err.message || 'Webhook failed.');
159
- }
160
- }
161
- });
162
- // POST /webhook/mollie
163
- router.post(`${basePath}/mollie`, async (req, res) => {
164
- // IP whitelist (production only)
165
- if (process.env.NODE_ENV === 'production') {
166
- const clientIp = req.headers['x-forwarded-for']?.split(',')[0]?.trim() || req.ip;
167
- if (!mollieIPs.includes(clientIp || '')) {
168
- logger.warn({ clientIp }, 'Mollie webhook from unauthorized IP');
169
- RFC7807ErrorResponse.forbidden(res, 'Not authorized.');
170
- return;
171
- }
172
- }
173
- // Return 200 immediately (Mollie requirement)
174
- res.status(200).send('OK');
175
- try {
176
- await service.handleMollieWebhook(req.body?.id);
177
- }
178
- catch (err) {
179
- logger.error({ error: err }, 'Mollie webhook error');
180
- }
181
- });
182
- return service;
183
- }
184
- //# sourceMappingURL=routes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/shared/billing/routes.ts"],"names":[],"mappings":"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"}
@@ -1,53 +0,0 @@
1
- /**
2
- * Seat-based pricing calculator
3
- *
4
- * Shared logic for per-user pricing with volume discounts and tier minimums.
5
- * Used by: website pricing calculator, SeatBillingService, license validation.
6
- *
7
- * @module @soulbatical/tetra-core/billing
8
- */
9
- export interface SeatTier {
10
- /** Minimum users for this tier (inclusive) */
11
- min: number;
12
- /** Maximum users for this tier (inclusive, Infinity for last tier) */
13
- max: number;
14
- /** Price per user per month in EUR */
15
- pricePerUser: number;
16
- /** Minimum monthly charge for this tier (prevents price dips at tier boundary) */
17
- minimum: number;
18
- }
19
- /** Default Tetra seat pricing tiers */
20
- export declare const DEFAULT_SEAT_TIERS: SeatTier[];
21
- export interface SeatPriceResult {
22
- /** Total monthly price in EUR */
23
- monthlyPrice: number;
24
- /** Total yearly price in EUR */
25
- yearlyPrice: number;
26
- /** Number of free users */
27
- freeUsers: number;
28
- /** Number of paid users */
29
- paidUsers: number;
30
- /** Effective price per user (total / users) */
31
- effectivePricePerUser: number;
32
- /** Which tier the user count falls in */
33
- tierIndex: number;
34
- /** The tier's listed price per user */
35
- tierPricePerUser: number;
36
- /** Whether the minimum was applied */
37
- minimumApplied: boolean;
38
- }
39
- /**
40
- * Calculate the monthly price for a given number of seat users.
41
- *
42
- * Rules:
43
- * - First 10 users are free
44
- * - Price per user decreases with volume
45
- * - Each tier has a minimum monthly charge (prevents price dips at boundary)
46
- * - For 1000+ users, the last tier rate applies
47
- */
48
- export declare function calculateSeatPrice(users: number, tiers?: SeatTier[]): SeatPriceResult;
49
- /**
50
- * Convert seat price to Stripe-compatible amount in cents.
51
- */
52
- export declare function seatPriceToCents(monthlyPrice: number): number;
53
- //# sourceMappingURL=seat-pricing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seat-pricing.d.ts","sourceRoot":"","sources":["../../../src/shared/billing/seat-pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,QAAQ;IACvB,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,EAAE,QAAQ,EAMxC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,QAAQ,EAAuB,GACrC,eAAe,CAuDjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE7D"}
@@ -1,81 +0,0 @@
1
- /**
2
- * Seat-based pricing calculator
3
- *
4
- * Shared logic for per-user pricing with volume discounts and tier minimums.
5
- * Used by: website pricing calculator, SeatBillingService, license validation.
6
- *
7
- * @module @soulbatical/tetra-core/billing
8
- */
9
- /** Default Tetra seat pricing tiers */
10
- export const DEFAULT_SEAT_TIERS = [
11
- { min: 1, max: 10, pricePerUser: 0, minimum: 0 },
12
- { min: 11, max: 100, pricePerUser: 3.90, minimum: 0 },
13
- { min: 101, max: 250, pricePerUser: 2.90, minimum: 351 },
14
- { min: 251, max: 500, pricePerUser: 1.90, minimum: 725 },
15
- { min: 501, max: 1000, pricePerUser: 0.90, minimum: 950 },
16
- ];
17
- /**
18
- * Calculate the monthly price for a given number of seat users.
19
- *
20
- * Rules:
21
- * - First 10 users are free
22
- * - Price per user decreases with volume
23
- * - Each tier has a minimum monthly charge (prevents price dips at boundary)
24
- * - For 1000+ users, the last tier rate applies
25
- */
26
- export function calculateSeatPrice(users, tiers = DEFAULT_SEAT_TIERS) {
27
- if (users <= 0) {
28
- return {
29
- monthlyPrice: 0,
30
- yearlyPrice: 0,
31
- freeUsers: 0,
32
- paidUsers: 0,
33
- effectivePricePerUser: 0,
34
- tierIndex: 0,
35
- tierPricePerUser: 0,
36
- minimumApplied: false,
37
- };
38
- }
39
- // Find the tier
40
- let tierIndex = 0;
41
- let tierPricePerUser = 0;
42
- for (let i = 0; i < tiers.length; i++) {
43
- if (users >= tiers[i].min && users <= tiers[i].max) {
44
- tierIndex = i;
45
- tierPricePerUser = tiers[i].pricePerUser;
46
- break;
47
- }
48
- }
49
- // Beyond last tier: use last tier's rate
50
- if (users > tiers[tiers.length - 1].max) {
51
- const lastTier = tiers[tiers.length - 1];
52
- tierIndex = tiers.length - 1;
53
- tierPricePerUser = lastTier.pricePerUser;
54
- }
55
- const tier = tiers[tierIndex];
56
- const freeUsers = Math.min(users, tiers[0].max);
57
- const paidUsers = Math.max(0, users - tiers[0].max);
58
- // Calculate raw price
59
- const rawPrice = users * tierPricePerUser;
60
- // Apply minimum
61
- const minimum = tier?.minimum ?? 0;
62
- const minimumApplied = rawPrice < minimum && minimum > 0;
63
- const monthlyPrice = Math.max(rawPrice, minimum);
64
- return {
65
- monthlyPrice: Math.round(monthlyPrice * 100) / 100,
66
- yearlyPrice: Math.round(monthlyPrice * 12 * 100) / 100,
67
- freeUsers,
68
- paidUsers,
69
- effectivePricePerUser: users > 0 ? Math.round((monthlyPrice / users) * 100) / 100 : 0,
70
- tierIndex,
71
- tierPricePerUser,
72
- minimumApplied,
73
- };
74
- }
75
- /**
76
- * Convert seat price to Stripe-compatible amount in cents.
77
- */
78
- export function seatPriceToCents(monthlyPrice) {
79
- return Math.round(monthlyPrice * 100);
80
- }
81
- //# sourceMappingURL=seat-pricing.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seat-pricing.js","sourceRoot":"","sources":["../../../src/shared/billing/seat-pricing.ts"],"names":[],"mappings":"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"}
@@ -1,109 +0,0 @@
1
- /**
2
- * Billing types — shared across all Tetra projects
3
- *
4
- * Projects provide their own plan configs via BillingConfig.
5
- * The billing module handles Stripe + Mollie checkout, webhooks, and subscription lifecycle.
6
- */
7
- import type { SupabaseClient } from '@supabase/supabase-js';
8
- export interface PlanConfig {
9
- /** Display name */
10
- name: string;
11
- /** Monthly price in EUR cents (1900 = €19.00) */
12
- priceMonthCents: number;
13
- /** Yearly price in EUR cents (19000 = €190.00) */
14
- priceYearCents: number;
15
- /** Stripe price ID for monthly billing */
16
- stripePriceMonthly: string;
17
- /** Stripe price ID for yearly billing */
18
- stripePriceYearly: string;
19
- /** Mollie amount string for monthly (e.g. "19.00") */
20
- mollieAmountMonthly: string;
21
- /** Mollie amount string for yearly (e.g. "190.00") */
22
- mollieAmountYearly: string;
23
- }
24
- export type BillingCycle = 'monthly' | 'yearly';
25
- export type SubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid';
26
- export type BillingProvider = 'stripe' | 'mollie';
27
- export interface BillingConfig {
28
- /** Plan definitions keyed by plan slug (e.g. { starter: {...}, pro: {...} }) */
29
- plans: Record<string, PlanConfig>;
30
- /** Stripe configuration */
31
- stripe: {
32
- secretKey: string;
33
- webhookSecret: string;
34
- };
35
- /** Mollie configuration */
36
- mollie: {
37
- apiKey: string;
38
- webhookBaseUrl: string;
39
- };
40
- /** Frontend URL for redirect after checkout */
41
- frontendUrl: string;
42
- /** Number of trial days for Stripe subscriptions (0 = no trial) */
43
- trialDays: number;
44
- /** Success redirect path (appended to frontendUrl) */
45
- successPath: string;
46
- /** Cancel redirect path (appended to frontendUrl) */
47
- cancelPath: string;
48
- /** Metadata key prefix for org ID in Stripe/Mollie metadata (default: "org_id") */
49
- orgIdMetadataKey?: string;
50
- /** Product name for Mollie payment descriptions (e.g. "VinciFox", "Agentrook") */
51
- productName: string;
52
- /** Function to get a system-level DB client (bypasses RLS) */
53
- getSystemDB: () => SupabaseClient;
54
- /** Function to get a webhook-level DB client (bypasses RLS, for webhook handlers) */
55
- getWebhookDB: (context: string) => SupabaseClient;
56
- /** Optional: callback after successful subscription creation */
57
- onSubscriptionCreated?: (orgId: string, plan: string, provider: BillingProvider) => Promise<void>;
58
- /** Optional: callback after subscription canceled */
59
- onSubscriptionCanceled?: (orgId: string) => Promise<void>;
60
- /** Optional: callback after payment failed */
61
- onPaymentFailed?: (orgId: string) => Promise<void>;
62
- /** Mollie webhook IP whitelist (production only). Defaults to standard Mollie IPs. */
63
- mollieWebhookIPs?: string[];
64
- }
65
- export interface SubscriptionRecord {
66
- id: string;
67
- organization_id: string;
68
- provider: BillingProvider;
69
- external_subscription_id: string | null;
70
- external_customer_id: string | null;
71
- plan: string;
72
- billing_cycle: BillingCycle;
73
- price_amount_cents: number;
74
- status: SubscriptionStatus;
75
- trial_end: string | null;
76
- current_period_start: string;
77
- current_period_end: string;
78
- cancel_at: string | null;
79
- canceled_at: string | null;
80
- ended_at: string | null;
81
- created_at: string;
82
- updated_at: string;
83
- }
84
- export interface BillingStatusResponse {
85
- plan: string;
86
- limits: Record<string, unknown>;
87
- usage: Record<string, number>;
88
- subscription: {
89
- id: string;
90
- provider: BillingProvider;
91
- status: SubscriptionStatus;
92
- billing_cycle: BillingCycle;
93
- trial_end: string | null;
94
- current_period_start: string;
95
- current_period_end: string;
96
- cancel_at: string | null;
97
- canceled_at: string | null;
98
- } | null;
99
- has_stripe: boolean;
100
- }
101
- export interface BillingRouteOptions {
102
- /** The billing configuration */
103
- config: BillingConfig;
104
- /** Function to resolve orgId from authenticated request */
105
- getOrgId: (req: any) => string | undefined;
106
- /** Function to get billing status for an org (plan, limits, usage) */
107
- getBillingStatus: (orgId: string) => Promise<BillingStatusResponse>;
108
- }
109
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shared/billing/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,WAAW,UAAU;IACzB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yCAAyC;IACzC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,CAAC;AAChD,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAC5F,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAIlD,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAElC,2BAA2B;IAC3B,MAAM,EAAE;QACN,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF,2BAA2B;IAC3B,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IAEpB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAElB,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IAEpB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IAEnB,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;IAEpB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,cAAc,CAAC;IAElC,qFAAqF;IACrF,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,cAAc,CAAC;IAElD,gEAAgE;IAChE,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElG,qDAAqD;IACrD,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D,8CAA8C;IAC9C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,sFAAsF;IACtF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAID,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,YAAY,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,YAAY,EAAE;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,eAAe,CAAC;QAC1B,MAAM,EAAE,kBAAkB,CAAC;QAC3B,aAAa,EAAE,YAAY,CAAC;QAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,GAAG,IAAI,CAAC;IACT,UAAU,EAAE,OAAO,CAAC;CACrB;AAID,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,MAAM,EAAE,aAAa,CAAC;IAEtB,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;IAE3C,sEAAsE;IACtE,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACrE"}
@@ -1,8 +0,0 @@
1
- /**
2
- * Billing types — shared across all Tetra projects
3
- *
4
- * Projects provide their own plan configs via BillingConfig.
5
- * The billing module handles Stripe + Mollie checkout, webhooks, and subscription lifecycle.
6
- */
7
- export {};
8
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/shared/billing/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,64 +0,0 @@
1
- /**
2
- * EmailService — Core service for sending templated emails.
3
- *
4
- * Template lookup with language + org fallback, Handlebars rendering,
5
- * DB logging, and multi-transport delivery (Gmail, SMTP, Mailgun).
6
- *
7
- * @module @soulbatical/tetra-core/email
8
- */
9
- import type { SupabaseClient } from '@supabase/supabase-js';
10
- import type { EmailConfig, SendEmailOpts } from './types.js';
11
- export declare class EmailService {
12
- private supabase;
13
- private config;
14
- private templateCache;
15
- constructor(supabase: SupabaseClient, config: EmailConfig);
16
- /**
17
- * Send a templated email.
18
- *
19
- * Template lookup order:
20
- * 1. slug + language + organization_id (org-specific translation)
21
- * 2. slug + language + org IS NULL (system default in requested language)
22
- * 3. slug + 'en' + org IS NULL (English fallback)
23
- * 4. fallbackSubject / fallbackHtml from code
24
- */
25
- send(opts: SendEmailOpts): Promise<{
26
- success: boolean;
27
- logId?: string;
28
- }>;
29
- /**
30
- * Clear template cache. Call after template is updated via admin UI.
31
- */
32
- clearCache(slug?: string): void;
33
- /**
34
- * Resolve transport and send email.
35
- * Priority: explicit config.transport > auto-detect (gmail > smtp > mailgun).
36
- */
37
- private deliver;
38
- /**
39
- * Send via Gmail API using stored OAuth tokens.
40
- */
41
- private deliverViaGmail;
42
- private resolveTransport;
43
- /**
44
- * Template lookup with language + org fallback chain.
45
- * Results are cached for 5 minutes.
46
- */
47
- private loadTemplate;
48
- private getCached;
49
- private setCache;
50
- /**
51
- * Render a Handlebars template string with variables.
52
- * Rejects templates with triple-brace {{{…}}} syntax to prevent escaping bypass.
53
- */
54
- private render;
55
- /**
56
- * Create a pending email log entry.
57
- */
58
- private createLog;
59
- /**
60
- * Update an email log entry after send attempt.
61
- */
62
- private updateLog;
63
- }
64
- //# sourceMappingURL=EmailService.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EmailService.d.ts","sourceRoot":"","sources":["../../../src/shared/email/EmailService.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAqD,MAAM,YAAY,CAAC;AAahH,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IAJhB,OAAO,CAAC,aAAa,CAAiC;gBAG5C,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,WAAW;IAG7B;;;;;;;;OAQG;IACG,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAsD9E;;OAEG;IACH,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAa/B;;;OAGG;YACW,OAAO;IA6CrB;;OAEG;YACW,eAAe;IAmC7B,OAAO,CAAC,gBAAgB;IAOxB;;;OAGG;YACW,YAAY;IAqE1B,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,QAAQ;IAIhB;;;OAGG;IACH,OAAO,CAAC,MAAM;IAQd;;OAEG;YACW,SAAS;IA0CvB;;OAEG;YACW,SAAS;CAkBxB"}