@iann29/rastro 0.10.9 → 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 (178) hide show
  1. package/README.md +8 -0
  2. package/agent/integration.md +45 -0
  3. package/agent/manifest.json +4 -4
  4. package/dist/client/federation.d.ts +82 -9
  5. package/dist/client/federation.d.ts.map +1 -1
  6. package/dist/client/federation.js +40 -2
  7. package/dist/client/federation.js.map +1 -1
  8. package/dist/client/index.d.ts +464 -8
  9. package/dist/client/index.d.ts.map +1 -1
  10. package/dist/client/index.js +259 -7
  11. package/dist/client/index.js.map +1 -1
  12. package/dist/component/_generated/api.d.ts +10 -0
  13. package/dist/component/_generated/api.d.ts.map +1 -1
  14. package/dist/component/_generated/api.js.map +1 -1
  15. package/dist/component/_generated/component.d.ts +273 -21
  16. package/dist/component/_generated/component.d.ts.map +1 -1
  17. package/dist/component/_generated/server.d.ts +2 -0
  18. package/dist/component/_generated/server.d.ts.map +1 -1
  19. package/dist/component/_generated/server.js.map +1 -1
  20. package/dist/component/constants.d.ts +31 -0
  21. package/dist/component/constants.d.ts.map +1 -1
  22. package/dist/component/constants.js +31 -0
  23. package/dist/component/constants.js.map +1 -1
  24. package/dist/component/convex.config.d.ts +2 -0
  25. package/dist/component/convex.config.js +7 -0
  26. package/dist/component/convex.config.js.map +1 -1
  27. package/dist/component/errors.d.ts +1 -1
  28. package/dist/component/errors.d.ts.map +1 -1
  29. package/dist/component/errors.js.map +1 -1
  30. package/dist/component/http.d.ts.map +1 -1
  31. package/dist/component/http.js +64 -0
  32. package/dist/component/http.js.map +1 -1
  33. package/dist/component/leadAdsValidators.d.ts +1092 -0
  34. package/dist/component/leadAdsValidators.d.ts.map +1 -0
  35. package/dist/component/leadAdsValidators.js +304 -0
  36. package/dist/component/leadAdsValidators.js.map +1 -0
  37. package/dist/component/leadFormRules.d.ts +60 -0
  38. package/dist/component/leadFormRules.d.ts.map +1 -0
  39. package/dist/component/leadFormRules.js +140 -0
  40. package/dist/component/leadFormRules.js.map +1 -0
  41. package/dist/component/leadFormStore.d.ts +16 -0
  42. package/dist/component/leadFormStore.d.ts.map +1 -0
  43. package/dist/component/leadFormStore.js +92 -0
  44. package/dist/component/leadFormStore.js.map +1 -0
  45. package/dist/component/leadgenToken.d.ts +56 -0
  46. package/dist/component/leadgenToken.d.ts.map +1 -0
  47. package/dist/component/leadgenToken.js +262 -0
  48. package/dist/component/leadgenToken.js.map +1 -0
  49. package/dist/component/leads.d.ts +76 -7
  50. package/dist/component/leads.d.ts.map +1 -1
  51. package/dist/component/leads.js +112 -78
  52. package/dist/component/leads.js.map +1 -1
  53. package/dist/component/meta.d.ts.map +1 -1
  54. package/dist/component/meta.js +21 -1
  55. package/dist/component/meta.js.map +1 -1
  56. package/dist/component/metaFake.d.ts +44 -0
  57. package/dist/component/metaFake.d.ts.map +1 -1
  58. package/dist/component/metaFake.js +400 -1
  59. package/dist/component/metaFake.js.map +1 -1
  60. package/dist/component/metaGraph.d.ts +91 -0
  61. package/dist/component/metaGraph.d.ts.map +1 -1
  62. package/dist/component/metaGraph.js +217 -0
  63. package/dist/component/metaGraph.js.map +1 -1
  64. package/dist/component/metaLeads.d.ts +681 -0
  65. package/dist/component/metaLeads.d.ts.map +1 -0
  66. package/dist/component/metaLeads.js +2634 -0
  67. package/dist/component/metaLeads.js.map +1 -0
  68. package/dist/component/schema.d.ts +414 -5
  69. package/dist/component/schema.d.ts.map +1 -1
  70. package/dist/component/schema.js +169 -1
  71. package/dist/component/schema.js.map +1 -1
  72. package/dist/component/validators.d.ts +235 -11
  73. package/dist/component/validators.d.ts.map +1 -1
  74. package/dist/component/validators.js +14 -1
  75. package/dist/component/validators.js.map +1 -1
  76. package/dist/tracker/generated.d.ts +1 -1
  77. package/dist/tracker/generated.js +1 -1
  78. package/dist/ui/campaigns/CampaignsView.d.ts +5 -1
  79. package/dist/ui/campaigns/CampaignsView.d.ts.map +1 -1
  80. package/dist/ui/campaigns/CampaignsView.js.map +1 -1
  81. package/dist/ui/campaigns/Drawer.d.ts.map +1 -1
  82. package/dist/ui/campaigns/Drawer.js +8 -26
  83. package/dist/ui/campaigns/Drawer.js.map +1 -1
  84. package/dist/ui/campaigns/labels.d.ts +29 -1
  85. package/dist/ui/campaigns/labels.d.ts.map +1 -1
  86. package/dist/ui/campaigns/labels.js +77 -2
  87. package/dist/ui/campaigns/labels.js.map +1 -1
  88. package/dist/ui/campaigns/model.js +2 -2
  89. package/dist/ui/campaigns/model.js.map +1 -1
  90. package/dist/ui/forms/FirstContact.d.ts +19 -0
  91. package/dist/ui/forms/FirstContact.d.ts.map +1 -0
  92. package/dist/ui/forms/FirstContact.js +81 -0
  93. package/dist/ui/forms/FirstContact.js.map +1 -0
  94. package/dist/ui/forms/FormLead.d.ts +28 -0
  95. package/dist/ui/forms/FormLead.d.ts.map +1 -0
  96. package/dist/ui/forms/FormLead.js +199 -0
  97. package/dist/ui/forms/FormLead.js.map +1 -0
  98. package/dist/ui/forms/FormRulesDrawer.d.ts +49 -0
  99. package/dist/ui/forms/FormRulesDrawer.d.ts.map +1 -0
  100. package/dist/ui/forms/FormRulesDrawer.js +149 -0
  101. package/dist/ui/forms/FormRulesDrawer.js.map +1 -0
  102. package/dist/ui/forms/FormsView.d.ts +10 -0
  103. package/dist/ui/forms/FormsView.d.ts.map +1 -0
  104. package/dist/ui/forms/FormsView.js +215 -0
  105. package/dist/ui/forms/FormsView.js.map +1 -0
  106. package/dist/ui/forms/Icons.d.ts +46 -0
  107. package/dist/ui/forms/Icons.d.ts.map +1 -0
  108. package/dist/ui/forms/Icons.js +45 -0
  109. package/dist/ui/forms/Icons.js.map +1 -0
  110. package/dist/ui/forms/RuleRow.d.ts +37 -0
  111. package/dist/ui/forms/RuleRow.d.ts.map +1 -0
  112. package/dist/ui/forms/RuleRow.js +80 -0
  113. package/dist/ui/forms/RuleRow.js.map +1 -0
  114. package/dist/ui/forms/WhatsAppButtonGuide.d.ts +33 -0
  115. package/dist/ui/forms/WhatsAppButtonGuide.d.ts.map +1 -0
  116. package/dist/ui/forms/WhatsAppButtonGuide.js +90 -0
  117. package/dist/ui/forms/WhatsAppButtonGuide.js.map +1 -0
  118. package/dist/ui/forms/index.d.ts +11 -0
  119. package/dist/ui/forms/index.d.ts.map +1 -0
  120. package/dist/ui/forms/index.js +7 -0
  121. package/dist/ui/forms/index.js.map +1 -0
  122. package/dist/ui/forms/journey.d.ts +19 -0
  123. package/dist/ui/forms/journey.d.ts.map +1 -0
  124. package/dist/ui/forms/journey.js +54 -0
  125. package/dist/ui/forms/journey.js.map +1 -0
  126. package/dist/ui/forms/model.d.ts +239 -0
  127. package/dist/ui/forms/model.d.ts.map +1 -0
  128. package/dist/ui/forms/model.js +556 -0
  129. package/dist/ui/forms/model.js.map +1 -0
  130. package/dist/ui/forms/sample.d.ts +36 -0
  131. package/dist/ui/forms/sample.d.ts.map +1 -0
  132. package/dist/ui/forms/sample.js +444 -0
  133. package/dist/ui/forms/sample.js.map +1 -0
  134. package/dist/ui/forms/types.d.ts +454 -0
  135. package/dist/ui/forms/types.d.ts.map +1 -0
  136. package/dist/ui/forms/types.js +2 -0
  137. package/dist/ui/forms/types.js.map +1 -0
  138. package/dist/ui/index.d.ts +2 -0
  139. package/dist/ui/index.d.ts.map +1 -1
  140. package/dist/ui/index.js +4 -0
  141. package/dist/ui/index.js.map +1 -1
  142. package/dist/ui/integrations/Overlay.d.ts +3 -1
  143. package/dist/ui/integrations/Overlay.d.ts.map +1 -1
  144. package/dist/ui/integrations/Overlay.js +2 -2
  145. package/dist/ui/integrations/Overlay.js.map +1 -1
  146. package/dist/ui/portfolio/PortfolioView.d.ts +4 -1
  147. package/dist/ui/portfolio/PortfolioView.d.ts.map +1 -1
  148. package/dist/ui/portfolio/PortfolioView.js.map +1 -1
  149. package/dist/ui/sample.d.ts +3 -1
  150. package/dist/ui/sample.d.ts.map +1 -1
  151. package/dist/ui/sample.js +2 -0
  152. package/dist/ui/sample.js.map +1 -1
  153. package/dist/ui/seed.d.ts +1 -1
  154. package/dist/ui/ui.css +2301 -0
  155. package/docs/federation.md +19 -0
  156. package/docs/meta-ads.md +713 -7
  157. package/docs/upgrading.md +70 -0
  158. package/llms.txt +1 -0
  159. package/package.json +1 -1
  160. package/src/component/_generated/api.ts +10 -0
  161. package/src/component/_generated/component.ts +289 -20
  162. package/src/component/_generated/server.ts +2 -0
  163. package/src/component/constants.ts +33 -0
  164. package/src/component/convex.config.ts +7 -0
  165. package/src/component/errors.ts +3 -1
  166. package/src/component/http.ts +75 -0
  167. package/src/component/leadAdsValidators.ts +365 -0
  168. package/src/component/leadFormRules.ts +202 -0
  169. package/src/component/leadFormStore.ts +129 -0
  170. package/src/component/leadgenToken.ts +348 -0
  171. package/src/component/leads.ts +136 -84
  172. package/src/component/meta.ts +21 -1
  173. package/src/component/metaFake.ts +485 -1
  174. package/src/component/metaGraph.ts +327 -0
  175. package/src/component/metaLeads.ts +3101 -0
  176. package/src/component/schema.ts +187 -1
  177. package/src/component/validators.ts +17 -1
  178. package/src/tracker/generated.ts +1 -1
