@iann29/rastro 0.9.0 → 0.10.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 (265) hide show
  1. package/README.md +9 -1
  2. package/agent/integration.md +23 -1
  3. package/agent/manifest.json +4 -4
  4. package/dist/client/federation.d.ts +114 -9
  5. package/dist/client/federation.d.ts.map +1 -1
  6. package/dist/client/federation.js +54 -2
  7. package/dist/client/federation.js.map +1 -1
  8. package/dist/client/index.d.ts +642 -8
  9. package/dist/client/index.d.ts.map +1 -1
  10. package/dist/client/index.js +391 -9
  11. package/dist/client/index.js.map +1 -1
  12. package/dist/component/_generated/api.d.ts +14 -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 +278 -1
  16. package/dist/component/_generated/component.d.ts.map +1 -1
  17. package/dist/component/_generated/server.d.ts +4 -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 +5 -0
  21. package/dist/component/constants.d.ts.map +1 -1
  22. package/dist/component/constants.js +10 -0
  23. package/dist/component/constants.js.map +1 -1
  24. package/dist/component/convex.config.d.ts +4 -0
  25. package/dist/component/convex.config.js +9 -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/leads.d.ts +69 -3
  31. package/dist/component/leads.d.ts.map +1 -1
  32. package/dist/component/leads.js +419 -16
  33. package/dist/component/leads.js.map +1 -1
  34. package/dist/component/meta.d.ts +358 -0
  35. package/dist/component/meta.d.ts.map +1 -0
  36. package/dist/component/meta.js +1295 -0
  37. package/dist/component/meta.js.map +1 -0
  38. package/dist/component/metaCapi.d.ts +162 -0
  39. package/dist/component/metaCapi.d.ts.map +1 -0
  40. package/dist/component/metaCapi.js +754 -0
  41. package/dist/component/metaCapi.js.map +1 -0
  42. package/dist/component/metaFake.d.ts +5 -0
  43. package/dist/component/metaFake.d.ts.map +1 -0
  44. package/dist/component/metaFake.js +225 -0
  45. package/dist/component/metaFake.js.map +1 -0
  46. package/dist/component/metaGraph.d.ts +165 -0
  47. package/dist/component/metaGraph.d.ts.map +1 -0
  48. package/dist/component/metaGraph.js +507 -0
  49. package/dist/component/metaGraph.js.map +1 -0
  50. package/dist/component/metaSync.d.ts +186 -0
  51. package/dist/component/metaSync.d.ts.map +1 -0
  52. package/dist/component/metaSync.js +961 -0
  53. package/dist/component/metaSync.js.map +1 -0
  54. package/dist/component/pipeline.d.ts +99 -0
  55. package/dist/component/pipeline.d.ts.map +1 -0
  56. package/dist/component/pipeline.js +337 -0
  57. package/dist/component/pipeline.js.map +1 -0
  58. package/dist/component/schema.d.ts +404 -2
  59. package/dist/component/schema.d.ts.map +1 -1
  60. package/dist/component/schema.js +168 -2
  61. package/dist/component/schema.js.map +1 -1
  62. package/dist/component/secrets.d.ts +15 -0
  63. package/dist/component/secrets.d.ts.map +1 -0
  64. package/dist/component/secrets.js +67 -0
  65. package/dist/component/secrets.js.map +1 -0
  66. package/dist/component/validators.d.ts +1052 -15
  67. package/dist/component/validators.d.ts.map +1 -1
  68. package/dist/component/validators.js +307 -3
  69. package/dist/component/validators.js.map +1 -1
  70. package/dist/tracker/generated.d.ts +1 -1
  71. package/dist/tracker/generated.d.ts.map +1 -1
  72. package/dist/tracker/generated.js +1 -1
  73. package/dist/tracker/generated.js.map +1 -1
  74. package/dist/ui/campaigns/CampaignsView.d.ts +48 -0
  75. package/dist/ui/campaigns/CampaignsView.d.ts.map +1 -0
  76. package/dist/ui/campaigns/CampaignsView.js +47 -0
  77. package/dist/ui/campaigns/CampaignsView.js.map +1 -0
  78. package/dist/ui/campaigns/Conversions.d.ts +16 -0
  79. package/dist/ui/campaigns/Conversions.d.ts.map +1 -0
  80. package/dist/ui/campaigns/Conversions.js +40 -0
  81. package/dist/ui/campaigns/Conversions.js.map +1 -0
  82. package/dist/ui/campaigns/Drawer.d.ts +24 -0
  83. package/dist/ui/campaigns/Drawer.d.ts.map +1 -0
  84. package/dist/ui/campaigns/Drawer.js +120 -0
  85. package/dist/ui/campaigns/Drawer.js.map +1 -0
  86. package/dist/ui/campaigns/Icons.d.ts +35 -0
  87. package/dist/ui/campaigns/Icons.d.ts.map +1 -0
  88. package/dist/ui/campaigns/Icons.js +41 -0
  89. package/dist/ui/campaigns/Icons.js.map +1 -0
  90. package/dist/ui/campaigns/Summary.d.ts +21 -0
  91. package/dist/ui/campaigns/Summary.d.ts.map +1 -0
  92. package/dist/ui/campaigns/Summary.js +56 -0
  93. package/dist/ui/campaigns/Summary.js.map +1 -0
  94. package/dist/ui/campaigns/Thumbnail.d.ts +11 -0
  95. package/dist/ui/campaigns/Thumbnail.d.ts.map +1 -0
  96. package/dist/ui/campaigns/Thumbnail.js +23 -0
  97. package/dist/ui/campaigns/Thumbnail.js.map +1 -0
  98. package/dist/ui/campaigns/Tree.d.ts +12 -0
  99. package/dist/ui/campaigns/Tree.d.ts.map +1 -0
  100. package/dist/ui/campaigns/Tree.js +105 -0
  101. package/dist/ui/campaigns/Tree.js.map +1 -0
  102. package/dist/ui/campaigns/glyphs.d.ts +20 -0
  103. package/dist/ui/campaigns/glyphs.d.ts.map +1 -0
  104. package/dist/ui/campaigns/glyphs.js +19 -0
  105. package/dist/ui/campaigns/glyphs.js.map +1 -0
  106. package/dist/ui/campaigns/index.d.ts +4 -0
  107. package/dist/ui/campaigns/index.d.ts.map +1 -0
  108. package/dist/ui/campaigns/index.js +3 -0
  109. package/dist/ui/campaigns/index.js.map +1 -0
  110. package/dist/ui/campaigns/labels.d.ts +53 -0
  111. package/dist/ui/campaigns/labels.d.ts.map +1 -0
  112. package/dist/ui/campaigns/labels.js +169 -0
  113. package/dist/ui/campaigns/labels.js.map +1 -0
  114. package/dist/ui/campaigns/model.d.ts +99 -0
  115. package/dist/ui/campaigns/model.d.ts.map +1 -0
  116. package/dist/ui/campaigns/model.js +230 -0
  117. package/dist/ui/campaigns/model.js.map +1 -0
  118. package/dist/ui/campaigns/modes.d.ts +18 -0
  119. package/dist/ui/campaigns/modes.d.ts.map +1 -0
  120. package/dist/ui/campaigns/modes.js +7 -0
  121. package/dist/ui/campaigns/modes.js.map +1 -0
  122. package/dist/ui/index.d.ts +21 -0
  123. package/dist/ui/index.d.ts.map +1 -0
  124. package/dist/ui/index.js +20 -0
  125. package/dist/ui/index.js.map +1 -0
  126. package/dist/ui/integrations/AccountPicker.d.ts +26 -0
  127. package/dist/ui/integrations/AccountPicker.d.ts.map +1 -0
  128. package/dist/ui/integrations/AccountPicker.js +101 -0
  129. package/dist/ui/integrations/AccountPicker.js.map +1 -0
  130. package/dist/ui/integrations/ClientCards.d.ts +17 -0
  131. package/dist/ui/integrations/ClientCards.d.ts.map +1 -0
  132. package/dist/ui/integrations/ClientCards.js +42 -0
  133. package/dist/ui/integrations/ClientCards.js.map +1 -0
  134. package/dist/ui/integrations/ClientsTable.d.ts +36 -0
  135. package/dist/ui/integrations/ClientsTable.d.ts.map +1 -0
  136. package/dist/ui/integrations/ClientsTable.js +143 -0
  137. package/dist/ui/integrations/ClientsTable.js.map +1 -0
  138. package/dist/ui/integrations/Connect.d.ts +35 -0
  139. package/dist/ui/integrations/Connect.d.ts.map +1 -0
  140. package/dist/ui/integrations/Connect.js +62 -0
  141. package/dist/ui/integrations/Connect.js.map +1 -0
  142. package/dist/ui/integrations/Connection.d.ts +37 -0
  143. package/dist/ui/integrations/Connection.d.ts.map +1 -0
  144. package/dist/ui/integrations/Connection.js +108 -0
  145. package/dist/ui/integrations/Connection.js.map +1 -0
  146. package/dist/ui/integrations/Dialogs.d.ts +21 -0
  147. package/dist/ui/integrations/Dialogs.d.ts.map +1 -0
  148. package/dist/ui/integrations/Dialogs.js +34 -0
  149. package/dist/ui/integrations/Dialogs.js.map +1 -0
  150. package/dist/ui/integrations/EventsFeed.d.ts +15 -0
  151. package/dist/ui/integrations/EventsFeed.d.ts.map +1 -0
  152. package/dist/ui/integrations/EventsFeed.js +61 -0
  153. package/dist/ui/integrations/EventsFeed.js.map +1 -0
  154. package/dist/ui/integrations/EventsSheet.d.ts +34 -0
  155. package/dist/ui/integrations/EventsSheet.d.ts.map +1 -0
  156. package/dist/ui/integrations/EventsSheet.js +136 -0
  157. package/dist/ui/integrations/EventsSheet.js.map +1 -0
  158. package/dist/ui/integrations/Icons.d.ts +38 -0
  159. package/dist/ui/integrations/Icons.d.ts.map +1 -0
  160. package/dist/ui/integrations/Icons.js +40 -0
  161. package/dist/ui/integrations/Icons.js.map +1 -0
  162. package/dist/ui/integrations/IntegrationsView.d.ts +15 -0
  163. package/dist/ui/integrations/IntegrationsView.d.ts.map +1 -0
  164. package/dist/ui/integrations/IntegrationsView.js +141 -0
  165. package/dist/ui/integrations/IntegrationsView.js.map +1 -0
  166. package/dist/ui/integrations/Overlay.d.ts +18 -0
  167. package/dist/ui/integrations/Overlay.d.ts.map +1 -0
  168. package/dist/ui/integrations/Overlay.js +36 -0
  169. package/dist/ui/integrations/Overlay.js.map +1 -0
  170. package/dist/ui/integrations/Partner.d.ts +14 -0
  171. package/dist/ui/integrations/Partner.d.ts.map +1 -0
  172. package/dist/ui/integrations/Partner.js +38 -0
  173. package/dist/ui/integrations/Partner.js.map +1 -0
  174. package/dist/ui/integrations/RowMenu.d.ts +15 -0
  175. package/dist/ui/integrations/RowMenu.d.ts.map +1 -0
  176. package/dist/ui/integrations/RowMenu.js +47 -0
  177. package/dist/ui/integrations/RowMenu.js.map +1 -0
  178. package/dist/ui/integrations/UnlinkDialog.d.ts +18 -0
  179. package/dist/ui/integrations/UnlinkDialog.d.ts.map +1 -0
  180. package/dist/ui/integrations/UnlinkDialog.js +29 -0
  181. package/dist/ui/integrations/UnlinkDialog.js.map +1 -0
  182. package/dist/ui/integrations/audience.d.ts +12 -0
  183. package/dist/ui/integrations/audience.d.ts.map +1 -0
  184. package/dist/ui/integrations/audience.js +12 -0
  185. package/dist/ui/integrations/audience.js.map +1 -0
  186. package/dist/ui/integrations/format.d.ts +28 -0
  187. package/dist/ui/integrations/format.d.ts.map +1 -0
  188. package/dist/ui/integrations/format.js +101 -0
  189. package/dist/ui/integrations/format.js.map +1 -0
  190. package/dist/ui/integrations/index.d.ts +5 -0
  191. package/dist/ui/integrations/index.d.ts.map +1 -0
  192. package/dist/ui/integrations/index.js +3 -0
  193. package/dist/ui/integrations/index.js.map +1 -0
  194. package/dist/ui/integrations/modal.d.ts +10 -0
  195. package/dist/ui/integrations/modal.d.ts.map +1 -0
  196. package/dist/ui/integrations/modal.js +77 -0
  197. package/dist/ui/integrations/modal.js.map +1 -0
  198. package/dist/ui/integrations/model.d.ts +99 -0
  199. package/dist/ui/integrations/model.d.ts.map +1 -0
  200. package/dist/ui/integrations/model.js +164 -0
  201. package/dist/ui/integrations/model.js.map +1 -0
  202. package/dist/ui/integrations/parts.d.ts +36 -0
  203. package/dist/ui/integrations/parts.d.ts.map +1 -0
  204. package/dist/ui/integrations/parts.js +85 -0
  205. package/dist/ui/integrations/parts.js.map +1 -0
  206. package/dist/ui/integrations/types.d.ts +146 -0
  207. package/dist/ui/integrations/types.d.ts.map +1 -0
  208. package/dist/ui/integrations/types.js +2 -0
  209. package/dist/ui/integrations/types.js.map +1 -0
  210. package/dist/ui/metrics.d.ts +106 -0
  211. package/dist/ui/metrics.d.ts.map +1 -0
  212. package/dist/ui/metrics.js +166 -0
  213. package/dist/ui/metrics.js.map +1 -0
  214. package/dist/ui/portfolio/PortfolioView.d.ts +26 -0
  215. package/dist/ui/portfolio/PortfolioView.d.ts.map +1 -0
  216. package/dist/ui/portfolio/PortfolioView.js +216 -0
  217. package/dist/ui/portfolio/PortfolioView.js.map +1 -0
  218. package/dist/ui/portfolio/SpendChart.d.ts +10 -0
  219. package/dist/ui/portfolio/SpendChart.d.ts.map +1 -0
  220. package/dist/ui/portfolio/SpendChart.js +196 -0
  221. package/dist/ui/portfolio/SpendChart.js.map +1 -0
  222. package/dist/ui/portfolio/alerts.d.ts +74 -0
  223. package/dist/ui/portfolio/alerts.d.ts.map +1 -0
  224. package/dist/ui/portfolio/alerts.js +291 -0
  225. package/dist/ui/portfolio/alerts.js.map +1 -0
  226. package/dist/ui/portfolio/figures.d.ts +79 -0
  227. package/dist/ui/portfolio/figures.d.ts.map +1 -0
  228. package/dist/ui/portfolio/figures.js +103 -0
  229. package/dist/ui/portfolio/figures.js.map +1 -0
  230. package/dist/ui/portfolio/format.d.ts +8 -0
  231. package/dist/ui/portfolio/format.d.ts.map +1 -0
  232. package/dist/ui/portfolio/format.js +28 -0
  233. package/dist/ui/portfolio/format.js.map +1 -0
  234. package/dist/ui/sample.d.ts +536 -0
  235. package/dist/ui/sample.d.ts.map +1 -0
  236. package/dist/ui/sample.js +574 -0
  237. package/dist/ui/sample.js.map +1 -0
  238. package/dist/ui/seed.d.ts +188 -0
  239. package/dist/ui/seed.d.ts.map +1 -0
  240. package/dist/ui/seed.js +563 -0
  241. package/dist/ui/seed.js.map +1 -0
  242. package/dist/ui/ui.css +3424 -0
  243. package/docs/federation.md +46 -1
  244. package/docs/meta-ads.md +795 -0
  245. package/docs/upgrading.md +116 -0
  246. package/llms.txt +3 -0
  247. package/package.json +15 -3
  248. package/src/component/_generated/api.ts +14 -0
  249. package/src/component/_generated/component.ts +324 -1
  250. package/src/component/_generated/server.ts +4 -0
  251. package/src/component/constants.ts +10 -0
  252. package/src/component/convex.config.ts +9 -0
  253. package/src/component/errors.ts +5 -1
  254. package/src/component/leads.ts +517 -17
  255. package/src/component/meta.ts +1525 -0
  256. package/src/component/metaCapi.ts +921 -0
  257. package/src/component/metaFake.ts +277 -0
  258. package/src/component/metaGraph.ts +722 -0
  259. package/src/component/metaSync.ts +1164 -0
  260. package/src/component/pipeline.ts +410 -0
  261. package/src/component/schema.ts +197 -1
  262. package/src/component/secrets.ts +98 -0
  263. package/src/component/validators.ts +376 -3
  264. package/src/tracker/generated.ts +1 -1
  265. package/src/ui/seed.ts +755 -0
