@soulbatical/tetra-core 0.10.5 → 0.11.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 (251) hide show
  1. package/README.md +34 -6
  2. package/dist/core/createApp.d.ts +1 -1
  3. package/dist/core/createApp.d.ts.map +1 -1
  4. package/dist/frontend/sentry.d.ts +1 -1
  5. package/dist/frontend/sentry.js +1 -1
  6. package/dist/frontend/storage/StorageDropzone.d.ts +1 -1
  7. package/dist/frontend/storage/StorageDropzone.js +1 -1
  8. package/dist/frontend/storage/storageUrl.d.ts +1 -1
  9. package/dist/frontend/storage/storageUrl.js +1 -1
  10. package/dist/generators/rls-checker.d.ts +1 -1
  11. package/dist/generators/rls-checker.js +1 -1
  12. package/dist/generators/rls-exec-sql.d.ts +1 -1
  13. package/dist/generators/rls-exec-sql.js +1 -1
  14. package/dist/generators/rpc/index.d.ts +1 -1
  15. package/dist/generators/rpc/index.js +1 -1
  16. package/dist/index.d.ts +0 -6
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3 -9
  19. package/dist/index.js.map +1 -1
  20. package/dist/middleware/securityMiddleware.d.ts +1 -1
  21. package/dist/middleware/securityMiddleware.d.ts.map +1 -1
  22. package/dist/utils/logger.d.ts.map +1 -1
  23. package/dist/utils/logger.js +12 -1
  24. package/dist/utils/logger.js.map +1 -1
  25. package/package.json +32 -43
  26. package/dist/affiliate.d.ts +0 -11
  27. package/dist/affiliate.d.ts.map +0 -1
  28. package/dist/affiliate.js +0 -10
  29. package/dist/affiliate.js.map +0 -1
  30. package/dist/billing.d.ts +0 -8
  31. package/dist/billing.d.ts.map +0 -1
  32. package/dist/billing.js +0 -7
  33. package/dist/billing.js.map +0 -1
  34. package/dist/email.d.ts +0 -9
  35. package/dist/email.d.ts.map +0 -1
  36. package/dist/email.js +0 -8
  37. package/dist/email.js.map +0 -1
  38. package/dist/generators/rls-exec-sql.sql +0 -57
  39. package/dist/generators.d.ts +0 -9
  40. package/dist/generators.d.ts.map +0 -1
  41. package/dist/generators.js +0 -8
  42. package/dist/generators.js.map +0 -1
  43. package/dist/mcp.d.ts +0 -8
  44. package/dist/mcp.d.ts.map +0 -1
  45. package/dist/mcp.js +0 -7
  46. package/dist/mcp.js.map +0 -1
  47. package/dist/planner.d.ts +0 -8
  48. package/dist/planner.d.ts.map +0 -1
  49. package/dist/planner.js +0 -7
  50. package/dist/planner.js.map +0 -1
  51. package/dist/shared/affiliate/AffiliateAttributionService.d.ts +0 -47
  52. package/dist/shared/affiliate/AffiliateAttributionService.d.ts.map +0 -1
  53. package/dist/shared/affiliate/AffiliateAttributionService.js +0 -308
  54. package/dist/shared/affiliate/AffiliateAttributionService.js.map +0 -1
  55. package/dist/shared/affiliate/AffiliateClickService.d.ts +0 -35
  56. package/dist/shared/affiliate/AffiliateClickService.d.ts.map +0 -1
  57. package/dist/shared/affiliate/AffiliateClickService.js +0 -87
  58. package/dist/shared/affiliate/AffiliateClickService.js.map +0 -1
  59. package/dist/shared/affiliate/affiliateFeatureConfig.d.ts +0 -11
  60. package/dist/shared/affiliate/affiliateFeatureConfig.d.ts.map +0 -1
  61. package/dist/shared/affiliate/affiliateFeatureConfig.js +0 -242
  62. package/dist/shared/affiliate/affiliateFeatureConfig.js.map +0 -1
  63. package/dist/shared/affiliate/index.d.ts +0 -11
  64. package/dist/shared/affiliate/index.d.ts.map +0 -1
  65. package/dist/shared/affiliate/index.js +0 -13
  66. package/dist/shared/affiliate/index.js.map +0 -1
  67. package/dist/shared/affiliate/routes.d.ts +0 -87
  68. package/dist/shared/affiliate/routes.d.ts.map +0 -1
  69. package/dist/shared/affiliate/routes.js +0 -404
  70. package/dist/shared/affiliate/routes.js.map +0 -1
  71. package/dist/shared/affiliate/types.d.ts +0 -170
  72. package/dist/shared/affiliate/types.d.ts.map +0 -1
  73. package/dist/shared/affiliate/types.js +0 -11
  74. package/dist/shared/affiliate/types.js.map +0 -1
  75. package/dist/shared/billing/BillingService.d.ts +0 -56
  76. package/dist/shared/billing/BillingService.d.ts.map +0 -1
  77. package/dist/shared/billing/BillingService.js +0 -588
  78. package/dist/shared/billing/BillingService.js.map +0 -1
  79. package/dist/shared/billing/SeatBillingService.d.ts +0 -106
  80. package/dist/shared/billing/SeatBillingService.d.ts.map +0 -1
  81. package/dist/shared/billing/SeatBillingService.js +0 -292
  82. package/dist/shared/billing/SeatBillingService.js.map +0 -1
  83. package/dist/shared/billing/index.d.ts +0 -30
  84. package/dist/shared/billing/index.d.ts.map +0 -1
  85. package/dist/shared/billing/index.js +0 -27
  86. package/dist/shared/billing/index.js.map +0 -1
  87. package/dist/shared/billing/routes.d.ts +0 -45
  88. package/dist/shared/billing/routes.d.ts.map +0 -1
  89. package/dist/shared/billing/routes.js +0 -184
  90. package/dist/shared/billing/routes.js.map +0 -1
  91. package/dist/shared/billing/seat-pricing.d.ts +0 -53
  92. package/dist/shared/billing/seat-pricing.d.ts.map +0 -1
  93. package/dist/shared/billing/seat-pricing.js +0 -81
  94. package/dist/shared/billing/seat-pricing.js.map +0 -1
  95. package/dist/shared/billing/types.d.ts +0 -109
  96. package/dist/shared/billing/types.d.ts.map +0 -1
  97. package/dist/shared/billing/types.js +0 -8
  98. package/dist/shared/billing/types.js.map +0 -1
  99. package/dist/shared/email/EmailService.d.ts +0 -64
  100. package/dist/shared/email/EmailService.d.ts.map +0 -1
  101. package/dist/shared/email/EmailService.js +0 -300
  102. package/dist/shared/email/EmailService.js.map +0 -1
  103. package/dist/shared/email/adminRoutes.d.ts +0 -30
  104. package/dist/shared/email/adminRoutes.d.ts.map +0 -1
  105. package/dist/shared/email/adminRoutes.js +0 -227
  106. package/dist/shared/email/adminRoutes.js.map +0 -1
  107. package/dist/shared/email/gmail.d.ts +0 -208
  108. package/dist/shared/email/gmail.d.ts.map +0 -1
  109. package/dist/shared/email/gmail.js +0 -626
  110. package/dist/shared/email/gmail.js.map +0 -1
  111. package/dist/shared/email/index.d.ts +0 -15
  112. package/dist/shared/email/index.d.ts.map +0 -1
  113. package/dist/shared/email/index.js +0 -18
  114. package/dist/shared/email/index.js.map +0 -1
  115. package/dist/shared/email/mailgun.d.ts +0 -18
  116. package/dist/shared/email/mailgun.d.ts.map +0 -1
  117. package/dist/shared/email/mailgun.js +0 -76
  118. package/dist/shared/email/mailgun.js.map +0 -1
  119. package/dist/shared/email/sanitize.d.ts +0 -25
  120. package/dist/shared/email/sanitize.d.ts.map +0 -1
  121. package/dist/shared/email/sanitize.js +0 -39
  122. package/dist/shared/email/sanitize.js.map +0 -1
  123. package/dist/shared/email/smtp.d.ts +0 -20
  124. package/dist/shared/email/smtp.d.ts.map +0 -1
  125. package/dist/shared/email/smtp.js +0 -53
  126. package/dist/shared/email/smtp.js.map +0 -1
  127. package/dist/shared/email/types.d.ts +0 -113
  128. package/dist/shared/email/types.d.ts.map +0 -1
  129. package/dist/shared/email/types.js +0 -7
  130. package/dist/shared/email/types.js.map +0 -1
  131. package/dist/shared/email/webhookRoutes.d.ts +0 -29
  132. package/dist/shared/email/webhookRoutes.d.ts.map +0 -1
  133. package/dist/shared/email/webhookRoutes.js +0 -125
  134. package/dist/shared/email/webhookRoutes.js.map +0 -1
  135. package/dist/shared/mcp/index.d.ts +0 -51
  136. package/dist/shared/mcp/index.d.ts.map +0 -1
  137. package/dist/shared/mcp/index.js +0 -51
  138. package/dist/shared/mcp/index.js.map +0 -1
  139. package/dist/shared/mcp/mcp-auth-routes.d.ts +0 -26
  140. package/dist/shared/mcp/mcp-auth-routes.d.ts.map +0 -1
  141. package/dist/shared/mcp/mcp-auth-routes.js +0 -141
  142. package/dist/shared/mcp/mcp-auth-routes.js.map +0 -1
  143. package/dist/shared/mcp/mcp-db.d.ts +0 -99
  144. package/dist/shared/mcp/mcp-db.d.ts.map +0 -1
  145. package/dist/shared/mcp/mcp-db.js +0 -106
  146. package/dist/shared/mcp/mcp-db.js.map +0 -1
  147. package/dist/shared/mcp/mcp-routes.d.ts +0 -29
  148. package/dist/shared/mcp/mcp-routes.d.ts.map +0 -1
  149. package/dist/shared/mcp/mcp-routes.js +0 -171
  150. package/dist/shared/mcp/mcp-routes.js.map +0 -1
  151. package/dist/shared/mcp/mcp-tokens-routes.d.ts +0 -35
  152. package/dist/shared/mcp/mcp-tokens-routes.d.ts.map +0 -1
  153. package/dist/shared/mcp/mcp-tokens-routes.js +0 -94
  154. package/dist/shared/mcp/mcp-tokens-routes.js.map +0 -1
  155. package/dist/shared/mcp/mcp-usage-routes.d.ts +0 -17
  156. package/dist/shared/mcp/mcp-usage-routes.d.ts.map +0 -1
  157. package/dist/shared/mcp/mcp-usage-routes.js +0 -81
  158. package/dist/shared/mcp/mcp-usage-routes.js.map +0 -1
  159. package/dist/shared/mcp/tenant-context.d.ts +0 -59
  160. package/dist/shared/mcp/tenant-context.d.ts.map +0 -1
  161. package/dist/shared/mcp/tenant-context.js +0 -136
  162. package/dist/shared/mcp/tenant-context.js.map +0 -1
  163. package/dist/shared/mcp/types.d.ts +0 -74
  164. package/dist/shared/mcp/types.d.ts.map +0 -1
  165. package/dist/shared/mcp/types.js +0 -7
  166. package/dist/shared/mcp/types.js.map +0 -1
  167. package/dist/shared/planner/GoogleCalendarService.d.ts +0 -137
  168. package/dist/shared/planner/GoogleCalendarService.d.ts.map +0 -1
  169. package/dist/shared/planner/GoogleCalendarService.js +0 -525
  170. package/dist/shared/planner/GoogleCalendarService.js.map +0 -1
  171. package/dist/shared/planner/PlannerService.d.ts +0 -264
  172. package/dist/shared/planner/PlannerService.d.ts.map +0 -1
  173. package/dist/shared/planner/PlannerService.js +0 -1393
  174. package/dist/shared/planner/PlannerService.js.map +0 -1
  175. package/dist/shared/planner/index.d.ts +0 -37
  176. package/dist/shared/planner/index.d.ts.map +0 -1
  177. package/dist/shared/planner/index.js +0 -35
  178. package/dist/shared/planner/index.js.map +0 -1
  179. package/dist/shared/planner/intervals.d.ts +0 -60
  180. package/dist/shared/planner/intervals.d.ts.map +0 -1
  181. package/dist/shared/planner/intervals.js +0 -141
  182. package/dist/shared/planner/intervals.js.map +0 -1
  183. package/dist/shared/planner/routes.d.ts +0 -69
  184. package/dist/shared/planner/routes.d.ts.map +0 -1
  185. package/dist/shared/planner/routes.js +0 -770
  186. package/dist/shared/planner/routes.js.map +0 -1
  187. package/dist/shared/planner/types.d.ts +0 -328
  188. package/dist/shared/planner/types.d.ts.map +0 -1
  189. package/dist/shared/planner/types.js +0 -9
  190. package/dist/shared/planner/types.js.map +0 -1
  191. package/dist/shared/storage/ImageProcessingService.d.ts +0 -32
  192. package/dist/shared/storage/ImageProcessingService.d.ts.map +0 -1
  193. package/dist/shared/storage/ImageProcessingService.js +0 -127
  194. package/dist/shared/storage/ImageProcessingService.js.map +0 -1
  195. package/dist/shared/storage/StorageProxyService.d.ts +0 -47
  196. package/dist/shared/storage/StorageProxyService.d.ts.map +0 -1
  197. package/dist/shared/storage/StorageProxyService.js +0 -196
  198. package/dist/shared/storage/StorageProxyService.js.map +0 -1
  199. package/dist/shared/storage/StorageUploadService.d.ts +0 -126
  200. package/dist/shared/storage/StorageUploadService.d.ts.map +0 -1
  201. package/dist/shared/storage/StorageUploadService.js +0 -206
  202. package/dist/shared/storage/StorageUploadService.js.map +0 -1
  203. package/dist/shared/storage/creative-urls.d.ts +0 -14
  204. package/dist/shared/storage/creative-urls.d.ts.map +0 -1
  205. package/dist/shared/storage/creative-urls.js +0 -30
  206. package/dist/shared/storage/creative-urls.js.map +0 -1
  207. package/dist/shared/storage/index.d.ts +0 -28
  208. package/dist/shared/storage/index.d.ts.map +0 -1
  209. package/dist/shared/storage/index.js +0 -27
  210. package/dist/shared/storage/index.js.map +0 -1
  211. package/dist/shared/storage/routes.d.ts +0 -42
  212. package/dist/shared/storage/routes.d.ts.map +0 -1
  213. package/dist/shared/storage/routes.js +0 -160
  214. package/dist/shared/storage/routes.js.map +0 -1
  215. package/dist/shared/storage/types.d.ts +0 -53
  216. package/dist/shared/storage/types.d.ts.map +0 -1
  217. package/dist/shared/storage/types.js +0 -2
  218. package/dist/shared/storage/types.js.map +0 -1
  219. package/dist/shared/telegram/index.d.ts +0 -4
  220. package/dist/shared/telegram/index.d.ts.map +0 -1
  221. package/dist/shared/telegram/index.js +0 -3
  222. package/dist/shared/telegram/index.js.map +0 -1
  223. package/dist/shared/telegram/routes.d.ts +0 -48
  224. package/dist/shared/telegram/routes.d.ts.map +0 -1
  225. package/dist/shared/telegram/routes.js +0 -918
  226. package/dist/shared/telegram/routes.js.map +0 -1
  227. package/dist/shared/telegram/types.d.ts +0 -186
  228. package/dist/shared/telegram/types.d.ts.map +0 -1
  229. package/dist/shared/telegram/types.js +0 -7
  230. package/dist/shared/telegram/types.js.map +0 -1
  231. package/dist/shared/telegram/utils.d.ts +0 -44
  232. package/dist/shared/telegram/utils.d.ts.map +0 -1
  233. package/dist/shared/telegram/utils.js +0 -121
  234. package/dist/shared/telegram/utils.js.map +0 -1
  235. package/dist/storage.d.ts +0 -9
  236. package/dist/storage.d.ts.map +0 -1
  237. package/dist/storage.js +0 -8
  238. package/dist/storage.js.map +0 -1
  239. package/dist/telemetry.d.ts +0 -9
  240. package/dist/telemetry.d.ts.map +0 -1
  241. package/dist/telemetry.js +0 -8
  242. package/dist/telemetry.js.map +0 -1
  243. package/scripts/postinstall.js +0 -79
  244. package/src/shared/affiliate/migrations/001_create_affiliates.sql +0 -49
  245. package/src/shared/affiliate/migrations/002_create_affiliate_commissions.sql +0 -31
  246. package/src/shared/affiliate/migrations/003_create_affiliate_clicks.sql +0 -26
  247. package/src/shared/affiliate/migrations/004_create_affiliate_payments.sql +0 -34
  248. package/src/shared/affiliate/migrations/005_create_affiliate_tier_history.sql +0 -19
  249. package/src/shared/affiliate/migrations/006_create_affiliate_rpc_functions.sql +0 -209
  250. package/src/shared/affiliate/migrations/007_create_affiliate_rls_policies.sql +0 -123
  251. package/src/shared/billing/migrations/00000000000001_billing.sql +0 -114
