@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.
- package/README.md +8 -0
- package/agent/integration.md +45 -0
- package/agent/manifest.json +4 -4
- package/dist/client/federation.d.ts +82 -9
- package/dist/client/federation.d.ts.map +1 -1
- package/dist/client/federation.js +40 -2
- package/dist/client/federation.js.map +1 -1
- package/dist/client/index.d.ts +464 -8
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +259 -7
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +10 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +273 -21
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/_generated/server.d.ts +2 -0
- package/dist/component/_generated/server.d.ts.map +1 -1
- package/dist/component/_generated/server.js.map +1 -1
- package/dist/component/constants.d.ts +31 -0
- package/dist/component/constants.d.ts.map +1 -1
- package/dist/component/constants.js +31 -0
- package/dist/component/constants.js.map +1 -1
- package/dist/component/convex.config.d.ts +2 -0
- package/dist/component/convex.config.js +7 -0
- package/dist/component/convex.config.js.map +1 -1
- package/dist/component/errors.d.ts +1 -1
- package/dist/component/errors.d.ts.map +1 -1
- package/dist/component/errors.js.map +1 -1
- package/dist/component/http.d.ts.map +1 -1
- package/dist/component/http.js +64 -0
- package/dist/component/http.js.map +1 -1
- package/dist/component/leadAdsValidators.d.ts +1092 -0
- package/dist/component/leadAdsValidators.d.ts.map +1 -0
- package/dist/component/leadAdsValidators.js +304 -0
- package/dist/component/leadAdsValidators.js.map +1 -0
- package/dist/component/leadFormRules.d.ts +60 -0
- package/dist/component/leadFormRules.d.ts.map +1 -0
- package/dist/component/leadFormRules.js +140 -0
- package/dist/component/leadFormRules.js.map +1 -0
- package/dist/component/leadFormStore.d.ts +16 -0
- package/dist/component/leadFormStore.d.ts.map +1 -0
- package/dist/component/leadFormStore.js +92 -0
- package/dist/component/leadFormStore.js.map +1 -0
- package/dist/component/leadgenToken.d.ts +56 -0
- package/dist/component/leadgenToken.d.ts.map +1 -0
- package/dist/component/leadgenToken.js +262 -0
- package/dist/component/leadgenToken.js.map +1 -0
- package/dist/component/leads.d.ts +76 -7
- package/dist/component/leads.d.ts.map +1 -1
- package/dist/component/leads.js +112 -78
- package/dist/component/leads.js.map +1 -1
- package/dist/component/meta.d.ts.map +1 -1
- package/dist/component/meta.js +21 -1
- package/dist/component/meta.js.map +1 -1
- package/dist/component/metaFake.d.ts +44 -0
- package/dist/component/metaFake.d.ts.map +1 -1
- package/dist/component/metaFake.js +400 -1
- package/dist/component/metaFake.js.map +1 -1
- package/dist/component/metaGraph.d.ts +91 -0
- package/dist/component/metaGraph.d.ts.map +1 -1
- package/dist/component/metaGraph.js +217 -0
- package/dist/component/metaGraph.js.map +1 -1
- package/dist/component/metaLeads.d.ts +681 -0
- package/dist/component/metaLeads.d.ts.map +1 -0
- package/dist/component/metaLeads.js +2634 -0
- package/dist/component/metaLeads.js.map +1 -0
- package/dist/component/schema.d.ts +414 -5
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +169 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/validators.d.ts +235 -11
- package/dist/component/validators.d.ts.map +1 -1
- package/dist/component/validators.js +14 -1
- package/dist/component/validators.js.map +1 -1
- package/dist/tracker/generated.d.ts +1 -1
- package/dist/tracker/generated.js +1 -1
- package/dist/ui/campaigns/CampaignsView.d.ts +5 -1
- package/dist/ui/campaigns/CampaignsView.d.ts.map +1 -1
- package/dist/ui/campaigns/CampaignsView.js.map +1 -1
- package/dist/ui/campaigns/Drawer.d.ts.map +1 -1
- package/dist/ui/campaigns/Drawer.js +8 -26
- package/dist/ui/campaigns/Drawer.js.map +1 -1
- package/dist/ui/campaigns/labels.d.ts +29 -1
- package/dist/ui/campaigns/labels.d.ts.map +1 -1
- package/dist/ui/campaigns/labels.js +77 -2
- package/dist/ui/campaigns/labels.js.map +1 -1
- package/dist/ui/campaigns/model.js +2 -2
- package/dist/ui/campaigns/model.js.map +1 -1
- package/dist/ui/forms/FirstContact.d.ts +19 -0
- package/dist/ui/forms/FirstContact.d.ts.map +1 -0
- package/dist/ui/forms/FirstContact.js +81 -0
- package/dist/ui/forms/FirstContact.js.map +1 -0
- package/dist/ui/forms/FormLead.d.ts +28 -0
- package/dist/ui/forms/FormLead.d.ts.map +1 -0
- package/dist/ui/forms/FormLead.js +199 -0
- package/dist/ui/forms/FormLead.js.map +1 -0
- package/dist/ui/forms/FormRulesDrawer.d.ts +49 -0
- package/dist/ui/forms/FormRulesDrawer.d.ts.map +1 -0
- package/dist/ui/forms/FormRulesDrawer.js +149 -0
- package/dist/ui/forms/FormRulesDrawer.js.map +1 -0
- package/dist/ui/forms/FormsView.d.ts +10 -0
- package/dist/ui/forms/FormsView.d.ts.map +1 -0
- package/dist/ui/forms/FormsView.js +215 -0
- package/dist/ui/forms/FormsView.js.map +1 -0
- package/dist/ui/forms/Icons.d.ts +46 -0
- package/dist/ui/forms/Icons.d.ts.map +1 -0
- package/dist/ui/forms/Icons.js +45 -0
- package/dist/ui/forms/Icons.js.map +1 -0
- package/dist/ui/forms/RuleRow.d.ts +37 -0
- package/dist/ui/forms/RuleRow.d.ts.map +1 -0
- package/dist/ui/forms/RuleRow.js +80 -0
- package/dist/ui/forms/RuleRow.js.map +1 -0
- package/dist/ui/forms/WhatsAppButtonGuide.d.ts +33 -0
- package/dist/ui/forms/WhatsAppButtonGuide.d.ts.map +1 -0
- package/dist/ui/forms/WhatsAppButtonGuide.js +90 -0
- package/dist/ui/forms/WhatsAppButtonGuide.js.map +1 -0
- package/dist/ui/forms/index.d.ts +11 -0
- package/dist/ui/forms/index.d.ts.map +1 -0
- package/dist/ui/forms/index.js +7 -0
- package/dist/ui/forms/index.js.map +1 -0
- package/dist/ui/forms/journey.d.ts +19 -0
- package/dist/ui/forms/journey.d.ts.map +1 -0
- package/dist/ui/forms/journey.js +54 -0
- package/dist/ui/forms/journey.js.map +1 -0
- package/dist/ui/forms/model.d.ts +239 -0
- package/dist/ui/forms/model.d.ts.map +1 -0
- package/dist/ui/forms/model.js +556 -0
- package/dist/ui/forms/model.js.map +1 -0
- package/dist/ui/forms/sample.d.ts +36 -0
- package/dist/ui/forms/sample.d.ts.map +1 -0
- package/dist/ui/forms/sample.js +444 -0
- package/dist/ui/forms/sample.js.map +1 -0
- package/dist/ui/forms/types.d.ts +454 -0
- package/dist/ui/forms/types.d.ts.map +1 -0
- package/dist/ui/forms/types.js +2 -0
- package/dist/ui/forms/types.js.map +1 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +4 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/integrations/Overlay.d.ts +3 -1
- package/dist/ui/integrations/Overlay.d.ts.map +1 -1
- package/dist/ui/integrations/Overlay.js +2 -2
- package/dist/ui/integrations/Overlay.js.map +1 -1
- package/dist/ui/portfolio/PortfolioView.d.ts +4 -1
- package/dist/ui/portfolio/PortfolioView.d.ts.map +1 -1
- package/dist/ui/portfolio/PortfolioView.js.map +1 -1
- package/dist/ui/sample.d.ts +3 -1
- package/dist/ui/sample.d.ts.map +1 -1
- package/dist/ui/sample.js +2 -0
- package/dist/ui/sample.js.map +1 -1
- package/dist/ui/seed.d.ts +1 -1
- package/dist/ui/ui.css +2301 -0
- package/docs/federation.md +19 -0
- package/docs/meta-ads.md +713 -7
- package/docs/upgrading.md +70 -0
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/src/component/_generated/api.ts +10 -0
- package/src/component/_generated/component.ts +289 -20
- package/src/component/_generated/server.ts +2 -0
- package/src/component/constants.ts +33 -0
- package/src/component/convex.config.ts +7 -0
- package/src/component/errors.ts +3 -1
- package/src/component/http.ts +75 -0
- package/src/component/leadAdsValidators.ts +365 -0
- package/src/component/leadFormRules.ts +202 -0
- package/src/component/leadFormStore.ts +129 -0
- package/src/component/leadgenToken.ts +348 -0
- package/src/component/leads.ts +136 -84
- package/src/component/meta.ts +21 -1
- package/src/component/metaFake.ts +485 -1
- package/src/component/metaGraph.ts +327 -0
- package/src/component/metaLeads.ts +3101 -0
- package/src/component/schema.ts +187 -1
- package/src/component/validators.ts +17 -1
- package/src/tracker/generated.ts +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { labelChoices } from "./leadFormRules.js";
|
|
2
|
+
/*
|
|
3
|
+
* Reads and clean-up of a form lead's record (`formLeads`), shared by the
|
|
4
|
+
* lead journey (leads.ts) and the Lead Ads module (metaLeads.ts).
|
|
5
|
+
*/
|
|
6
|
+
/** Where a form lead came from, with the names Rastro knows. */
|
|
7
|
+
export async function formLeadOrigin(ctx, row) {
|
|
8
|
+
const link = await ctx.db
|
|
9
|
+
.query("sitePages")
|
|
10
|
+
.withIndex("by_pageId", (range) => range.eq("pageId", row.pageId))
|
|
11
|
+
.first();
|
|
12
|
+
const page = link ??
|
|
13
|
+
(await ctx.db
|
|
14
|
+
.query("metaPages")
|
|
15
|
+
.withIndex("by_pageId", (range) => range.eq("pageId", row.pageId))
|
|
16
|
+
.first());
|
|
17
|
+
const form = await ctx.db
|
|
18
|
+
.query("metaForms")
|
|
19
|
+
.withIndex("by_formId", (range) => range.eq("formId", row.formId))
|
|
20
|
+
.first();
|
|
21
|
+
const catalog = row.adId
|
|
22
|
+
? await ctx.db
|
|
23
|
+
.query("adCatalog")
|
|
24
|
+
.withIndex("by_siteId_and_adId", (range) => range.eq("siteId", row.siteId).eq("adId", row.adId))
|
|
25
|
+
.unique()
|
|
26
|
+
: null;
|
|
27
|
+
return {
|
|
28
|
+
pageId: row.pageId,
|
|
29
|
+
pageName: page?.name ?? null,
|
|
30
|
+
formId: row.formId,
|
|
31
|
+
formName: form?.name ?? null,
|
|
32
|
+
adId: row.adId ?? null,
|
|
33
|
+
adName: catalog?.adName ?? null,
|
|
34
|
+
adsetId: row.adsetId ?? catalog?.adsetId ?? null,
|
|
35
|
+
adsetName: catalog?.adsetName ?? null,
|
|
36
|
+
campaignId: row.campaignId ?? catalog?.campaignId ?? null,
|
|
37
|
+
campaignName: catalog?.campaignName ?? null,
|
|
38
|
+
platform: row.platform ?? null,
|
|
39
|
+
isOrganic: row.isOrganic,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** A form lead's answers, origin and path, for the lead journey. */
|
|
43
|
+
export async function formLeadDetail(ctx, lead) {
|
|
44
|
+
const row = await ctx.db
|
|
45
|
+
.query("formLeads")
|
|
46
|
+
.withIndex("by_leadId", (range) => range.eq("leadId", lead._id))
|
|
47
|
+
.first();
|
|
48
|
+
if (!row)
|
|
49
|
+
return null;
|
|
50
|
+
const form = await ctx.db
|
|
51
|
+
.query("metaForms")
|
|
52
|
+
.withIndex("by_formId", (range) => range.eq("formId", row.formId))
|
|
53
|
+
.first();
|
|
54
|
+
return {
|
|
55
|
+
leadgenId: row.leadgenId,
|
|
56
|
+
receivedAt: row.receivedAt,
|
|
57
|
+
origin: await formLeadOrigin(ctx, row),
|
|
58
|
+
answers: labelChoices(form?.questions ?? [], row.answers),
|
|
59
|
+
decision: row.decision,
|
|
60
|
+
rulePath: row.rulePath,
|
|
61
|
+
ruleIndex: row.ruleIndex ?? null,
|
|
62
|
+
returned: row.returned ?? null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Deletes a removed lead's ingestion record and leaves its leadgen id behind
|
|
67
|
+
* (nothing else), so the same Meta lead is never ingested again.
|
|
68
|
+
*/
|
|
69
|
+
export async function forgetFormLead(ctx, leadId) {
|
|
70
|
+
const rows = await ctx.db
|
|
71
|
+
.query("formLeads")
|
|
72
|
+
.withIndex("by_leadId", (range) => range.eq("leadId", leadId))
|
|
73
|
+
.take(10);
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
for (const row of rows) {
|
|
76
|
+
await ctx.db.delete("formLeads", row._id);
|
|
77
|
+
if (!(await isForgottenFormLead(ctx, row.leadgenId))) {
|
|
78
|
+
await ctx.db.insert("formLeadTombstones", {
|
|
79
|
+
leadgenId: row.leadgenId,
|
|
80
|
+
removedAt: now,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Whether the host removed the lead Meta knows by this leadgen id. */
|
|
86
|
+
export async function isForgottenFormLead(ctx, leadgenId) {
|
|
87
|
+
return ((await ctx.db
|
|
88
|
+
.query("formLeadTombstones")
|
|
89
|
+
.withIndex("by_leadgenId", (range) => range.eq("leadgenId", leadgenId))
|
|
90
|
+
.first()) !== null);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=leadFormStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leadFormStore.js","sourceRoot":"","sources":["../../src/component/leadFormStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export declare class LeadgenTokenError extends Error {
|
|
2
|
+
readonly reason: string;
|
|
3
|
+
readonly transient: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* `transient`: the token could not be checked because the issuer's keys
|
|
6
|
+
* could not be read right now (unreachable, 5xx, 429, not JSON). The route
|
|
7
|
+
* answers 503 then, which the control plane retries; any other refusal is a
|
|
8
|
+
* 401, which it does not.
|
|
9
|
+
*/
|
|
10
|
+
constructor(reason: string, transient?: boolean);
|
|
11
|
+
}
|
|
12
|
+
type Fetch = typeof fetch;
|
|
13
|
+
/**
|
|
14
|
+
* The production dashboard's federation issuer: what the leadgen route trusts
|
|
15
|
+
* when the host passes no `RASTRO_FEDERATION_ISSUER`, as a host's federation
|
|
16
|
+
* API does. The audience has no default: it is the host's own functions URL.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DEFAULT_FEDERATION_ISSUER = "https://site.api.amagerastro.com/federation";
|
|
19
|
+
/**
|
|
20
|
+
* The issuer and audience the leadgen route checks forwards against, from the
|
|
21
|
+
* component's env. `audience` null means the route refuses every forward
|
|
22
|
+
* (`FEDERATION_NOT_CONFIGURED`), so a Page must not be linked or routed here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function leadgenTrust(env: {
|
|
25
|
+
RASTRO_FEDERATION_ISSUER?: string;
|
|
26
|
+
RASTRO_FEDERATION_AUDIENCE?: string;
|
|
27
|
+
}): {
|
|
28
|
+
issuer: string;
|
|
29
|
+
audience: string | null;
|
|
30
|
+
};
|
|
31
|
+
/** For tests: forget the cached keys. */
|
|
32
|
+
export declare function clearLeadgenKeyCache(): void;
|
|
33
|
+
export interface LeadgenTokenClaims {
|
|
34
|
+
connectionId: string;
|
|
35
|
+
organizationId: string;
|
|
36
|
+
version: number;
|
|
37
|
+
pageId: string;
|
|
38
|
+
leadgenId: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Checks a forwarding token: RS256 under one of the issuer's keys, the
|
|
42
|
+
* issuer and audience the host trusts, alive and short-lived, for the
|
|
43
|
+
* leadgen purpose, and bound to exactly this Page and leadgen id. Throws a
|
|
44
|
+
* `LeadgenTokenError` (no secret in its reason) when anything is off.
|
|
45
|
+
*/
|
|
46
|
+
export declare function verifyLeadgenToken(token: string, expected: {
|
|
47
|
+
issuer: string;
|
|
48
|
+
audience: string;
|
|
49
|
+
pageId: string;
|
|
50
|
+
leadgenId: string;
|
|
51
|
+
}, options?: {
|
|
52
|
+
now?: number;
|
|
53
|
+
fetch?: Fetch;
|
|
54
|
+
}): Promise<LeadgenTokenClaims>;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=leadgenToken.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leadgenToken.d.ts","sourceRoot":"","sources":["../../src/component/leadgenToken.ts"],"names":[],"mappings":"AAyBA,qBAAa,iBAAkB,SAAQ,KAAK;IAQxC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,SAAS;IARpB;;;;;OAKG;IACH,YACW,MAAM,EAAE,MAAM,EACd,SAAS,UAAQ,EAI3B;CACF;AAGD,KAAK,KAAK,GAAG,OAAO,KAAK,CAAC;AAoC1B;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,gDACS,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAO9C;AAsFD,yCAAyC;AACzC,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,EACD,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAO,GAC5C,OAAO,CAAC,kBAAkB,CAAC,CAoI7B"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The control plane's word that Meta announced a lead: a short-lived RS256
|
|
3
|
+
* JWT signed with the federation issuer's key (the one the host already
|
|
4
|
+
* trusts for its dashboard connections), audience = the host's federation
|
|
5
|
+
* audience, bound to one Page and one leadgen id. A component has no
|
|
6
|
+
* `ctx.auth`, so the HTTP route checks it here against the issuer's published
|
|
7
|
+
* keys (`<issuer>/.well-known/openid-configuration` → `jwks_uri`). The token
|
|
8
|
+
* only says "go read this lead from Meta": the lead itself is always read
|
|
9
|
+
* from Meta with the Page's own token, so a replay at most repeats an
|
|
10
|
+
* idempotent read.
|
|
11
|
+
*/
|
|
12
|
+
import { META_LEADGEN_TOKEN } from "./constants.js";
|
|
13
|
+
// The claim names, purpose, subject and lifetime come from
|
|
14
|
+
// `META_LEADGEN_TOKEN` (constants.ts, contract §12.3): the control plane signs
|
|
15
|
+
// with the same object.
|
|
16
|
+
const CLAIMS = META_LEADGEN_TOKEN.claims;
|
|
17
|
+
const CLOCK_SKEW_SECONDS = 60;
|
|
18
|
+
const JWKS_TTL_MS = 5 * 60_000;
|
|
19
|
+
const JWKS_REFRESH_MIN_MS = 60_000;
|
|
20
|
+
const MAX_TOKEN = 8_192;
|
|
21
|
+
const GRAPH_ID = /^\d{1,32}$/u;
|
|
22
|
+
export class LeadgenTokenError extends Error {
|
|
23
|
+
reason;
|
|
24
|
+
transient;
|
|
25
|
+
/**
|
|
26
|
+
* `transient`: the token could not be checked because the issuer's keys
|
|
27
|
+
* could not be read right now (unreachable, 5xx, 429, not JSON). The route
|
|
28
|
+
* answers 503 then, which the control plane retries; any other refusal is a
|
|
29
|
+
* 401, which it does not.
|
|
30
|
+
*/
|
|
31
|
+
constructor(reason, transient = false) {
|
|
32
|
+
super(reason);
|
|
33
|
+
this.reason = reason;
|
|
34
|
+
this.transient = transient;
|
|
35
|
+
this.name = "LeadgenTokenError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const jwksCache = new Map();
|
|
39
|
+
function base64UrlBytes(value) {
|
|
40
|
+
if (!/^[A-Za-z0-9_-]*$/u.test(value)) {
|
|
41
|
+
throw new LeadgenTokenError("token is not base64url");
|
|
42
|
+
}
|
|
43
|
+
const padded = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
44
|
+
const binary = atob(padded + "=".repeat((4 - (padded.length % 4)) % 4));
|
|
45
|
+
const bytes = new Uint8Array(binary.length);
|
|
46
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
47
|
+
bytes[index] = binary.charCodeAt(index);
|
|
48
|
+
}
|
|
49
|
+
return bytes;
|
|
50
|
+
}
|
|
51
|
+
function jsonPart(value) {
|
|
52
|
+
let parsed;
|
|
53
|
+
try {
|
|
54
|
+
parsed = JSON.parse(new TextDecoder().decode(base64UrlBytes(value)));
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof LeadgenTokenError)
|
|
58
|
+
throw error;
|
|
59
|
+
throw new LeadgenTokenError("token part is not JSON");
|
|
60
|
+
}
|
|
61
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
62
|
+
throw new LeadgenTokenError("token part is not an object");
|
|
63
|
+
}
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
66
|
+
const trimSlash = (value) => value.replace(/\/+$/u, "");
|
|
67
|
+
/**
|
|
68
|
+
* The production dashboard's federation issuer: what the leadgen route trusts
|
|
69
|
+
* when the host passes no `RASTRO_FEDERATION_ISSUER`, as a host's federation
|
|
70
|
+
* API does. The audience has no default: it is the host's own functions URL.
|
|
71
|
+
*/
|
|
72
|
+
export const DEFAULT_FEDERATION_ISSUER = "https://site.api.amagerastro.com/federation";
|
|
73
|
+
/**
|
|
74
|
+
* The issuer and audience the leadgen route checks forwards against, from the
|
|
75
|
+
* component's env. `audience` null means the route refuses every forward
|
|
76
|
+
* (`FEDERATION_NOT_CONFIGURED`), so a Page must not be linked or routed here.
|
|
77
|
+
*/
|
|
78
|
+
export function leadgenTrust(env) {
|
|
79
|
+
return {
|
|
80
|
+
issuer: trimSlash(env.RASTRO_FEDERATION_ISSUER?.trim() ?? "") ||
|
|
81
|
+
DEFAULT_FEDERATION_ISSUER,
|
|
82
|
+
audience: trimSlash(env.RASTRO_FEDERATION_AUDIENCE?.trim() ?? "") || null,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function sameOriginHttps(base, target) {
|
|
86
|
+
try {
|
|
87
|
+
const from = new URL(base);
|
|
88
|
+
const to = new URL(target);
|
|
89
|
+
const local = to.hostname === "localhost" || to.hostname === "127.0.0.1";
|
|
90
|
+
return (from.origin === to.origin &&
|
|
91
|
+
(to.protocol === "https:" || (to.protocol === "http:" && local)));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function fetchJson(fetchImpl, target) {
|
|
98
|
+
let response;
|
|
99
|
+
try {
|
|
100
|
+
response = await fetchImpl(target, {
|
|
101
|
+
headers: { Accept: "application/json" },
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
throw new LeadgenTokenError("the issuer is unreachable", true);
|
|
106
|
+
}
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
throw new LeadgenTokenError(`the issuer answered ${response.status}`, response.status >= 500 || response.status === 429);
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
return await response.json();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
throw new LeadgenTokenError("the issuer answered something else than JSON", true);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The issuer's signing keys, cached for five minutes; `fetched` says whether
|
|
119
|
+
* they were read from the issuer just now (a forced refresh within a minute
|
|
120
|
+
* of the last read answers from the cache).
|
|
121
|
+
*/
|
|
122
|
+
async function issuerKeys(issuer, fetchImpl, now, refresh) {
|
|
123
|
+
const cached = jwksCache.get(issuer);
|
|
124
|
+
if (cached &&
|
|
125
|
+
now - cached.fetchedAt < JWKS_TTL_MS &&
|
|
126
|
+
!(refresh && now - cached.refreshedAt >= JWKS_REFRESH_MIN_MS)) {
|
|
127
|
+
return { keys: cached.keys, fetched: false };
|
|
128
|
+
}
|
|
129
|
+
const discovery = await fetchJson(fetchImpl, `${issuer}/.well-known/openid-configuration`);
|
|
130
|
+
const jwksUri = discovery &&
|
|
131
|
+
typeof discovery === "object" &&
|
|
132
|
+
typeof discovery.jwks_uri === "string"
|
|
133
|
+
? discovery.jwks_uri
|
|
134
|
+
: `${issuer}/jwks.json`;
|
|
135
|
+
if (!sameOriginHttps(issuer, jwksUri)) {
|
|
136
|
+
throw new LeadgenTokenError("the issuer's jwks_uri is not its own");
|
|
137
|
+
}
|
|
138
|
+
const jwks = await fetchJson(fetchImpl, jwksUri);
|
|
139
|
+
const keys = jwks &&
|
|
140
|
+
typeof jwks === "object" &&
|
|
141
|
+
Array.isArray(jwks.keys)
|
|
142
|
+
? jwks.keys.filter((key) => key && typeof key === "object")
|
|
143
|
+
: [];
|
|
144
|
+
jwksCache.set(issuer, { keys, fetchedAt: now, refreshedAt: now });
|
|
145
|
+
return { keys, fetched: true };
|
|
146
|
+
}
|
|
147
|
+
/** For tests: forget the cached keys. */
|
|
148
|
+
export function clearLeadgenKeyCache() {
|
|
149
|
+
jwksCache.clear();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Checks a forwarding token: RS256 under one of the issuer's keys, the
|
|
153
|
+
* issuer and audience the host trusts, alive and short-lived, for the
|
|
154
|
+
* leadgen purpose, and bound to exactly this Page and leadgen id. Throws a
|
|
155
|
+
* `LeadgenTokenError` (no secret in its reason) when anything is off.
|
|
156
|
+
*/
|
|
157
|
+
export async function verifyLeadgenToken(token, expected, options = {}) {
|
|
158
|
+
const now = options.now ?? Date.now();
|
|
159
|
+
const fetchImpl = options.fetch ?? ((...args) => fetch(...args));
|
|
160
|
+
const issuer = trimSlash(expected.issuer.trim());
|
|
161
|
+
const audience = trimSlash(expected.audience.trim());
|
|
162
|
+
if (!issuer || !audience) {
|
|
163
|
+
throw new LeadgenTokenError("the host has no federation issuer");
|
|
164
|
+
}
|
|
165
|
+
if (token.length > MAX_TOKEN)
|
|
166
|
+
throw new LeadgenTokenError("token too long");
|
|
167
|
+
const parts = token.split(".");
|
|
168
|
+
if (parts.length !== 3)
|
|
169
|
+
throw new LeadgenTokenError("token is not a JWT");
|
|
170
|
+
const [headerPart, payloadPart, signaturePart] = parts;
|
|
171
|
+
const header = jsonPart(headerPart);
|
|
172
|
+
if (header.alg !== "RS256") {
|
|
173
|
+
throw new LeadgenTokenError("token is not RS256");
|
|
174
|
+
}
|
|
175
|
+
const claims = jsonPart(payloadPart);
|
|
176
|
+
// The cheap checks first: a token for something else costs no key fetch.
|
|
177
|
+
const seconds = Math.floor(now / 1000);
|
|
178
|
+
const aud = claims.aud;
|
|
179
|
+
const audiences = (Array.isArray(aud) ? aud : [aud]).map((value) => typeof value === "string" ? trimSlash(value) : "");
|
|
180
|
+
const exp = claims.exp;
|
|
181
|
+
const iat = claims.iat;
|
|
182
|
+
if (typeof claims.iss !== "string" || trimSlash(claims.iss) !== issuer) {
|
|
183
|
+
throw new LeadgenTokenError("token issuer is not trusted");
|
|
184
|
+
}
|
|
185
|
+
if (!audiences.includes(audience)) {
|
|
186
|
+
throw new LeadgenTokenError("token audience is not this host");
|
|
187
|
+
}
|
|
188
|
+
if (typeof exp !== "number" || exp + CLOCK_SKEW_SECONDS < seconds) {
|
|
189
|
+
throw new LeadgenTokenError("token expired");
|
|
190
|
+
}
|
|
191
|
+
if (typeof iat !== "number" ||
|
|
192
|
+
iat - CLOCK_SKEW_SECONDS > seconds ||
|
|
193
|
+
exp - iat > META_LEADGEN_TOKEN.maxLifetimeSeconds) {
|
|
194
|
+
throw new LeadgenTokenError("token lifetime is not a forwarding one");
|
|
195
|
+
}
|
|
196
|
+
if (claims[CLAIMS.purpose] !== META_LEADGEN_TOKEN.purpose ||
|
|
197
|
+
claims.sub !== META_LEADGEN_TOKEN.subject) {
|
|
198
|
+
throw new LeadgenTokenError("token is not for a leadgen");
|
|
199
|
+
}
|
|
200
|
+
const organizationId = claims[CLAIMS.organizationId];
|
|
201
|
+
const version = claims[CLAIMS.version];
|
|
202
|
+
if (typeof organizationId !== "string" ||
|
|
203
|
+
organizationId.length === 0 ||
|
|
204
|
+
organizationId.length > 128 ||
|
|
205
|
+
typeof version !== "number" ||
|
|
206
|
+
!Number.isSafeInteger(version) ||
|
|
207
|
+
version < 0) {
|
|
208
|
+
throw new LeadgenTokenError("token names no organization");
|
|
209
|
+
}
|
|
210
|
+
const connectionId = claims[CLAIMS.connectionId];
|
|
211
|
+
if (typeof connectionId !== "string" ||
|
|
212
|
+
connectionId.length === 0 ||
|
|
213
|
+
connectionId.length > 128) {
|
|
214
|
+
throw new LeadgenTokenError("token names no connection");
|
|
215
|
+
}
|
|
216
|
+
if (claims[CLAIMS.pageId] !== expected.pageId ||
|
|
217
|
+
claims[CLAIMS.leadgenId] !== expected.leadgenId ||
|
|
218
|
+
!GRAPH_ID.test(expected.pageId) ||
|
|
219
|
+
!GRAPH_ID.test(expected.leadgenId)) {
|
|
220
|
+
throw new LeadgenTokenError("token is for another lead");
|
|
221
|
+
}
|
|
222
|
+
const kid = typeof header.kid === "string" ? header.kid : null;
|
|
223
|
+
const pick = (keys) => keys.filter((key) => key.kty === "RSA" &&
|
|
224
|
+
typeof key.n === "string" &&
|
|
225
|
+
typeof key.e === "string" &&
|
|
226
|
+
(kid === null || key.kid === undefined || key.kid === kid));
|
|
227
|
+
let candidates = pick((await issuerKeys(issuer, fetchImpl, now, false)).keys);
|
|
228
|
+
if (candidates.length === 0) {
|
|
229
|
+
// A rotated key: read the issuer again (at most once a minute).
|
|
230
|
+
const again = await issuerKeys(issuer, fetchImpl, now, true);
|
|
231
|
+
candidates = pick(again.keys);
|
|
232
|
+
if (candidates.length === 0) {
|
|
233
|
+
// Keys read a moment ago may predate the rotation: transient (503,
|
|
234
|
+
// retried) until the issuer has been read again.
|
|
235
|
+
throw new LeadgenTokenError(again.fetched
|
|
236
|
+
? "no issuer key matches the token"
|
|
237
|
+
: "no issuer key matches the token yet", !again.fetched);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const data = new TextEncoder().encode(`${headerPart}.${payloadPart}`);
|
|
241
|
+
const signature = base64UrlBytes(signaturePart);
|
|
242
|
+
for (const jwk of candidates) {
|
|
243
|
+
let key;
|
|
244
|
+
try {
|
|
245
|
+
key = await crypto.subtle.importKey("jwk", { kty: "RSA", n: jwk.n, e: jwk.e, ext: true }, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["verify"]);
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key, signature, data)) {
|
|
251
|
+
return {
|
|
252
|
+
connectionId,
|
|
253
|
+
organizationId,
|
|
254
|
+
version,
|
|
255
|
+
pageId: expected.pageId,
|
|
256
|
+
leadgenId: expected.leadgenId,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
throw new LeadgenTokenError("token signature is invalid");
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=leadgenToken.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leadgenToken.js","sourceRoot":"","sources":["../../src/component/leadgenToken.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Infer } from "convex/values";
|
|
2
|
+
import type { Doc, Id } from "./_generated/dataModel.js";
|
|
3
|
+
import { type MutationCtx } from "./_generated/server.js";
|
|
4
|
+
import { leadAdValidator } from "./validators.js";
|
|
2
5
|
/** Every lead from any ad falls in this origin bucket, whatever its entry point. */
|
|
3
6
|
export declare const AD_ORIGIN = "ctwa_ad";
|
|
4
7
|
/** The bucket for a lead the channel gave no entry point for. */
|
|
5
8
|
export declare const NO_ORIGIN = "none";
|
|
9
|
+
/**
|
|
10
|
+
* A Meta instant form's leads (since 0.11.0): `lead_form` when an ad brought
|
|
11
|
+
* them, so they count as paid next to `ctwa_ad`; `lead_form_organic` when the
|
|
12
|
+
* form was filled without an ad.
|
|
13
|
+
*/
|
|
14
|
+
export declare const LEAD_FORM_ORIGIN = "lead_form";
|
|
15
|
+
export declare const LEAD_FORM_ORGANIC_ORIGIN = "lead_form_organic";
|
|
16
|
+
type LeadAd = Infer<typeof leadAdValidator>;
|
|
6
17
|
type Counters = {
|
|
7
18
|
leads: number;
|
|
8
19
|
qualified: number;
|
|
@@ -22,7 +33,7 @@ export declare const record: import("convex/server").RegisteredMutation<"public"
|
|
|
22
33
|
sourceUrl?: string | undefined;
|
|
23
34
|
title?: string | undefined;
|
|
24
35
|
} | undefined;
|
|
25
|
-
channel: "whatsapp";
|
|
36
|
+
channel: "form" | "whatsapp";
|
|
26
37
|
column?: string | undefined;
|
|
27
38
|
entryPoint?: string | undefined;
|
|
28
39
|
label?: string | undefined;
|
|
@@ -32,9 +43,32 @@ export declare const record: import("convex/server").RegisteredMutation<"public"
|
|
|
32
43
|
siteId: import("convex/values").GenericId<"sites">;
|
|
33
44
|
visitorId?: string | undefined;
|
|
34
45
|
}, Promise<{
|
|
35
|
-
leadId:
|
|
46
|
+
leadId: Id<"leads">;
|
|
36
47
|
created: boolean;
|
|
37
48
|
}>>;
|
|
49
|
+
/**
|
|
50
|
+
* `record`'s body, shared with the Lead Ads ingestion (metaLeads.ts), which
|
|
51
|
+
* also files the lead under its instant form (`form`).
|
|
52
|
+
*/
|
|
53
|
+
export declare function recordLeadCore(ctx: MutationCtx, args: {
|
|
54
|
+
siteId: Id<"sites">;
|
|
55
|
+
leadKey: string;
|
|
56
|
+
channel: Doc<"leads">["channel"];
|
|
57
|
+
entryPoint?: string | undefined;
|
|
58
|
+
ad?: LeadAd | undefined;
|
|
59
|
+
label?: string | undefined;
|
|
60
|
+
visitorId?: string | undefined;
|
|
61
|
+
column?: string | undefined;
|
|
62
|
+
occurredAt: number;
|
|
63
|
+
meta?: unknown;
|
|
64
|
+
form?: {
|
|
65
|
+
formId: string;
|
|
66
|
+
pageId: string;
|
|
67
|
+
} | undefined;
|
|
68
|
+
}): Promise<{
|
|
69
|
+
leadId: Id<"leads">;
|
|
70
|
+
created: boolean;
|
|
71
|
+
}>;
|
|
38
72
|
/**
|
|
39
73
|
* Moves a lead through the host's pipeline, idempotent by `eventId`. A lead the
|
|
40
74
|
* host never recorded (a conversation older than the integration) is not
|
|
@@ -171,8 +205,9 @@ export declare const report: import("convex/server").RegisteredQuery<"public", {
|
|
|
171
205
|
/**
|
|
172
206
|
* The lead funnel per cohort day, for sparklines and the sales × spend chart:
|
|
173
207
|
* every UTC day in the range, empty days included. With `adId`, only that
|
|
174
|
-
* ad's leads; with `origin`, only that origin's (`ctwa_ad` for the
|
|
175
|
-
* ads
|
|
208
|
+
* ad's leads; with `origin`, only that origin's (`ctwa_ad` for the
|
|
209
|
+
* click-to-WhatsApp ads, `paid` for every lead an ad bought: `ctwa_ad` and
|
|
210
|
+
* `lead_form`). Spend is the day's Meta spend for the same scope, null where
|
|
176
211
|
* no synced ad account covers it, for an organic origin, or when the sites'
|
|
177
212
|
* accounts bill in more than one currency.
|
|
178
213
|
*/
|
|
@@ -203,7 +238,7 @@ export declare const list: import("convex/server").RegisteredQuery<"public", {
|
|
|
203
238
|
to: number;
|
|
204
239
|
}, Promise<{
|
|
205
240
|
adId: string | null;
|
|
206
|
-
channel: "whatsapp";
|
|
241
|
+
channel: "form" | "whatsapp";
|
|
207
242
|
entryPoint: string | null;
|
|
208
243
|
firstAt: number;
|
|
209
244
|
hasVisitor: boolean;
|
|
@@ -223,7 +258,7 @@ export declare const journey: import("convex/server").RegisteredQuery<"public",
|
|
|
223
258
|
}, Promise<{
|
|
224
259
|
lead: {
|
|
225
260
|
adId: string | null;
|
|
226
|
-
channel: "whatsapp";
|
|
261
|
+
channel: "form" | "whatsapp";
|
|
227
262
|
entryPoint: string | null;
|
|
228
263
|
firstAt: number;
|
|
229
264
|
hasVisitor: boolean;
|
|
@@ -246,6 +281,40 @@ export declare const journey: import("convex/server").RegisteredQuery<"public",
|
|
|
246
281
|
title: string | null;
|
|
247
282
|
} | null;
|
|
248
283
|
visitorId: string | null;
|
|
284
|
+
form?: {
|
|
285
|
+
answers: {
|
|
286
|
+
label: string;
|
|
287
|
+
questionKey: string;
|
|
288
|
+
values: string[];
|
|
289
|
+
}[];
|
|
290
|
+
decision: {
|
|
291
|
+
column: string | null;
|
|
292
|
+
} | {
|
|
293
|
+
discard: string;
|
|
294
|
+
};
|
|
295
|
+
leadgenId: string;
|
|
296
|
+
origin: {
|
|
297
|
+
adId: string | null;
|
|
298
|
+
adName: string | null;
|
|
299
|
+
adsetId: string | null;
|
|
300
|
+
adsetName: string | null;
|
|
301
|
+
campaignId: string | null;
|
|
302
|
+
campaignName: string | null;
|
|
303
|
+
formId: string;
|
|
304
|
+
formName: string | null;
|
|
305
|
+
isOrganic: boolean;
|
|
306
|
+
pageId: string;
|
|
307
|
+
pageName: string | null;
|
|
308
|
+
platform: string | null;
|
|
309
|
+
};
|
|
310
|
+
receivedAt: number;
|
|
311
|
+
returned: {
|
|
312
|
+
at: number;
|
|
313
|
+
reason: string;
|
|
314
|
+
} | null;
|
|
315
|
+
ruleIndex: number | null;
|
|
316
|
+
rulePath: number[];
|
|
317
|
+
} | null | undefined;
|
|
249
318
|
events: {
|
|
250
319
|
type: "created" | "lost" | "open" | "qualified" | "won";
|
|
251
320
|
at: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"leads.d.ts","sourceRoot":"","sources":["../../src/component/leads.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"leads.d.ts","sourceRoot":"","sources":["../../src/component/leads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAGL,KAAK,WAAW,EAEjB,MAAM,wBAAwB,CAAC;AA8BhC,OAAO,EAEL,eAAe,EAShB,MAAM,iBAAiB,CAAC;AAuBzB,oFAAoF;AACpF,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,iEAAiE;AACjE,eAAO,MAAM,SAAS,SAAS,CAAC;AAChC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,wBAAwB,sBAAsB,CAAC;AAS5D,KAAK,MAAM,GAAG,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAC5C,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAwIF;;;;GAIG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;YA2CE,EAAE,CAAC,OAAO,CAAC;aAAW,OAAO;GArBhD,CAAC;AAEH;;;GAGG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE;IACJ,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACvD,GACA,OAAO,CAAC;IAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA+EpD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;GAuInB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;GA2BjB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;GAgE1B,CAAC;AAgNH;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;eAttBV,MAAM;mBACF,MAAM;aACZ,MAAM;sBACG,MAAM;;;;;;eAHb,MAAM;mBACF,MAAM;aACZ,MAAM;sBACG,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAHb,MAAM;mBACF,MAAM;aACZ,MAAM;sBACG,MAAM;;;;;;;;;;GAigCpB,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,KAAK;;;;;;;WA/gCT,MAAM;eACF,MAAM;SACZ,MAAM;kBACG,MAAM;;;KAioCpB,CAAC;AAsBH;;;GAGG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;KAsDf,CAAC;AAEH,+CAA+C;AAC/C,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA2ClB,CAAC"}
|