@@ -0,0 +1,681 @@
1
+ import { type Infer } from "convex/values";
2
+ import type { Id } from "./_generated/dataModel.js";
3
+ import { type ActionCtx, type MutationCtx } from "./_generated/server.js";
4
+ import { type MetaPageErrorCode } from "./leadAdsValidators.js";
5
+ import { type MetaGraph } from "./metaGraph.js";
6
+ /** Leads, forms and Pages one call or one read handles at most. */
7
+ export declare const MAX_PAGES_PER_CONNECTION = 200;
8
+ export declare const MAX_SITE_PAGES = 20;
9
+ /** Forms the forms screen lists for a site, every Page together. */
10
+ export declare const MAX_SITE_FORMS = 500;
11
+ /**
12
+ * How often the reconciliation makes sure the app is still subscribed to a
13
+ * linked Page: the subscription is the Page's and the app's, shared by every
14
+ * host, so another host unlinking the Page (releases before this one did
15
+ * unsubscribe) or a Page admin may have taken it off.
16
+ */
17
+ export declare const SUBSCRIPTION_CHECK_MS: number;
18
+ /**
19
+ * A lead whose commit failed this many times, while later leads of its form
20
+ * came in, is skipped by the reconciliation (kept in `formLeadFailures`).
21
+ */
22
+ export declare const MAX_LEAD_ATTEMPTS = 5;
23
+ /**
24
+ * A link's stored `lastError` (`CODE: message`) as the code a screen reads;
25
+ * the message stays in the component. Anything unknown reads as Meta being
26
+ * unavailable, which passes by itself.
27
+ */
28
+ export declare function pageErrorCode(lastError: string | null | undefined): MetaPageErrorCode | null;
29
+ declare const sealedPageValidator: import("convex/values").VObject<{
30
+ leadsAllowed: boolean;
31
+ name: string;
32
+ pageId: string;
33
+ tasks: string[];
34
+ tokenCipher: string;
35
+ tokenIv: string;
36
+ }, {
37
+ pageId: import("convex/values").VString<string, "required">;
38
+ name: import("convex/values").VString<string, "required">;
39
+ tasks: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
40
+ leadsAllowed: import("convex/values").VBoolean<boolean, "required">;
41
+ tokenCipher: import("convex/values").VString<string, "required">;
42
+ tokenIv: import("convex/values").VString<string, "required">;
43
+ }, "required", "leadsAllowed" | "name" | "pageId" | "tasks" | "tokenCipher" | "tokenIv">;
44
+ /**
45
+ * The Pages a token acts for, each with its token sealed, for `savePages`.
46
+ * Never fails a login: a token without the Page permissions (a login with the
47
+ * old configuration) lists none, and anything Meta refuses here leaves the
48
+ * Pages already known (`complete: false`).
49
+ */
50
+ export declare function readPages(client: MetaGraph, token: string): Promise<{
51
+ pages: Array<Infer<typeof sealedPageValidator>>;
52
+ complete: boolean;
53
+ }>;
54
+ /**
55
+ * Stores the Pages a connection's token listed, with their sealed tokens. A
56
+ * linked Page the listing leaves out (with `complete`) stops, saying why; a
57
+ * linked Page listed again (or with a fresh token) resumes. Ignored when the
58
+ * connection has another token by now (`tokenIv`).
59
+ */
60
+ export declare const savePages: import("convex/server").RegisteredMutation<"internal", {
61
+ complete: boolean;
62
+ connectionId: import("convex/values").GenericId<"metaConnections">;
63
+ connectionTokenIv: string;
64
+ pages: {
65
+ leadsAllowed: boolean;
66
+ name: string;
67
+ pageId: string;
68
+ tasks: string[];
69
+ tokenCipher: string;
70
+ tokenIv: string;
71
+ }[];
72
+ }, Promise<null>>;
73
+ export declare const handlerRegistered: import("convex/server").RegisteredQuery<"internal", {}, Promise<boolean>>;
74
+ /**
75
+ * Reads and stores the Pages a connection's token acts for, on a host that
76
+ * opted into Lead Ads (its form lead handler is registered). A host that did
77
+ * not makes no Pages read and keeps no Page token.
78
+ */
79
+ export declare function syncOwnerPages(ctx: ActionCtx, client: MetaGraph, connection: {
80
+ connectionId: Id<"metaConnections">;
81
+ token: string;
82
+ tokenIv: string;
83
+ }): Promise<void>;
84
+ export declare const ownersToRead: import("convex/server").RegisteredQuery<"internal", {
85
+ after: number | null;
86
+ }, Promise<{
87
+ connectionId: import("convex/values").GenericId<"metaConnections">;
88
+ creationTime: number;
89
+ tokenCipher: string;
90
+ tokenIv: string;
91
+ active: boolean;
92
+ }[]>>;
93
+ /**
94
+ * The host registered its form lead handler for the first time: the Pages of
95
+ * the owners already connected are read now, a batch of owners at a time,
96
+ * instead of at each owner's next login.
97
+ */
98
+ export declare const readOwnersPages: import("convex/server").RegisteredAction<"internal", {
99
+ after: number | null;
100
+ }, Promise<null>>;
101
+ /**
102
+ * Meta refused the Page token sealed with `tokenIv`: the Page stops until a
103
+ * login lists it with a new one. A newer token (another IV) is left alone.
104
+ */
105
+ export declare const markPageInvalid: import("convex/server").RegisteredMutation<"internal", {
106
+ message: string;
107
+ pageRowId: import("convex/values").GenericId<"metaPages">;
108
+ tokenIv: string;
109
+ }, Promise<null>>;
110
+ /** Forgets a removed connection's Pages and links, a batch at a time. */
111
+ export declare function removeConnectionPages(ctx: MutationCtx, connectionId: Id<"metaConnections">, batch: number): Promise<boolean>;
112
+ /**
113
+ * The owner's Pages as a screen shows them: whether Meta granted their
114
+ * leads, the site each feeds (whoever linked it, since a Page feeds one
115
+ * site) and whether this owner linked it. Never a token.
116
+ */
117
+ export declare const pages: import("convex/server").RegisteredQuery<"public", {
118
+ ownerKey: string;
119
+ }, Promise<{
120
+ pageId: string;
121
+ name: string;
122
+ tasks: string[];
123
+ leadsAllowed: boolean;
124
+ linkedSiteId: import("convex/values").GenericId<"sites"> | null;
125
+ own: boolean | null;
126
+ subscribedAt: number | null;
127
+ lastError: "HANDLER_FAILED" | "HANDLER_GAVE_UP" | "HANDLER_MISSING" | "META_PERMISSION_MISSING" | "META_RATE_LIMITED" | "META_TOKEN_INVALID" | "META_TRUNCATED" | "META_UNAVAILABLE" | "RUN_TIMEOUT" | "SECRETS_KEY_MISSING" | null;
128
+ handlerReady: boolean;
129
+ }[]>>;
130
+ /**
131
+ * The Pages linked to the sites, for the control plane's webhook routes, and
132
+ * whether this host's leadgen route takes forwards at all: `leadgenReady` (the
133
+ * component has `RASTRO_FEDERATION_AUDIENCE`), the `issuer` it checks them
134
+ * against and the `audience` it expects. The control plane routes a Page here
135
+ * only when it is ready, the issuer is its own and the audience is the one it
136
+ * signs forwards for (decision D1). `handlerReady` says whether the host
137
+ * registered its form lead handler: without it no Page is read, so a screen
138
+ * with no Pages names the host's setup instead of the Meta login.
139
+ */
140
+ export declare const linkedPages: import("convex/server").RegisteredQuery<"public", {
141
+ siteIds: import("convex/values").GenericId<"sites">[];
142
+ }, Promise<{
143
+ pages: {
144
+ pageId: string;
145
+ siteId: import("convex/values").GenericId<"sites">;
146
+ }[];
147
+ leadgenReady: boolean;
148
+ issuer: string;
149
+ audience: string | null;
150
+ handlerReady: boolean;
151
+ }>>;
152
+ export declare const prepareLink: import("convex/server").RegisteredQuery<"internal", {
153
+ onlyOwn: boolean;
154
+ ownerKey: string;
155
+ pageId: string;
156
+ siteId: import("convex/values").GenericId<"sites">;
157
+ }, Promise<{
158
+ pageRowId: import("convex/values").GenericId<"metaPages">;
159
+ tokenCipher: string;
160
+ tokenIv: string;
161
+ }>>;
162
+ export declare const saveForms: import("convex/server").RegisteredMutation<"internal", {
163
+ complete: boolean;
164
+ forms: {
165
+ createdTime: number | null;
166
+ formId: string;
167
+ name: string;
168
+ questions: {
169
+ key: string;
170
+ label: string;
171
+ options?: {
172
+ key: string;
173
+ value: string;
174
+ }[] | undefined;
175
+ type: string;
176
+ }[];
177
+ status: string;
178
+ whatsappButton: boolean | null;
179
+ }[];
180
+ pageId: string;
181
+ }, Promise<null>>;
182
+ export declare const saveLink: import("convex/server").RegisteredMutation<"internal", {
183
+ forms: {
184
+ createdTime: number | null;
185
+ formId: string;
186
+ name: string;
187
+ questions: {
188
+ key: string;
189
+ label: string;
190
+ options?: {
191
+ key: string;
192
+ value: string;
193
+ }[] | undefined;
194
+ type: string;
195
+ }[];
196
+ status: string;
197
+ whatsappButton: boolean | null;
198
+ }[] | null;
199
+ onlyOwn: boolean;
200
+ ownerKey: string;
201
+ pageId: string;
202
+ reconcileFrom: number;
203
+ siteId: import("convex/values").GenericId<"sites">;
204
+ subscribedAt: number;
205
+ }, Promise<null>>;
206
+ /**
207
+ * Makes one of the owner's Pages feed the site's leads: subscribes the app to
208
+ * the Page's `leadgen` webhook with the Page's own token, reads its forms,
209
+ * records the link and starts the reconciliation. One Page feeds one site
210
+ * (`CONFLICT` otherwise). With `onlyOwn` (the federated path) a Page another
211
+ * owner linked to the site is a `CONFLICT` too; the host's own call moves it.
212
+ * `backfillDays` (0–30, host only) also brings the leads of the days before.
213
+ */
214
+ export declare const linkPage: import("convex/server").RegisteredAction<"public", {
215
+ backfillDays?: number | undefined;
216
+ onlyOwn?: boolean | undefined;
217
+ ownerKey: string;
218
+ pageId: string;
219
+ siteId: import("convex/values").GenericId<"sites">;
220
+ }, Promise<{
221
+ linked: boolean;
222
+ forms: number;
223
+ }>>;
224
+ /**
225
+ * Stops a Page feeding the site: forgets the link and so its reconciliation.
226
+ * The app's `leadgen` subscription stays on the Page: it is the Page's and
227
+ * the app's, shared by every host (one app, one dashboard webhook), so taking
228
+ * it off here would silence a host that links the Page now. The dashboard
229
+ * drops notifications for a Page no host claims. The site's form rules and
230
+ * the leads already in stay. With `ownerKey`, only that owner's link
231
+ * (another's is a `CONFLICT`). An action, like `linkPage`, for the callers
232
+ * that pair them.
233
+ */
234
+ export declare const unlinkPage: import("convex/server").RegisteredAction<"public", {
235
+ ownerKey?: string | undefined;
236
+ pageId: string;
237
+ siteId: import("convex/values").GenericId<"sites">;
238
+ }, Promise<{
239
+ unlinked: boolean;
240
+ }>>;
241
+ export declare const removeLink: import("convex/server").RegisteredMutation<"internal", {
242
+ ownerKey?: string | undefined;
243
+ pageId: string;
244
+ siteId: import("convex/values").GenericId<"sites">;
245
+ }, Promise<{
246
+ unlinked: boolean;
247
+ }>>;
248
+ export declare const loadSitePageTokens: import("convex/server").RegisteredQuery<"internal", {
249
+ pageId?: string | undefined;
250
+ siteId: import("convex/values").GenericId<"sites">;
251
+ }, Promise<{
252
+ pageId: string;
253
+ pageRowId: import("convex/values").GenericId<"metaPages">;
254
+ tokenCipher: string;
255
+ tokenIv: string;
256
+ }[]>>;
257
+ /**
258
+ * Reads the instant forms of the site's linked Pages (or one of them) from
259
+ * Meta again. New forms show up by themselves every reconciliation run; this
260
+ * is the screen's "refresh now".
261
+ */
262
+ export declare const refreshForms: import("convex/server").RegisteredAction<"public", {
263
+ pageId?: string | undefined;
264
+ siteId: import("convex/values").GenericId<"sites">;
265
+ }, Promise<{
266
+ pages: number;
267
+ forms: number;
268
+ }>>;
269
+ /**
270
+ * The Pages linked to the site and their forms, for the forms screen: each
271
+ * form's leads in the 30 UTC days up to `now` (and per day), its last lead,
272
+ * its rules and the end screen's WhatsApp button. With `ownerKey`, whether
273
+ * that owner linked each Page and may edit each form's rules (`own`).
274
+ */
275
+ export declare const forms: import("convex/server").RegisteredQuery<"public", {
276
+ now?: number | undefined;
277
+ ownerKey?: string | undefined;
278
+ siteId: import("convex/values").GenericId<"sites">;
279
+ }, Promise<{
280
+ pageId: string;
281
+ pageName: string;
282
+ leadsAllowed: boolean;
283
+ subscribedAt: number | null;
284
+ lastReconcileAt: number | null;
285
+ lastLeadAt: number | null;
286
+ lastError: "HANDLER_FAILED" | "HANDLER_GAVE_UP" | "HANDLER_MISSING" | "META_PERMISSION_MISSING" | "META_RATE_LIMITED" | "META_TOKEN_INVALID" | "META_TRUNCATED" | "META_UNAVAILABLE" | "RUN_TIMEOUT" | "SECRETS_KEY_MISSING" | null;
287
+ own?: boolean | undefined;
288
+ handlerReady: boolean;
289
+ forms: {
290
+ formId: string;
291
+ name: string;
292
+ status: string;
293
+ questions: {
294
+ key: string;
295
+ label: string;
296
+ options?: {
297
+ key: string;
298
+ value: string;
299
+ }[] | undefined;
300
+ type: string;
301
+ }[];
302
+ whatsappButton: boolean | null;
303
+ whatsappButtonConfirmed: boolean;
304
+ createdTime: number | null;
305
+ syncedAt: number;
306
+ leads30d: number | null;
307
+ daily: number[] | null;
308
+ lastLeadAt: number | null;
309
+ rules: {
310
+ configured: boolean;
311
+ count: number;
312
+ entryColumn: string | null;
313
+ own?: boolean | undefined;
314
+ };
315
+ }[];
316
+ }[]>>;
317
+ /**
318
+ * Where a site's form sends its leads: the rules in order (the first that
319
+ * matches decides; none → `entryColumn`, null for the host's own entry), and
320
+ * how the host makes the first contact. Replaces what was there; it decides
321
+ * the next leads only. With `ownerKey` and `onlyOwn` (the federated path), a
322
+ * Page or rules another owner set are a `CONFLICT`.
323
+ */
324
+ export declare const setFormRules: import("convex/server").RegisteredMutation<"public", {
325
+ entryColumn: string | null;
326
+ firstContact: {
327
+ brakes?: {
328
+ businessHoursOnly: boolean;
329
+ maxPerHour: number;
330
+ waitMinutes: number;
331
+ } | undefined;
332
+ mode: "automatic" | "lead_starts" | "one_click";
333
+ text?: string | undefined;
334
+ };
335
+ formId: string;
336
+ onlyOwn?: boolean | undefined;
337
+ ownerKey?: string | undefined;
338
+ rules: {
339
+ answers: string[];
340
+ questionKey: string;
341
+ to: {
342
+ column: string;
343
+ } | {
344
+ discard: string;
345
+ };
346
+ }[];
347
+ siteId: import("convex/values").GenericId<"sites">;
348
+ whatsappButtonConfirmed?: boolean | undefined;
349
+ }, Promise<null>>;
350
+ /**
351
+ * A form's rules for the drawer, each with the leads it decided in the 30
352
+ * days up to `now` (null without `now`). A form never configured answers its
353
+ * defaults with `configured: false`.
354
+ */
355
+ export declare const formRules: import("convex/server").RegisteredQuery<"public", {
356
+ formId: string;
357
+ now?: number | undefined;
358
+ ownerKey?: string | undefined;
359
+ siteId: import("convex/values").GenericId<"sites">;
360
+ }, Promise<{
361
+ siteId: import("convex/values").GenericId<"sites">;
362
+ formId: string;
363
+ configured: boolean;
364
+ entryColumn: string | null;
365
+ rules: {
366
+ monthCount: number | null;
367
+ answers: string[];
368
+ questionKey: string;
369
+ to: {
370
+ column: string;
371
+ } | {
372
+ discard: string;
373
+ };
374
+ }[];
375
+ firstContact: {
376
+ brakes?: {
377
+ businessHoursOnly: boolean;
378
+ maxPerHour: number;
379
+ waitMinutes: number;
380
+ } | undefined;
381
+ mode: "automatic" | "lead_starts" | "one_click";
382
+ text?: string | undefined;
383
+ };
384
+ whatsappButtonConfirmed: boolean;
385
+ updatedAt: number | null;
386
+ own?: boolean | undefined;
387
+ }>>;
388
+ /**
389
+ * The form's leads of the 30 days up to `now` under a draft of its rules:
390
+ * how many each rule would decide, and where they would all go. Reads the
391
+ * choice answers Rastro keeps; never Meta.
392
+ */
393
+ export declare const simulateFormRules: import("convex/server").RegisteredQuery<"public", {
394
+ entryColumn: string | null;
395
+ formId: string;
396
+ now: number;
397
+ rules: {
398
+ answers: string[];
399
+ questionKey: string;
400
+ to: {
401
+ column: string;
402
+ } | {
403
+ discard: string;
404
+ };
405
+ }[];
406
+ siteId: import("convex/values").GenericId<"sites">;
407
+ }, Promise<{
408
+ total: number;
409
+ entry: number;
410
+ rules: number[];
411
+ columns: {
412
+ column: string;
413
+ leads: number;
414
+ }[];
415
+ discarded: {
416
+ reason: string;
417
+ leads: number;
418
+ }[];
419
+ partial: boolean;
420
+ }>>;
421
+ /**
422
+ * Sends a discarded lead back to the funnel: its decision is cleared (it
423
+ * goes to the host's entry) and the reason it had is kept as history. The
424
+ * host moves its card back itself. With `ownerKey`, only for a Page that
425
+ * owner linked.
426
+ */
427
+ export declare const returnFormLead: import("convex/server").RegisteredMutation<"public", {
428
+ leadId: string;
429
+ ownerKey?: string | undefined;
430
+ siteId: import("convex/values").GenericId<"sites">;
431
+ }, Promise<{
432
+ returned: boolean;
433
+ }>>;
434
+ /**
435
+ * Registers the host's form lead handler: a function handle to an internal
436
+ * mutation that receives each lead (see `formLeadPayloadValidator`). Safe to
437
+ * call again; `null` removes it, and leads then wait (not marked ingested)
438
+ * until a handler is back.
439
+ */
440
+ export declare const setFormLeadHandler: import("convex/server").RegisteredMutation<"public", {
441
+ handle: string | null;
442
+ }, Promise<null>>;
443
+ /**
444
+ * What a failed commit says, safe for a log: a `ConvexError`'s `code` or the
445
+ * error's class name. Never the message: the host's handler had the lead's
446
+ * name, phone and e-mail in hand, and its message (or a validator's dump of
447
+ * the arguments) may carry them.
448
+ */
449
+ export declare function failureCode(error: unknown): string;
450
+ /**
451
+ * Counts one failed commit of a lead (its ids and the error's code, nothing
452
+ * else). Returns the attempts so far and whether the lead was already skipped.
453
+ */
454
+ export declare const recordLeadFailure: import("convex/server").RegisteredMutation<"internal", {
455
+ code: string;
456
+ formId: string;
457
+ leadgenId: string;
458
+ pageId: string;
459
+ }, Promise<{
460
+ attempts: number;
461
+ skipped: boolean;
462
+ }>>;
463
+ /** Marks leads the reconciliation gave up on, so they no longer hold it. */
464
+ export declare const skipFailedLeads: import("convex/server").RegisteredMutation<"internal", {
465
+ leadgenIds: string[];
466
+ }, Promise<null>>;
467
+ export declare const commitFormLead: import("convex/server").RegisteredMutation<"internal", {
468
+ adId: string | null;
469
+ adsetId: string | null;
470
+ campaignId: string | null;
471
+ choices: {
472
+ answers: string[];
473
+ questionKey: string;
474
+ }[];
475
+ contact: {
476
+ email: string | null;
477
+ name: string | null;
478
+ phone: string | null;
479
+ };
480
+ formId: string;
481
+ freeAnswers: {
482
+ label: string;
483
+ questionKey: string;
484
+ value: string;
485
+ }[];
486
+ isOrganic: boolean;
487
+ leadgenId: string;
488
+ pageId: string;
489
+ platform: string | null;
490
+ receivedAt: number;
491
+ }, Promise<{
492
+ status: "duplicate";
493
+ leadId: import("convex/values").GenericId<"leads">;
494
+ } | {
495
+ status: "duplicate";
496
+ leadId: null;
497
+ } | {
498
+ status: "unlinked";
499
+ leadId: null;
500
+ } | {
501
+ status: "handler_missing";
502
+ leadId: null;
503
+ } | {
504
+ status: "ingested";
505
+ leadId: Id<"leads">;
506
+ }>>;
507
+ export declare const loadIngestJob: import("convex/server").RegisteredQuery<"internal", {
508
+ leadgenId?: string | undefined;
509
+ pageId: string;
510
+ }, Promise<{
511
+ status: "duplicate";
512
+ linkId?: undefined;
513
+ pageRowId?: undefined;
514
+ tokenCipher?: undefined;
515
+ tokenIv?: undefined;
516
+ } | {
517
+ status: "unlinked";
518
+ linkId?: undefined;
519
+ pageRowId?: undefined;
520
+ tokenCipher?: undefined;
521
+ tokenIv?: undefined;
522
+ } | {
523
+ status: "handler_missing";
524
+ linkId?: undefined;
525
+ pageRowId?: undefined;
526
+ tokenCipher?: undefined;
527
+ tokenIv?: undefined;
528
+ } | {
529
+ status: "paused";
530
+ linkId?: undefined;
531
+ pageRowId?: undefined;
532
+ tokenCipher?: undefined;
533
+ tokenIv?: undefined;
534
+ } | {
535
+ status: "ready";
536
+ linkId: import("convex/values").GenericId<"sitePages">;
537
+ pageRowId: import("convex/values").GenericId<"metaPages">;
538
+ tokenCipher: string;
539
+ tokenIv: string;
540
+ }>>;
541
+ export declare const formQuestions: import("convex/server").RegisteredQuery<"internal", {
542
+ formId: string;
543
+ }, Promise<{
544
+ pageId: string;
545
+ questions: {
546
+ key: string;
547
+ label: string;
548
+ options?: {
549
+ key: string;
550
+ value: string;
551
+ }[] | undefined;
552
+ type: string;
553
+ }[];
554
+ } | null>>;
555
+ /**
556
+ * Brings one lead in, from Meta's webhook (forwarded by the control plane to
557
+ * `/rastro/meta/leadgen`). Idempotent on the leadgen id; a lead that cannot
558
+ * come in now (no handler, a stopped Page) is left for the reconciliation.
559
+ */
560
+ export declare const ingestFormLead: import("convex/server").RegisteredAction<"internal", {
561
+ leadgenId: string;
562
+ pageId: string;
563
+ }, Promise<{
564
+ status: string;
565
+ }>>;
566
+ /**
567
+ * The webhook's way in (http.ts): schedules the ingestion when the Page feeds
568
+ * a site here. Answers whether it did.
569
+ */
570
+ export declare const scheduleLeadgen: import("convex/server").RegisteredMutation<"internal", {
571
+ leadgenId: string;
572
+ pageId: string;
573
+ }, Promise<{
574
+ scheduled: boolean;
575
+ }>>;
576
+ /** Makes sure the chain runs by `at` (starts it, or pulls it earlier). */
577
+ export declare function kickLeadsLoop(ctx: MutationCtx, at: number): Promise<void>;
578
+ /** One link of the chain: hands the due Pages to fresh runs, moves on. */
579
+ export declare const loop: import("convex/server").RegisteredMutation<"internal", {}, Promise<null>>;
580
+ export declare const loadReconcileJob: import("convex/server").RegisteredQuery<"internal", {
581
+ linkId: import("convex/values").GenericId<"sitePages">;
582
+ runId: string;
583
+ }, Promise<{
584
+ pageId: string;
585
+ reconcileFrom: number;
586
+ connectionActive: boolean;
587
+ handlerReady: boolean;
588
+ subscriptionDue: boolean;
589
+ page: {
590
+ pageRowId: import("convex/values").GenericId<"metaPages">;
591
+ tokenCipher: string;
592
+ tokenIv: string;
593
+ listed: boolean;
594
+ leadsAllowed: boolean;
595
+ invalid: boolean;
596
+ } | null;
597
+ } | null>>;
598
+ export declare const markSubscriptionChecked: import("convex/server").RegisteredMutation<"internal", {
599
+ at: number;
600
+ linkId: import("convex/values").GenericId<"sitePages">;
601
+ runId: string;
602
+ }, Promise<null>>;
603
+ /** The Page's active forms with where the run reads each from (seconds). */
604
+ export declare const reconcileForms: import("convex/server").RegisteredQuery<"internal", {
605
+ linkId: import("convex/values").GenericId<"sitePages">;
606
+ runId: string;
607
+ }, Promise<{
608
+ formId: string;
609
+ sinceSec: number;
610
+ }[]>>;
611
+ export declare const saveCursor: import("convex/server").RegisteredMutation<"internal", {
612
+ formId: string;
613
+ linkId: import("convex/values").GenericId<"sitePages">;
614
+ runId: string;
615
+ sec: number;
616
+ }, Promise<{
617
+ stop: boolean;
618
+ }>>;
619
+ /** Records how a run ended and when the Page is read next. */
620
+ export declare const finishReconcile: import("convex/server").RegisteredMutation<"internal", {
621
+ linkId: import("convex/values").GenericId<"sitePages">;
622
+ outcome: {
623
+ kind: "ok";
624
+ note: string | null;
625
+ regainMs: number | null;
626
+ usagePct: number;
627
+ } | {
628
+ kind: "connection" | "granted" | "key" | "other" | "permission" | "throttled" | "token";
629
+ message: string;
630
+ regainMs: number | null;
631
+ };
632
+ runId: string;
633
+ startedAt: number;
634
+ }, Promise<null>>;
635
+ /**
636
+ * One reconciliation run of a Page: its forms read again (new ones show up
637
+ * by themselves), then each active form's leads since its cursor, oldest
638
+ * first, in windows Meta lists completely (`reconcileForm`), through the
639
+ * same ingestion as the webhook. A lead that cannot come in now (the handler
640
+ * threw, or is missing) holds its form's cursor there, so it is read again
641
+ * next run, until it is given up on (MAX_LEAD_ATTEMPTS); leads already in
642
+ * are skipped by their leadgen id.
643
+ */
644
+ export declare const reconcilePage: import("convex/server").RegisteredAction<"internal", {
645
+ linkId: import("convex/values").GenericId<"sitePages">;
646
+ runId: string;
647
+ }, Promise<null>>;
648
+ /**
649
+ * Per form, over the cohort days in the range: its leads, qualified, sales
650
+ * and revenue (from the lead rollups), and where its rules sent the leads
651
+ * (columns, the host's entry, discards by reason, the ones sent back).
652
+ */
653
+ export declare const formsReport: import("convex/server").RegisteredQuery<"public", {
654
+ from: number;
655
+ siteIds: import("convex/values").GenericId<"sites">[];
656
+ to: number;
657
+ }, Promise<{
658
+ forms: {
659
+ siteId: Id<"sites">;
660
+ pageId: string;
661
+ formId: string;
662
+ name: string | null;
663
+ leads: number;
664
+ qualified: number;
665
+ won: number;
666
+ revenueCents: number;
667
+ columns: {
668
+ column: string;
669
+ leads: number;
670
+ }[];
671
+ entry: number;
672
+ discarded: {
673
+ reason: string;
674
+ leads: number;
675
+ }[];
676
+ returned: number;
677
+ }[];
678
+ partial: boolean;
679
+ }>>;
680
+ export {};
681
+ //# sourceMappingURL=metaLeads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metaLeads.d.ts","sourceRoot":"","sources":["../../src/component/metaLeads.ts"],"names":[],"mappings":"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"}