package/dist/email.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"email.js","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClJ,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,57 +0,0 @@
1
- -- ============================================================================
2
- -- Tetra Core: exec_sql — Secure SQL Execution for RLS Checker
3
- -- ============================================================================
4
- -- This function allows the RLS checker to run audit queries against the DB.
5
- --
6
- -- SECURITY MODEL:
7
- -- - SECURITY INVOKER (NOT definer) — runs as the calling role
8
- -- - Only service_role should call this (via backend service client)
9
- -- - anon and authenticated are explicitly REVOKED from EXECUTE
10
- -- - search_path set to '' to prevent search_path injection
11
- -- - Returns JSONB array so it works with any query shape
12
- --
13
- -- WHY THIS IS SAFE:
14
- -- 1. service_role already bypasses RLS — this adds no new capability
15
- -- 2. anon/authenticated CANNOT call it (REVOKE + no GRANT)
16
- -- 3. Even if somehow called by authenticated, it runs as THAT role
17
- -- (SECURITY INVOKER), so RLS still applies to their queries
18
- -- 4. The function is just a thin wrapper around EXECUTE — it doesn't
19
- -- escalate privileges
20
- --
21
- -- PREREQUISITE: Must be deployed BEFORE runRLSCheck() can work.
22
- -- ============================================================================
23
-
24
- -- Drop old versions if they exist
25
- DROP FUNCTION IF EXISTS public.exec_sql(text);
26
- DROP FUNCTION IF EXISTS public.execute_sql(text);
27
-
28
- -- Create the function
29
- CREATE OR REPLACE FUNCTION public.exec_sql(query text)
30
- RETURNS jsonb
31
- LANGUAGE plpgsql
32
- VOLATILE
33
- SECURITY INVOKER
34
- SET search_path = ''
35
- AS $$
36
- DECLARE
37
- result jsonb;
38
- BEGIN
39
- EXECUTE 'SELECT COALESCE(jsonb_agg(row_to_json(t)), ''[]''::jsonb) FROM (' || query || ') t'
40
- INTO result;
41
- RETURN result;
42
- END;
43
- $$;
44
-
45
- -- CRITICAL: Revoke from all public-facing roles
46
- REVOKE ALL ON FUNCTION public.exec_sql(text) FROM PUBLIC;
47
- REVOKE ALL ON FUNCTION public.exec_sql(text) FROM anon;
48
- REVOKE ALL ON FUNCTION public.exec_sql(text) FROM authenticated;
49
-
50
- -- Only service_role (backend) and postgres (migrations) can use it
51
- GRANT EXECUTE ON FUNCTION public.exec_sql(text) TO service_role;
52
- GRANT EXECUTE ON FUNCTION public.exec_sql(text) TO postgres;
53
-
54
- -- Add a comment explaining the security model
55
- COMMENT ON FUNCTION public.exec_sql(text) IS
56
- 'Tetra RLS Checker: executes audit SQL. SECURITY INVOKER + only service_role can call. '
57
- 'anon/authenticated are explicitly revoked. Does NOT escalate privileges.';
@@ -1,9 +0,0 @@
1
- /**
2
- * @soulbatical/tetra-core/generators
3
- *
4
- * Compatibility entrypoint.
5
- * The canonical generator surface now lives in `@soulbatical/tetra-supabase`.
6
- */
7
- export { generateRLS, generateRLSBatch, getAuditChecks, generateAuditSQL, runRLSCheck, runRLSCheckDebug, generateExecSQL, checkExecSQLExists, RPCGenerator, DetailRPCGenerator, validateRPCConfig, generateAuthCheck, generateAuthWhereClause, generateAuthDeclarations, generateTimestamp, getTableAlias, escapeIdentifier, } from '@soulbatical/tetra-supabase';
8
- export type { RLSConfig, RLSTableType, RLSGeneratorResult, AuditCheck, RLSReport, RLSCheckResult, RLSViolation, RLSCategorySummary, GeneratedSQL, FilterDefinition, RPCGeneratorOptions, DetailRPCGeneratorOptions, RPCValidationResult, RPCValidationError, AccessLevel, CreatorVisibilityConfig as RPCCreatorVisibilityConfig, } from '@soulbatical/tetra-supabase';
9
- //# sourceMappingURL=generators.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,YAAY,EACV,SAAS,EACT,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,uBAAuB,IAAI,0BAA0B,GACtD,MAAM,6BAA6B,CAAC"}
@@ -1,8 +0,0 @@
1
- /**
2
- * @soulbatical/tetra-core/generators
3
- *
4
- * Compatibility entrypoint.
5
- * The canonical generator surface now lives in `@soulbatical/tetra-supabase`.
6
- */
7
- export { generateRLS, generateRLSBatch, getAuditChecks, generateAuditSQL, runRLSCheck, runRLSCheckDebug, generateExecSQL, checkExecSQLExists, RPCGenerator, DetailRPCGenerator, validateRPCConfig, generateAuthCheck, generateAuthWhereClause, generateAuthDeclarations, generateTimestamp, getTableAlias, escapeIdentifier, } from '@soulbatical/tetra-supabase';
8
- //# sourceMappingURL=generators.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generators.js","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,GACjB,MAAM,6BAA6B,CAAC"}
package/dist/mcp.d.ts DELETED
@@ -1,8 +0,0 @@
1
- /**
2
- * @soulbatical/tetra-core/mcp
3
- *
4
- * MCP Online module. Requires @modelcontextprotocol/sdk.
5
- */
6
- export { addMcpRoutes, addMcpAuthRoutes, addMcpTokenRoutes, addMcpUsageRoutes, getMcpOrganizationId, getMcpTenantContext, runWithMcpTenant, validateMcpApiToken, generateMcpApiToken, mcpDB, mcpScopedDB } from './shared/mcp/index.js';
7
- export type { McpRoutesConfig, McpAuthRoutesConfig, McpToolDefinition, McpToolResult, McpToolHandler, TenantContext, TenantContext as McpTenantContext, McpDBResult, McpDBLocalResult, McpDBOptions, GenerateMcpApiTokenOptions } from './shared/mcp/index.js';
8
- //# sourceMappingURL=mcp.d.ts.map
package/dist/mcp.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACxO,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,IAAI,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/mcp.js DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * @soulbatical/tetra-core/mcp
3
- *
4
- * MCP Online module. Requires @modelcontextprotocol/sdk.
5
- */
6
- export { addMcpRoutes, addMcpAuthRoutes, addMcpTokenRoutes, addMcpUsageRoutes, getMcpOrganizationId, getMcpTenantContext, runWithMcpTenant, validateMcpApiToken, generateMcpApiToken, mcpDB, mcpScopedDB } from './shared/mcp/index.js';
7
- //# sourceMappingURL=mcp.js.map
package/dist/mcp.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/planner.d.ts DELETED
@@ -1,8 +0,0 @@
1
- /**
2
- * @soulbatical/tetra-core/planner
3
- *
4
- * Planner module (scheduling, availability, Google Calendar).
5
- */
6
- export { PlannerService, GoogleCalendarService, addPlannerRoutes, addPlannerPublicRoutes, addPlannerCalendarRoutes, computeAvailableSlots, timeToMinutes, minutesToTime } from './shared/planner/index.js';
7
- export type { PlannerConfig, PlannerCalendarConfig, PlannerRouteOptions, PlannerCallbackContext, AvailabilitySlotRecord, AvailabilitySlotInput, AppointmentRecord, AppointmentInput, SchedulerSettingsRecord, VacationRecord, CalendarTokenRecord, PublicBookingInput, PublicBookingVisitor, TimeSlot, DayAvailability, TeamAvailability, PublicSchedulerData } from './shared/planner/index.js';
8
- //# sourceMappingURL=planner.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC3M,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,cAAc,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/planner.js DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * @soulbatical/tetra-core/planner
3
- *
4
- * Planner module (scheduling, availability, Google Calendar).
5
- */
6
- export { PlannerService, GoogleCalendarService, addPlannerRoutes, addPlannerPublicRoutes, addPlannerCalendarRoutes, computeAvailableSlots, timeToMinutes, minutesToTime } from './shared/planner/index.js';
7
- //# sourceMappingURL=planner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"planner.js","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC"}
@@ -1,47 +0,0 @@
1
- /**
2
- * AffiliateAttributionService
3
- *
4
- * Generic affiliate attribution and commission engine.
5
- * Internal referral only (voucher > URL > cookie).
6
- * Config-driven tier upgrades.
7
- *
8
- * @module @soulbatical/tetra-core/affiliate
9
- */
10
- import type { SupabaseClient } from '@supabase/supabase-js';
11
- import type { Request } from 'express';
12
- import type { AffiliateAttribution, AffiliateConfig, AffiliateOrder } from './types.js';
13
- export declare class AffiliateAttributionService {
14
- private supabase;
15
- private organizationId?;
16
- private config;
17
- constructor(supabase: SupabaseClient, config?: Partial<AffiliateConfig>, organizationId?: string);
18
- /**
19
- * Determine affiliate attribution for an order.
20
- * Priority: Voucher > URL (?ref=) > Cookie
21
- */
22
- determineAttribution(req: Request, voucherCode?: string): Promise<AffiliateAttribution | null>;
23
- /**
24
- * Create a commission record for an affiliate sale.
25
- * Updates affiliate stats and checks for tier upgrade.
26
- */
27
- createCommission(order: AffiliateOrder, attribution: AffiliateAttribution): Promise<void>;
28
- /**
29
- * Generate a referral code for a new affiliate.
30
- * Uses custom generator from config or default format.
31
- */
32
- generateReferralCode(contactName: string): string;
33
- private checkVoucherAttribution;
34
- private checkUrlParameter;
35
- private checkCookie;
36
- /**
37
- * Resolve an affiliate from referral code or ID.
38
- */
39
- resolveAffiliate(reference: string, affiliateId: string | null): Promise<any>;
40
- private updateAffiliateStats;
41
- /**
42
- * Check if affiliate qualifies for tier upgrade (config-driven).
43
- */
44
- checkTierUpgrade(affiliateId: string, totalSales: number): Promise<void>;
45
- private upgradeAffiliateTier;
46
- }
47
- //# sourceMappingURL=AffiliateAttributionService.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AffiliateAttributionService.d.ts","sourceRoot":"","sources":["../../../src/shared/affiliate/AffiliateAttributionService.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA0BxF,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,MAAM,CAAkB;gBAG9B,QAAQ,EAAE,cAAc,EACxB,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACjC,cAAc,CAAC,EAAE,MAAM;IASzB;;;OAGG;IACG,oBAAoB,CACxB,GAAG,EAAE,OAAO,EACZ,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAgCvC;;;OAGG;IACG,gBAAgB,CACpB,KAAK,EAAE,cAAc,EACrB,WAAW,EAAE,oBAAoB,GAChC,OAAO,CAAC,IAAI,CAAC;IA6DhB;;;OAGG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;YAOnC,uBAAuB;IAwBrC,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,WAAW;IAiCnB;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,GAAG,CAAC;YAkCD,oBAAoB;IAgBlC;;OAEG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA8ChE,oBAAoB;CAkDnC"}
@@ -1,308 +0,0 @@
1
- import crypto from 'crypto';
2
- import { createLogger } from '../../utils/logger.js';
3
- const logger = createLogger('service:affiliate:attribution');
4
- const DEFAULT_CONFIG = {
5
- defaultCommissionPercentage: 30,
6
- cookieDurationDays: 90,
7
- tiers: [
8
- { name: 'starter', minSales: 0, commissionPercentage: 30 },
9
- { name: 'active', minSales: 10, commissionPercentage: 35 },
10
- ],
11
- };
12
- /**
13
- * Generate a referral code from a contact name.
14
- * Format: firstname-XXXX (e.g., 'monique-1234')
15
- */
16
- function defaultReferralCodeGenerator(contactName) {
17
- const normalized = contactName
18
- .toLowerCase()
19
- .replace(/[^a-z0-9]/g, '')
20
- .substring(0, 15);
21
- const randomDigits = crypto.randomInt(1000, 10000);
22
- return `${normalized}-${randomDigits}`;
23
- }
24
- export class AffiliateAttributionService {
25
- supabase;
26
- organizationId;
27
- config;
28
- constructor(supabase, config, organizationId) {
29
- this.supabase = supabase;
30
- this.organizationId = organizationId;
31
- this.config = { ...DEFAULT_CONFIG, ...config };
32
- }
33
- // ─── Attribution ────────────────────────────────────────────
34
- /**
35
- * Determine affiliate attribution for an order.
36
- * Priority: Voucher > URL (?ref=) > Cookie
37
- */
38
- async determineAttribution(req, voucherCode) {
39
- logger.info('Determining affiliate attribution', { voucherCode });
40
- // 1. Voucher with affiliate
41
- if (voucherCode) {
42
- const attribution = await this.checkVoucherAttribution(voucherCode);
43
- if (attribution) {
44
- logger.info('Attribution via voucher', attribution);
45
- return attribution;
46
- }
47
- }
48
- // 2. URL parameter (?ref=)
49
- const urlAttribution = this.checkUrlParameter(req);
50
- if (urlAttribution) {
51
- logger.info('Attribution via URL', urlAttribution);
52
- return urlAttribution;
53
- }
54
- // 3. Cookie fallback
55
- const cookieAttribution = this.checkCookie(req);
56
- if (cookieAttribution) {
57
- logger.info('Attribution via cookie', cookieAttribution);
58
- return cookieAttribution;
59
- }
60
- logger.info('No affiliate attribution found');
61
- return null;
62
- }
63
- // ─── Commission ─────────────────────────────────────────────
64
- /**
65
- * Create a commission record for an affiliate sale.
66
- * Updates affiliate stats and checks for tier upgrade.
67
- */
68
- async createCommission(order, attribution) {
69
- logger.info('Creating commission', { orderId: order.id, attribution });
70
- const affiliate = await this.resolveAffiliate(attribution.reference, attribution.affiliate_id);
71
- if (!affiliate) {
72
- logger.warn('Affiliate not found', { attribution });
73
- return;
74
- }
75
- const orderAmount = order.total_excl_vat;
76
- const commissionAmount = orderAmount * (affiliate.commission_percentage / 100);
77
- logger.info('Commission calculated', {
78
- affiliateId: affiliate.id,
79
- orderAmount,
80
- commissionPercentage: affiliate.commission_percentage,
81
- commissionAmount,
82
- });
83
- // Create commission record
84
- const { data: commission, error } = await this.supabase
85
- .from('affiliate_commissions')
86
- .insert({
87
- organization_id: order.organization_id,
88
- affiliate_id: affiliate.id,
89
- order_id: order.id,
90
- affiliate_source: 'internal',
91
- product_name: 'Order',
92
- order_amount_excl_vat: orderAmount,
93
- commission_percentage: affiliate.commission_percentage,
94
- commission_amount: commissionAmount,
95
- status: 'pending',
96
- })
97
- .select()
98
- .single();
99
- if (error) {
100
- logger.error('Failed to create commission', { error, orderId: order.id });
101
- throw error;
102
- }
103
- logger.info('Commission created', { commissionId: commission.id });
104
- // Update affiliate stats
105
- await this.updateAffiliateStats(affiliate.id, {
106
- total_sales: affiliate.total_sales + 1,
107
- total_revenue: affiliate.total_revenue + orderAmount,
108
- total_commission_earned: affiliate.total_commission_earned + commissionAmount,
109
- last_sale_at: new Date().toISOString(),
110
- });
111
- // Check for tier upgrade
112
- await this.checkTierUpgrade(affiliate.id, affiliate.total_sales + 1);
113
- }
114
- // ─── Referral Code ──────────────────────────────────────────
115
- /**
116
- * Generate a referral code for a new affiliate.
117
- * Uses custom generator from config or default format.
118
- */
119
- generateReferralCode(contactName) {
120
- const generator = this.config.referralCodeGenerator || defaultReferralCodeGenerator;
121
- return generator(contactName);
122
- }
123
- // ─── Private: Attribution Checks ────────────────────────────
124
- async checkVoucherAttribution(voucherCode) {
125
- try {
126
- const { data: voucher, error } = await this.supabase
127
- .from('vouchers')
128
- .select('id, affiliate_id')
129
- .eq('code', voucherCode)
130
- .single();
131
- if (error || !voucher?.affiliate_id) {
132
- return null;
133
- }
134
- return {
135
- affiliate_id: voucher.affiliate_id,
136
- source: 'internal',
137
- attribution_type: 'voucher',
138
- reference: voucherCode,
139
- };
140
- }
141
- catch (error) {
142
- logger.error('Error checking voucher attribution', error);
143
- return null;
144
- }
145
- }
146
- checkUrlParameter(req) {
147
- const ref = req.query.ref;
148
- if (!ref)
149
- return null;
150
- return {
151
- affiliate_id: null,
152
- source: 'internal',
153
- attribution_type: 'url',
154
- reference: ref,
155
- };
156
- }
157
- checkCookie(req) {
158
- const cookie = req.cookies?.affiliate_ref;
159
- if (!cookie)
160
- return null;
161
- try {
162
- const data = JSON.parse(cookie);
163
- const age = Date.now() - data.timestamp;
164
- const maxAge = this.config.cookieDurationDays * 24 * 60 * 60 * 1000;
165
- if (age > maxAge) {
166
- logger.info('Affiliate cookie expired', { ageDays: Math.floor(age / (24 * 60 * 60 * 1000)) });
167
- return null;
168
- }
169
- // Only accept internal source in tetra-core
170
- if (data.source && data.source !== 'internal') {
171
- return null;
172
- }
173
- return {
174
- affiliate_id: null,
175
- source: 'internal',
176
- attribution_type: 'cookie',
177
- reference: data.ref,
178
- };
179
- }
180
- catch (error) {
181
- logger.error('Error parsing affiliate cookie', error);
182
- return null;
183
- }
184
- }
185
- // ─── Private: Affiliate Resolution ──────────────────────────
186
- /**
187
- * Resolve an affiliate from referral code or ID.
188
- */
189
- async resolveAffiliate(reference, affiliateId) {
190
- // If affiliate ID already known (voucher attribution)
191
- if (affiliateId) {
192
- const { data, error } = await this.supabase
193
- .from('affiliates')
194
- .select('*')
195
- .eq('id', affiliateId)
196
- .eq('status', 'active')
197
- .single();
198
- if (error) {
199
- logger.error('Failed to fetch affiliate by ID', { error, affiliateId });
200
- return null;
201
- }
202
- return data;
203
- }
204
- // Look up by referral code
205
- const { data, error } = await this.supabase
206
- .from('affiliates')
207
- .select('*')
208
- .eq('referral_code', reference)
209
- .eq('status', 'active')
210
- .single();
211
- if (error) {
212
- logger.error('Failed to fetch affiliate by referral code', { error, reference });
213
- return null;
214
- }
215
- return data;
216
- }
217
- // ─── Private: Stats & Tiers ─────────────────────────────────
218
- async updateAffiliateStats(affiliateId, updates) {
219
- const { error } = await this.supabase
220
- .from('affiliates')
221
- .update(updates)
222
- .eq('id', affiliateId);
223
- if (error) {
224
- logger.error('Failed to update affiliate stats', { error, affiliateId });
225
- throw error;
226
- }
227
- logger.info('Affiliate stats updated', { affiliateId, updates });
228
- }
229
- /**
230
- * Check if affiliate qualifies for tier upgrade (config-driven).
231
- */
232
- async checkTierUpgrade(affiliateId, totalSales) {
233
- const { data: affiliate, error } = await this.supabase
234
- .from('affiliates')
235
- .select('tier, commission_percentage')
236
- .eq('id', affiliateId)
237
- .single();
238
- if (error || !affiliate) {
239
- logger.error('Failed to fetch affiliate for tier check', { error, affiliateId });
240
- return;
241
- }
242
- // Find the highest qualifying tier
243
- const sortedTiers = [...this.config.tiers].sort((a, b) => b.minSales - a.minSales);
244
- const qualifyingTier = sortedTiers.find(t => totalSales >= t.minSales);
245
- if (!qualifyingTier || qualifyingTier.name === affiliate.tier) {
246
- return; // No upgrade needed
247
- }
248
- // Check if this is actually an upgrade (not a downgrade)
249
- const currentTierIndex = this.config.tiers.findIndex(t => t.name === affiliate.tier);
250
- const newTierIndex = this.config.tiers.findIndex(t => t.name === qualifyingTier.name);
251
- if (newTierIndex <= currentTierIndex) {
252
- return;
253
- }
254
- logger.info('Tier upgrade triggered', {
255
- affiliateId,
256
- oldTier: affiliate.tier,
257
- newTier: qualifyingTier.name,
258
- oldCommission: affiliate.commission_percentage,
259
- newCommission: qualifyingTier.commissionPercentage,
260
- totalSales,
261
- });
262
- await this.upgradeAffiliateTier(affiliateId, {
263
- old_tier: affiliate.tier,
264
- new_tier: qualifyingTier.name,
265
- old_commission: affiliate.commission_percentage,
266
- new_commission: qualifyingTier.commissionPercentage,
267
- reason: 'milestone_reached',
268
- triggered_by_sale_count: totalSales,
269
- });
270
- }
271
- async upgradeAffiliateTier(affiliateId, upgrade) {
272
- // Update affiliate tier and commission
273
- const { error: updateError } = await this.supabase
274
- .from('affiliates')
275
- .update({
276
- tier: upgrade.new_tier,
277
- commission_percentage: upgrade.new_commission,
278
- updated_at: new Date().toISOString(),
279
- })
280
- .eq('id', affiliateId);
281
- if (updateError) {
282
- logger.error('Failed to update affiliate tier', { error: updateError, affiliateId });
283
- throw updateError;
284
- }
285
- // Record in tier history
286
- const { error: historyError } = await this.supabase
287
- .from('affiliate_tier_history')
288
- .insert({
289
- affiliate_id: affiliateId,
290
- old_tier: upgrade.old_tier,
291
- new_tier: upgrade.new_tier,
292
- old_commission_percentage: upgrade.old_commission,
293
- new_commission_percentage: upgrade.new_commission,
294
- reason: upgrade.reason,
295
- triggered_by_sale_count: upgrade.triggered_by_sale_count,
296
- });
297
- if (historyError) {
298
- logger.error('Failed to record tier history', { error: historyError, affiliateId });
299
- // Don't throw — tier upgrade succeeded even if history failed
300
- }
301
- logger.info('Tier upgraded successfully', {
302
- affiliateId,
303
- oldTier: upgrade.old_tier,
304
- newTier: upgrade.new_tier,
305
- });
306
- }
307
- }
308
- //# sourceMappingURL=AffiliateAttributionService.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AffiliateAttributionService.js","sourceRoot":"","sources":["../../../src/shared/affiliate/AffiliateAttributionService.ts"],"names":[],"mappings":"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"}
@@ -1,35 +0,0 @@
1
- /**
2
- * AffiliateClickService
3
- *
4
- * Handles click tracking and conversion marking for the affiliate module.
5
- *
6
- * @module @soulbatical/tetra-core/affiliate
7
- */
8
- import type { SupabaseClient } from '@supabase/supabase-js';
9
- export declare class AffiliateClickService {
10
- private supabase;
11
- constructor(supabase: SupabaseClient);
12
- /**
13
- * Register an affiliate click event.
14
- * Returns the click record ID.
15
- */
16
- registerClick(data: {
17
- affiliate_id?: string | null;
18
- organization_id?: string | null;
19
- affiliate_source: string;
20
- visitor_ip?: string | null;
21
- user_agent?: string | null;
22
- referrer_url?: string | null;
23
- landing_page?: string | null;
24
- external_click_ref?: string | null;
25
- }): Promise<string | null>;
26
- /**
27
- * Increment affiliate total_clicks counter.
28
- */
29
- incrementClickCount(affiliateId: string): Promise<void>;
30
- /**
31
- * Mark a click as converted after a successful order.
32
- */
33
- markConverted(clickId: string, orderId: string): Promise<void>;
34
- }
35
- //# sourceMappingURL=AffiliateClickService.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AffiliateClickService.d.ts","sourceRoot":"","sources":["../../../src/shared/affiliate/AffiliateClickService.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAiB;gBAErB,QAAQ,EAAE,cAAc;IAIpC;;;OAGG;IACG,aAAa,CAAC,IAAI,EAAE;QACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA0B1B;;OAEG;IACG,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB7D;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA4BrE"}
@@ -1,87 +0,0 @@
1
- import { createLogger } from '../../utils/logger.js';
2
- const logger = createLogger('service:affiliate:clicks');
3
- export class AffiliateClickService {
4
- supabase;
5
- constructor(supabase) {
6
- this.supabase = supabase;
7
- }
8
- /**
9
- * Register an affiliate click event.
10
- * Returns the click record ID.
11
- */
12
- async registerClick(data) {
13
- const { data: click, error } = await this.supabase
14
- .from('affiliate_clicks')
15
- .insert({
16
- organization_id: data.organization_id || null,
17
- affiliate_id: data.affiliate_id || null,
18
- visitor_ip: data.visitor_ip || null,
19
- user_agent: data.user_agent || null,
20
- referrer_url: data.referrer_url || null,
21
- landing_page: data.landing_page || null,
22
- affiliate_source: data.affiliate_source,
23
- external_click_ref: data.external_click_ref || null,
24
- converted: false,
25
- })
26
- .select('id')
27
- .single();
28
- if (error) {
29
- logger.error('Failed to record click', { error });
30
- return null;
31
- }
32
- logger.info('Click registered', { clickId: click.id, affiliateId: data.affiliate_id });
33
- return click.id;
34
- }
35
- /**
36
- * Increment affiliate total_clicks counter.
37
- */
38
- async incrementClickCount(affiliateId) {
39
- // Fetch current count, then increment (safe for low-concurrency affiliate use case)
40
- const { data: affiliate, error: fetchError } = await this.supabase
41
- .from('affiliates')
42
- .select('total_clicks')
43
- .eq('id', affiliateId)
44
- .single();
45
- if (fetchError || !affiliate) {
46
- logger.error('Failed to fetch affiliate for click count update', { error: fetchError, affiliateId });
47
- return;
48
- }
49
- const { error: updateError } = await this.supabase
50
- .from('affiliates')
51
- .update({ total_clicks: (affiliate.total_clicks || 0) + 1 })
52
- .eq('id', affiliateId);
53
- if (updateError) {
54
- logger.error('Failed to update click count', { error: updateError, affiliateId });
55
- }
56
- }
57
- /**
58
- * Mark a click as converted after a successful order.
59
- */
60
- async markConverted(clickId, orderId) {
61
- const { data: click, error: fetchError } = await this.supabase
62
- .from('affiliate_clicks')
63
- .select('clicked_at')
64
- .eq('id', clickId)
65
- .single();
66
- let conversionTimeHours = null;
67
- if (!fetchError && click?.clicked_at) {
68
- const clickedAt = new Date(click.clicked_at).getTime();
69
- conversionTimeHours = Math.round((Date.now() - clickedAt) / (1000 * 60 * 60));
70
- }
71
- const { error } = await this.supabase
72
- .from('affiliate_clicks')
73
- .update({
74
- converted: true,
75
- order_id: orderId,
76
- conversion_time_hours: conversionTimeHours,
77
- })
78
- .eq('id', clickId);
79
- if (error) {
80
- logger.error('Failed to mark click as converted', { error, clickId, orderId });
81
- }
82
- else {
83
- logger.info('Click marked as converted', { clickId, orderId, conversionTimeHours });
84
- }
85
- }
86
- }
87
- //# sourceMappingURL=AffiliateClickService.js.map