@@ -0,0 +1,277 @@
1
+ import { SAMPLE_SEED } from "../ui/seed.js";
2
+ import {
3
+ actId,
4
+ MetaGraphError,
5
+ type GraphAd,
6
+ type GraphPixel,
7
+ type GraphSpendRow,
8
+ type MetaGraph,
9
+ } from "./metaGraph.js";
10
+
11
+ /*
12
+ * The Meta Graph API under RASTRO_META_FAKE=true: the sample agency of
13
+ * `@iann29/rastro/ui/sample` (four clients, their ad accounts, catalog and
14
+ * spend per ad per day), so the example host's demo and the screens' sample
15
+ * show the same numbers. Any token works except one containing "invalid",
16
+ * which Meta refuses like an expired token. A token
17
+ * `rastro-fake-sample-token:<days>` moves every date by that many whole days,
18
+ * so a demo seeded today reads the sample as its last 30 days, sync after
19
+ * sync. Conversions API sends are accepted. No network call is made.
20
+ */
21
+
22
+ const BUSINESS = { id: "sample-business", name: "Connection Company" };
23
+ const USAGE = { pct: 0, regainMs: null };
24
+ const DAY_MS = 86_400_000;
25
+ const FAKE_SHORT_TOKEN = "rastro-fake-user-token:";
26
+ const FAKE_LONG_TOKEN = "rastro-fake-long-token:";
27
+ const FAKE_SHORT_MS = 2 * 60 * 60 * 1000;
28
+ const FAKE_LONG_MS = 60 * DAY_MS;
29
+ const SHIFT_TOKEN = /^rastro-fake-sample-token:(-?\d{1,5})$/;
30
+
31
+ /** The whole days a fake token moves the sample by (0 for any other). */
32
+ export function fakeShiftDays(token: string): number {
33
+ const match = SHIFT_TOKEN.exec(token);
34
+ return match ? Number(match[1]) : 0;
35
+ }
36
+
37
+ const shiftDate = (date: string, days: number) =>
38
+ days === 0
39
+ ? date
40
+ : new Date(Date.parse(`${date}T00:00:00Z`) + days * DAY_MS)
41
+ .toISOString()
42
+ .slice(0, 10);
43
+
44
+ /** `total` split over `weights` in whole units, largest remainder first. */
45
+ function spread(total: number, weights: readonly number[]): number[] {
46
+ const sum = weights.reduce((acc, weight) => acc + weight, 0);
47
+ if (sum <= 0) return weights.map(() => 0);
48
+ const raw = weights.map((weight) => (weight / sum) * total);
49
+ const out = raw.map((value) => Math.floor(value + 1e-9));
50
+ let left = total - out.reduce((acc, value) => acc + value, 0);
51
+ const order = raw
52
+ .map((value, index) => ({ index, rest: value - (out[index] ?? 0) }))
53
+ .sort((a, b) => b.rest - a.rest || a.index - b.index);
54
+ for (const { index } of order) {
55
+ if (left <= 0) break;
56
+ out[index] = (out[index] ?? 0) + 1;
57
+ left -= 1;
58
+ }
59
+ return out;
60
+ }
61
+
62
+ type Day = { dayStart: number; spendCents: number | null };
63
+
64
+ /**
65
+ * One period of one ad as Meta would report it: the day's spend, and the
66
+ * sample's reach (48 impressions per real spent, 2.1% of them clicked) spread
67
+ * over the days by spend, so the period sums to the sample's totals.
68
+ */
69
+ function periodRows(
70
+ ad: { adId: string },
71
+ meta: Omit<
72
+ GraphSpendRow,
73
+ "adId" | "date" | "spendCents" | "impressions" | "clicks" | "conversations"
74
+ >,
75
+ days: readonly Day[],
76
+ ): GraphSpendRow[] {
77
+ const cents = days.map((day) => day.spendCents ?? 0);
78
+ const total = cents.reduce((acc, value) => acc + value, 0);
79
+ const impressions = Math.round((total / 100) * 48);
80
+ const clicks = Math.round(impressions * 0.021);
81
+ const dayImpressions = spread(impressions, cents);
82
+ const dayClicks = spread(clicks, cents);
83
+ return days.flatMap((day, index) =>
84
+ (day.spendCents ?? 0) > 0
85
+ ? [
86
+ {
87
+ adId: ad.adId,
88
+ date: new Date(day.dayStart).toISOString().slice(0, 10),
89
+ spendCents: day.spendCents ?? 0,
90
+ impressions: dayImpressions[index] ?? 0,
91
+ clicks: dayClicks[index] ?? 0,
92
+ conversations: 0,
93
+ ...meta,
94
+ },
95
+ ]
96
+ : [],
97
+ );
98
+ }
99
+
100
+ interface FakeAccount {
101
+ adAccountId: string;
102
+ name: string;
103
+ currency: string;
104
+ timezone: string;
105
+ pixelId: string | null;
106
+ pixelName: string | null;
107
+ ads: GraphAd[];
108
+ rows: GraphSpendRow[];
109
+ }
110
+
111
+ let accounts: FakeAccount[] | null = null;
112
+
113
+ function fixtures(): FakeAccount[] {
114
+ accounts ??= SAMPLE_SEED.map((site) => {
115
+ const ads: GraphAd[] = [];
116
+ const rows: GraphSpendRow[] = [];
117
+ for (const campaign of site.campaigns) {
118
+ for (const adset of campaign.adsets) {
119
+ for (const ad of adset.ads) {
120
+ const names = {
121
+ adName: ad.name,
122
+ adsetId: adset.adsetId,
123
+ adsetName: adset.name,
124
+ campaignId: campaign.campaignId,
125
+ campaignName: campaign.name,
126
+ };
127
+ ads.push({
128
+ adId: ad.adId,
129
+ name: ad.name,
130
+ effectiveStatus: ad.adStatus,
131
+ adsetId: adset.adsetId,
132
+ adsetName: adset.name,
133
+ campaignId: campaign.campaignId,
134
+ campaignName: campaign.name,
135
+ creativeType: ad.creativeType,
136
+ thumbnailUrl: null,
137
+ });
138
+ rows.push(...periodRows(ad, names, ad.daily));
139
+ if (ad.previousDaily) {
140
+ rows.push(...periodRows(ad, names, ad.previousDaily));
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return {
146
+ ...site.adAccount,
147
+ pixelId: site.pixelId,
148
+ pixelName: site.pixelId ? `Pixel ${site.name}` : null,
149
+ ads,
150
+ rows,
151
+ };
152
+ });
153
+ return accounts;
154
+ }
155
+
156
+ function checkToken(token: string) {
157
+ if (token.includes("invalid")) {
158
+ throw new MetaGraphError(
159
+ "token",
160
+ "Error validating access token: the session is invalid (fake)",
161
+ 190,
162
+ );
163
+ }
164
+ }
165
+
166
+ function account(adAccountId: string): FakeAccount {
167
+ const found = fixtures().find(
168
+ (row) => row.adAccountId === actId(adAccountId),
169
+ );
170
+ if (!found) {
171
+ throw new MetaGraphError(
172
+ "permission",
173
+ "ad account not reachable (fake)",
174
+ 200,
175
+ );
176
+ }
177
+ return found;
178
+ }
179
+
180
+ export function fakeMetaGraph(): MetaGraph {
181
+ return {
182
+ async exchangeCode(_app, code) {
183
+ // Any code logs in except one containing "invalid", refused like an
184
+ // expired token; the token it yields reads the unshifted sample. A
185
+ // code containing "user-token" yields a short-lived user token, as a
186
+ // login without a system user configuration does; any other, a system
187
+ // user token that never expires.
188
+ checkToken(code);
189
+ const clean = code.replace(/[^A-Za-z0-9_-]/g, "").slice(0, 64);
190
+ return code.includes("user-token")
191
+ ? {
192
+ accessToken: `${FAKE_SHORT_TOKEN}${clean}`,
193
+ expiresInMs: FAKE_SHORT_MS,
194
+ }
195
+ : {
196
+ accessToken: `rastro-fake-login-token:${clean}`,
197
+ expiresInMs: null,
198
+ };
199
+ },
200
+ async debugToken(_app, token) {
201
+ checkToken(token);
202
+ if (token.startsWith(FAKE_SHORT_TOKEN)) {
203
+ return { type: "USER", expiresAt: Date.now() + FAKE_SHORT_MS };
204
+ }
205
+ if (token.startsWith(FAKE_LONG_TOKEN)) {
206
+ return { type: "USER", expiresAt: Date.now() + FAKE_LONG_MS };
207
+ }
208
+ return { type: "SYSTEM_USER", expiresAt: null };
209
+ },
210
+ async exchangeLongLived(_app, token) {
211
+ checkToken(token);
212
+ return {
213
+ accessToken: `${FAKE_LONG_TOKEN}${token.slice(FAKE_SHORT_TOKEN.length)}`,
214
+ expiresInMs: FAKE_LONG_MS,
215
+ };
216
+ },
217
+ async me(token) {
218
+ checkToken(token);
219
+ return { ...BUSINESS };
220
+ },
221
+ async adAccounts(token) {
222
+ checkToken(token);
223
+ return fixtures().map((row) => ({
224
+ adAccountId: row.adAccountId,
225
+ name: row.name,
226
+ currency: row.currency,
227
+ timezone: row.timezone,
228
+ accountStatus: 1,
229
+ }));
230
+ },
231
+ async adPixels(token, adAccountId): Promise<GraphPixel[]> {
232
+ checkToken(token);
233
+ const row = account(adAccountId);
234
+ return row.pixelId && row.pixelName
235
+ ? [{ pixelId: row.pixelId, name: row.pixelName }]
236
+ : [];
237
+ },
238
+ async ads(token, adAccountId, adIds) {
239
+ checkToken(token);
240
+ const all = account(adAccountId).ads;
241
+ return {
242
+ ads: adIds ? all.filter((ad) => adIds.includes(ad.adId)) : [...all],
243
+ usage: USAGE,
244
+ complete: true,
245
+ };
246
+ },
247
+ async insights(token, adAccountId, since, until) {
248
+ checkToken(token);
249
+ const days = fakeShiftDays(token);
250
+ return {
251
+ rows: account(adAccountId)
252
+ .rows.map((row) => ({ ...row, date: shiftDate(row.date, days) }))
253
+ .filter((row) => row.date >= since && row.date <= until),
254
+ usage: USAGE,
255
+ complete: true,
256
+ };
257
+ },
258
+ async pixel(token, pixelId) {
259
+ checkToken(token);
260
+ if (!fixtures().some((row) => row.pixelId === pixelId)) {
261
+ throw new MetaGraphError(
262
+ "permission",
263
+ "pixel not reachable (fake)",
264
+ 200,
265
+ );
266
+ }
267
+ return { id: pixelId };
268
+ },
269
+ async thumbnail() {
270
+ return null;
271
+ },
272
+ async conversions(token, _pixelId, payload) {
273
+ checkToken(token);
274
+ return { eventsReceived: payload.data.length, fbtraceId: "fake-trace" };
275
+ },
276
+ };
277
+ }