@agentsean/google 1.0.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 (112) hide show
  1. package/LICENSE +661 -0
  2. package/dist/audit-extras.d.ts +21 -0
  3. package/dist/audit-extras.d.ts.map +1 -0
  4. package/dist/audit-extras.js +62 -0
  5. package/dist/audit-extras.js.map +1 -0
  6. package/dist/broker.d.ts +47 -0
  7. package/dist/broker.d.ts.map +1 -0
  8. package/dist/broker.js +146 -0
  9. package/dist/broker.js.map +1 -0
  10. package/dist/causes.d.ts +157 -0
  11. package/dist/causes.d.ts.map +1 -0
  12. package/dist/causes.js +175 -0
  13. package/dist/causes.js.map +1 -0
  14. package/dist/connect-flow.d.ts +63 -0
  15. package/dist/connect-flow.d.ts.map +1 -0
  16. package/dist/connect-flow.js +150 -0
  17. package/dist/connect-flow.js.map +1 -0
  18. package/dist/crux.d.ts +37 -0
  19. package/dist/crux.d.ts.map +1 -0
  20. package/dist/crux.js +112 -0
  21. package/dist/crux.js.map +1 -0
  22. package/dist/data/changepoints.json +174 -0
  23. package/dist/data/quotas.json +17 -0
  24. package/dist/errors.d.ts +46 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +110 -0
  27. package/dist/errors.js.map +1 -0
  28. package/dist/ga4.d.ts +46 -0
  29. package/dist/ga4.d.ts.map +1 -0
  30. package/dist/ga4.js +126 -0
  31. package/dist/ga4.js.map +1 -0
  32. package/dist/gsc.d.ts +98 -0
  33. package/dist/gsc.d.ts.map +1 -0
  34. package/dist/gsc.js +141 -0
  35. package/dist/gsc.js.map +1 -0
  36. package/dist/http.d.ts +14 -0
  37. package/dist/http.d.ts.map +1 -0
  38. package/dist/http.js +47 -0
  39. package/dist/http.js.map +1 -0
  40. package/dist/incidents.d.ts +51 -0
  41. package/dist/incidents.d.ts.map +1 -0
  42. package/dist/incidents.js +221 -0
  43. package/dist/incidents.js.map +1 -0
  44. package/dist/index.d.ts +27 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +27 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/integrity.d.ts +32 -0
  49. package/dist/integrity.d.ts.map +1 -0
  50. package/dist/integrity.js +52 -0
  51. package/dist/integrity.js.map +1 -0
  52. package/dist/oauth-broker.d.ts +38 -0
  53. package/dist/oauth-broker.d.ts.map +1 -0
  54. package/dist/oauth-broker.js +81 -0
  55. package/dist/oauth-broker.js.map +1 -0
  56. package/dist/oauth-config.d.ts +16 -0
  57. package/dist/oauth-config.d.ts.map +1 -0
  58. package/dist/oauth-config.js +24 -0
  59. package/dist/oauth-config.js.map +1 -0
  60. package/dist/oauth-desktop.d.ts +29 -0
  61. package/dist/oauth-desktop.d.ts.map +1 -0
  62. package/dist/oauth-desktop.js +76 -0
  63. package/dist/oauth-desktop.js.map +1 -0
  64. package/dist/pending.d.ts +18 -0
  65. package/dist/pending.d.ts.map +1 -0
  66. package/dist/pending.js +29 -0
  67. package/dist/pending.js.map +1 -0
  68. package/dist/persist.d.ts +48 -0
  69. package/dist/persist.d.ts.map +1 -0
  70. package/dist/persist.js +298 -0
  71. package/dist/persist.js.map +1 -0
  72. package/dist/pkce.d.ts +9 -0
  73. package/dist/pkce.d.ts.map +1 -0
  74. package/dist/pkce.js +13 -0
  75. package/dist/pkce.js.map +1 -0
  76. package/dist/psi.d.ts +19 -0
  77. package/dist/psi.d.ts.map +1 -0
  78. package/dist/psi.js +47 -0
  79. package/dist/psi.js.map +1 -0
  80. package/dist/quota.d.ts +22 -0
  81. package/dist/quota.d.ts.map +1 -0
  82. package/dist/quota.js +136 -0
  83. package/dist/quota.js.map +1 -0
  84. package/dist/reconcile.d.ts +19 -0
  85. package/dist/reconcile.d.ts.map +1 -0
  86. package/dist/reconcile.js +89 -0
  87. package/dist/reconcile.js.map +1 -0
  88. package/dist/scopes.d.ts +25 -0
  89. package/dist/scopes.d.ts.map +1 -0
  90. package/dist/scopes.js +49 -0
  91. package/dist/scopes.js.map +1 -0
  92. package/dist/seal.d.ts +4 -0
  93. package/dist/seal.d.ts.map +1 -0
  94. package/dist/seal.js +27 -0
  95. package/dist/seal.js.map +1 -0
  96. package/dist/sync.d.ts +29 -0
  97. package/dist/sync.d.ts.map +1 -0
  98. package/dist/sync.js +266 -0
  99. package/dist/sync.js.map +1 -0
  100. package/dist/tokens.d.ts +57 -0
  101. package/dist/tokens.d.ts.map +1 -0
  102. package/dist/tokens.js +122 -0
  103. package/dist/tokens.js.map +1 -0
  104. package/dist/verification.d.ts +17 -0
  105. package/dist/verification.d.ts.map +1 -0
  106. package/dist/verification.js +51 -0
  107. package/dist/verification.js.map +1 -0
  108. package/dist/waterfall.d.ts +39 -0
  109. package/dist/waterfall.d.ts.map +1 -0
  110. package/dist/waterfall.js +167 -0
  111. package/dist/waterfall.js.map +1 -0
  112. package/package.json +52 -0
package/dist/sync.js ADDED
@@ -0,0 +1,266 @@
1
+ import { eq } from "drizzle-orm";
2
+ import { ga4Connections, gscConnections, sites } from "@agentsean/db";
3
+ import { createQuotaManager } from "./quota.js";
4
+ import { defaultSleep } from "./http.js";
5
+ import { createGscClient, defaultGscWindow, monthChunks, } from "./gsc.js";
6
+ import { createGa4Client, googleOrganicFilter } from "./ga4.js";
7
+ import { queryCruxWithFallback } from "./crux.js";
8
+ import { runPsi } from "./psi.js";
9
+ import { fetchIncidents, seedCuratedChangepoints, upsertIncidents, } from "./incidents.js";
10
+ import { reconcileSite } from "./reconcile.js";
11
+ import { persistCrux, persistGa4Daily, persistGa4Landing, persistGscDaily, persistGscDimensionRows, persistInspection, persistPsi, } from "./persist.js";
12
+ import { loadApiKey, loadByoClient, loadGrant, validAccessToken } from "./tokens.js";
13
+ import { brokerRefreshAccessToken } from "./oauth-broker.js";
14
+ import { resolveOAuthConfig } from "./oauth-config.js";
15
+ import { randomWrapKey } from "./pkce.js";
16
+ import { QuotaExceededError } from "./errors.js";
17
+ function httpOf(deps, db) {
18
+ return {
19
+ fetch: deps.fetch ?? fetch,
20
+ quota: createQuotaManager(db),
21
+ maxRetries: 4,
22
+ sleep: deps.sleep ?? defaultSleep,
23
+ maxBackoffMs: deps.maxBackoffMs ?? 15 * 60_000,
24
+ };
25
+ }
26
+ async function tokenFn(deps) {
27
+ const grant = await loadGrant(deps.store);
28
+ if (!grant)
29
+ throw new Error("Google is not connected.");
30
+ const cfg = resolveOAuthConfig();
31
+ const byo = (await loadByoClient(deps.store)) ?? cfg.byo;
32
+ const fetchFn = deps.fetch ?? fetch;
33
+ return validAccessToken(deps.store, {
34
+ fetch: fetchFn,
35
+ clientId: byo?.clientId,
36
+ clientSecret: byo?.clientSecret,
37
+ brokerRefresh: grant.mode === "broker"
38
+ ? async (rt) => {
39
+ const wrap = randomWrapKey();
40
+ return brokerRefreshAccessToken(cfg.brokerUrl, rt, wrap, fetchFn);
41
+ }
42
+ : undefined,
43
+ });
44
+ }
45
+ export async function syncGoogle(deps) {
46
+ const errors = [];
47
+ seedCuratedChangepoints(deps.db);
48
+ let incidents = 0;
49
+ try {
50
+ const fetched = await fetchIncidents(deps.fetch ?? fetch);
51
+ incidents = upsertIncidents(deps.db, fetched);
52
+ }
53
+ catch (err) {
54
+ errors.push(`incidents: ${err instanceof Error ? err.message : String(err)}`);
55
+ }
56
+ const grant = await loadGrant(deps.store);
57
+ const testingModeSuspected = grant?.testingModeSuspected ?? false;
58
+ const http = httpOf(deps, deps.db);
59
+ const getToken = () => tokenFn(deps);
60
+ const gsc = createGscClient({ http, getToken });
61
+ const ga4 = createGa4Client({ http, getToken });
62
+ const gscConn = deps.db
63
+ .select()
64
+ .from(gscConnections)
65
+ .where(eq(gscConnections.siteId, deps.siteId))
66
+ .get();
67
+ const ga4Conn = deps.db
68
+ .select()
69
+ .from(ga4Connections)
70
+ .where(eq(ga4Connections.siteId, deps.siteId))
71
+ .get();
72
+ const site = deps.db.select().from(sites).where(eq(sites.id, deps.siteId)).get();
73
+ let gscDays = 0;
74
+ let gscPages = 0;
75
+ let gscQueries = 0;
76
+ if (gscConn) {
77
+ try {
78
+ const pulled = await syncGsc(gsc, deps.db, deps.siteId, gscConn.siteUrl);
79
+ gscDays = pulled.days;
80
+ gscPages = pulled.pages;
81
+ gscQueries = pulled.queries;
82
+ }
83
+ catch (err) {
84
+ errors.push(`gsc: ${err instanceof Error ? err.message : String(err)}`);
85
+ }
86
+ if (deps.inspectUrls?.length) {
87
+ for (const url of deps.inspectUrls) {
88
+ try {
89
+ const remaining = http.quota.remainingInspectionToday(gscConn.siteUrl);
90
+ if (remaining <= 0)
91
+ break;
92
+ const result = await gsc.inspectUrl(gscConn.siteUrl, url);
93
+ if (result)
94
+ persistInspection(deps.db, deps.siteId, url, result);
95
+ }
96
+ catch (err) {
97
+ if (err instanceof QuotaExceededError)
98
+ break;
99
+ errors.push(`inspect ${url}: ${err instanceof Error ? err.message : String(err)}`);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ let ga4Days = 0;
105
+ if (ga4Conn) {
106
+ try {
107
+ ga4Days = await syncGa4(ga4, deps.db, deps.siteId, ga4Conn.propertyId);
108
+ }
109
+ catch (err) {
110
+ errors.push(`ga4: ${err instanceof Error ? err.message : String(err)}`);
111
+ }
112
+ }
113
+ const apiKey = await loadApiKey(deps.store);
114
+ let cruxOk = false;
115
+ let psiOk = false;
116
+ if (apiKey && site) {
117
+ try {
118
+ const rec = await queryCruxWithFallback({
119
+ http,
120
+ apiKey,
121
+ url: site.origin,
122
+ origin: site.origin,
123
+ formFactor: "PHONE",
124
+ });
125
+ persistCrux(deps.db, deps.siteId, rec);
126
+ cruxOk = !rec.insufficientTraffic || rec.lcpP75 !== null;
127
+ }
128
+ catch (err) {
129
+ errors.push(`crux: ${err instanceof Error ? err.message : String(err)}`);
130
+ }
131
+ if (deps.runPsiAudit) {
132
+ try {
133
+ const psi = await runPsi({ http, url: site.origin, apiKey });
134
+ persistPsi(deps.db, deps.siteId, psi);
135
+ psiOk = true;
136
+ }
137
+ catch (err) {
138
+ errors.push(`psi: ${err instanceof Error ? err.message : String(err)}`);
139
+ }
140
+ }
141
+ }
142
+ const residualRows = reconcileSite(deps.db, deps.siteId);
143
+ const inspectionRemaining = gscConn
144
+ ? http.quota.remainingInspectionToday(gscConn.siteUrl)
145
+ : 0;
146
+ return {
147
+ gscDays,
148
+ gscPages,
149
+ gscQueries,
150
+ ga4Days,
151
+ crux: cruxOk,
152
+ psi: psiOk,
153
+ incidents,
154
+ residualRows,
155
+ inspectionRemaining,
156
+ testingModeSuspected,
157
+ errors,
158
+ };
159
+ }
160
+ async function syncGsc(gsc, db, siteId, siteUrl) {
161
+ const window = defaultGscWindow();
162
+ const chunks = monthChunks(window.startDate, window.endDate);
163
+ let days = 0;
164
+ let pages = 0;
165
+ let queries = 0;
166
+ let firstIncomplete = null;
167
+ for (const chunk of chunks) {
168
+ const totals = await gsc.querySearchAnalyticsAllPages(siteUrl, {
169
+ startDate: chunk.startDate,
170
+ endDate: chunk.endDate,
171
+ dimensions: ["date"],
172
+ type: "web",
173
+ dataState: "final",
174
+ rowLimit: 25_000,
175
+ });
176
+ if (totals.firstIncompleteDate)
177
+ firstIncomplete = totals.firstIncompleteDate;
178
+ for (const row of totals.rows) {
179
+ const date = row.keys?.[0];
180
+ if (!date)
181
+ continue;
182
+ persistGscDaily(db, siteId, "web", date, {
183
+ clicks: row.clicks,
184
+ impressions: row.impressions,
185
+ ctr: row.ctr,
186
+ position: row.position,
187
+ }, "final", firstIncomplete);
188
+ days += 1;
189
+ }
190
+ const pageRows = await gsc.querySearchAnalyticsAllPages(siteUrl, {
191
+ startDate: chunk.startDate,
192
+ endDate: chunk.endDate,
193
+ dimensions: ["page", "date"],
194
+ type: "web",
195
+ dataState: "final",
196
+ rowLimit: 25_000,
197
+ });
198
+ pages += persistGscDimensionRows(db, siteId, "web", "page", pageRows.rows);
199
+ const queryRows = await gsc.querySearchAnalyticsAllPages(siteUrl, {
200
+ startDate: chunk.startDate,
201
+ endDate: chunk.endDate,
202
+ dimensions: ["query", "date"],
203
+ type: "web",
204
+ dataState: "final",
205
+ rowLimit: 25_000,
206
+ });
207
+ queries += persistGscDimensionRows(db, siteId, "web", "query", queryRows.rows);
208
+ }
209
+ return { days, pages, queries };
210
+ }
211
+ async function syncGa4(ga4, db, siteId, propertyId) {
212
+ const window = defaultGscWindow();
213
+ const daily = await ga4.runReport({
214
+ propertyId,
215
+ startDate: window.startDate,
216
+ endDate: window.endDate,
217
+ dimensions: ["date"],
218
+ metrics: ["sessions", "engagedSessions", "conversions"],
219
+ });
220
+ const organic = await ga4.runReport({
221
+ propertyId,
222
+ startDate: window.startDate,
223
+ endDate: window.endDate,
224
+ dimensions: ["date"],
225
+ metrics: ["sessions"],
226
+ dimensionFilter: googleOrganicFilter(),
227
+ });
228
+ const organicByDate = new Map();
229
+ for (const row of organic.rows) {
230
+ organicByDate.set(ga4Date(row.dimensionValues[0] ?? ""), row.metricValues[0] ?? 0);
231
+ }
232
+ let n = 0;
233
+ for (const row of daily.rows) {
234
+ const date = ga4Date(row.dimensionValues[0] ?? "");
235
+ if (!date)
236
+ continue;
237
+ persistGa4Daily(db, siteId, date, {
238
+ sessions: row.metricValues[0] ?? 0,
239
+ organicSessions: organicByDate.get(date) ?? 0,
240
+ engagedSessions: row.metricValues[1] ?? 0,
241
+ conversions: row.metricValues[2] ?? 0,
242
+ });
243
+ n += 1;
244
+ }
245
+ const landing = await ga4.runReport({
246
+ propertyId,
247
+ startDate: window.startDate,
248
+ endDate: window.endDate,
249
+ dimensions: ["date", "landingPagePlusQueryString"],
250
+ metrics: ["sessions", "engagedSessions"],
251
+ limit: 10000,
252
+ });
253
+ for (const row of landing.rows) {
254
+ const date = ga4Date(row.dimensionValues[0] ?? "");
255
+ const page = row.dimensionValues[1] ?? "/";
256
+ persistGa4Landing(db, siteId, date, page, row.metricValues[0] ?? 0, row.metricValues[1] ?? 0);
257
+ }
258
+ return n;
259
+ }
260
+ function ga4Date(raw) {
261
+ if (/^\d{8}$/.test(raw)) {
262
+ return `${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`;
263
+ }
264
+ return raw;
265
+ }
266
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type CredentialStore } from "@agentsean/credentials";
2
+ export type OAuthMode = "broker" | "byo";
3
+ export type StoredGoogleGrant = {
4
+ accessToken: string;
5
+ refreshToken: string;
6
+ expiresAt: string;
7
+ scopes: string;
8
+ tokenType: string;
9
+ issuedAt: string;
10
+ refreshTokenExpiresAt: string | null;
11
+ email: string | null;
12
+ googleSub: string | null;
13
+ mode: OAuthMode;
14
+ testingModeSuspected: boolean;
15
+ };
16
+ export type ByoClient = {
17
+ clientId: string;
18
+ clientSecret: string;
19
+ };
20
+ export declare function parseGrant(raw: string): StoredGoogleGrant;
21
+ export declare function loadGrant(store: CredentialStore): Promise<StoredGoogleGrant | null>;
22
+ export declare function saveGrant(store: CredentialStore, grant: StoredGoogleGrant): Promise<void>;
23
+ export declare function loadByoClient(store: CredentialStore): Promise<ByoClient | null>;
24
+ export declare function saveByoClient(store: CredentialStore, client: ByoClient): Promise<void>;
25
+ export declare function loadApiKey(store: CredentialStore): Promise<string | null>;
26
+ export declare function saveApiKey(store: CredentialStore, key: string): Promise<void>;
27
+ export declare function testingModeFromTokenResponse(res: {
28
+ refresh_token_expires_in?: number | undefined;
29
+ }): boolean;
30
+ export declare function grantFromTokenResponse(res: {
31
+ access_token: string;
32
+ refresh_token?: string | undefined;
33
+ expires_in?: number | undefined;
34
+ scope?: string | undefined;
35
+ token_type?: string | undefined;
36
+ refresh_token_expires_in?: number | undefined;
37
+ }, prev: StoredGoogleGrant | null, extras: {
38
+ mode: OAuthMode;
39
+ email: string | null;
40
+ googleSub: string | null;
41
+ now?: Date | undefined;
42
+ }): StoredGoogleGrant;
43
+ export declare function refreshAccessToken(grant: StoredGoogleGrant, opts: {
44
+ fetch: typeof fetch;
45
+ clientId?: string | undefined;
46
+ clientSecret?: string | undefined;
47
+ brokerRefresh?: ((refreshToken: string) => Promise<{
48
+ access_token: string;
49
+ expires_in?: number | undefined;
50
+ refresh_token?: string | undefined;
51
+ refresh_token_expires_in?: number | undefined;
52
+ scope?: string | undefined;
53
+ }>) | undefined;
54
+ }): Promise<StoredGoogleGrant>;
55
+ export declare function accessTokenValid(grant: StoredGoogleGrant, now?: Date): boolean;
56
+ export declare function validAccessToken(store: CredentialStore, refreshOpts: Parameters<typeof refreshAccessToken>[1]): Promise<string>;
57
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
package/dist/tokens.js ADDED
@@ -0,0 +1,122 @@
1
+ import { Secret } from "@agentsean/credentials";
2
+ import { GOOGLE_API_KEY_ACCOUNT, GOOGLE_BYO_CLIENT_ACCOUNT, GOOGLE_OAUTH_ACCOUNT, GOOGLE_TOKEN_URL, } from "./scopes.js";
3
+ import { GscTokenError } from "./errors.js";
4
+ export function parseGrant(raw) {
5
+ const parsed = JSON.parse(raw);
6
+ if (!parsed.accessToken || !parsed.refreshToken) {
7
+ throw new GscTokenError("Stored Google grant is incomplete.");
8
+ }
9
+ return parsed;
10
+ }
11
+ export async function loadGrant(store) {
12
+ const secret = await store.get(GOOGLE_OAUTH_ACCOUNT);
13
+ if (!secret)
14
+ return null;
15
+ return parseGrant(secret.unwrap());
16
+ }
17
+ export async function saveGrant(store, grant) {
18
+ await store.set(GOOGLE_OAUTH_ACCOUNT, new Secret(JSON.stringify(grant)));
19
+ }
20
+ export async function loadByoClient(store) {
21
+ const secret = await store.get(GOOGLE_BYO_CLIENT_ACCOUNT);
22
+ if (!secret)
23
+ return null;
24
+ const parsed = JSON.parse(secret.unwrap());
25
+ if (!parsed.clientId || !parsed.clientSecret)
26
+ return null;
27
+ return parsed;
28
+ }
29
+ export async function saveByoClient(store, client) {
30
+ await store.set(GOOGLE_BYO_CLIENT_ACCOUNT, new Secret(JSON.stringify(client)));
31
+ }
32
+ export async function loadApiKey(store) {
33
+ const secret = await store.get(GOOGLE_API_KEY_ACCOUNT);
34
+ return secret?.unwrap() ?? null;
35
+ }
36
+ export async function saveApiKey(store, key) {
37
+ await store.set(GOOGLE_API_KEY_ACCOUNT, new Secret(key));
38
+ }
39
+ export function testingModeFromTokenResponse(res) {
40
+ const exp = res.refresh_token_expires_in;
41
+ if (typeof exp !== "number")
42
+ return false;
43
+ return exp > 0 && exp <= 7 * 24 * 3600 + 60;
44
+ }
45
+ export function grantFromTokenResponse(res, prev, extras) {
46
+ const now = extras.now ?? new Date();
47
+ const refresh = res.refresh_token ?? prev?.refreshToken;
48
+ if (!refresh) {
49
+ throw new GscTokenError("Google did not return a refresh token. Reconnect with prompt=consent.");
50
+ }
51
+ const expiresIn = res.expires_in ?? 3600;
52
+ const testing = testingModeFromTokenResponse(res) || (prev?.testingModeSuspected ?? false);
53
+ const refreshExp = typeof res.refresh_token_expires_in === "number"
54
+ ? new Date(now.getTime() + res.refresh_token_expires_in * 1000).toISOString()
55
+ : (prev?.refreshTokenExpiresAt ?? null);
56
+ return {
57
+ accessToken: res.access_token,
58
+ refreshToken: refresh,
59
+ expiresAt: new Date(now.getTime() + expiresIn * 1000).toISOString(),
60
+ scopes: res.scope ?? prev?.scopes ?? "",
61
+ tokenType: res.token_type ?? "Bearer",
62
+ issuedAt: prev?.issuedAt ?? now.toISOString(),
63
+ refreshTokenExpiresAt: refreshExp,
64
+ email: extras.email ?? prev?.email ?? null,
65
+ googleSub: extras.googleSub ?? prev?.googleSub ?? null,
66
+ mode: extras.mode,
67
+ testingModeSuspected: testing,
68
+ };
69
+ }
70
+ export async function refreshAccessToken(grant, opts) {
71
+ if (grant.mode === "broker") {
72
+ if (!opts.brokerRefresh) {
73
+ throw new GscTokenError("Broker refresh is not configured.");
74
+ }
75
+ const res = await opts.brokerRefresh(grant.refreshToken);
76
+ return grantFromTokenResponse(res, grant, {
77
+ mode: "broker",
78
+ email: grant.email,
79
+ googleSub: grant.googleSub,
80
+ });
81
+ }
82
+ if (!opts.clientId || !opts.clientSecret) {
83
+ throw new GscTokenError("BYO client_id and client_secret are required to refresh.");
84
+ }
85
+ const body = new URLSearchParams({
86
+ client_id: opts.clientId,
87
+ client_secret: opts.clientSecret,
88
+ refresh_token: grant.refreshToken,
89
+ grant_type: "refresh_token",
90
+ });
91
+ const response = await opts.fetch(GOOGLE_TOKEN_URL, {
92
+ method: "POST",
93
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
94
+ body,
95
+ });
96
+ if (!response.ok) {
97
+ const text = await response.text().catch(() => "");
98
+ throw new GscTokenError(`Google token refresh failed (${response.status}): ${text.slice(0, 200)}`);
99
+ }
100
+ const json = (await response.json());
101
+ if (!json.access_token)
102
+ throw new GscTokenError("Refresh response missing access_token.");
103
+ return grantFromTokenResponse({ ...json, access_token: json.access_token }, grant, {
104
+ mode: "byo",
105
+ email: grant.email,
106
+ googleSub: grant.googleSub,
107
+ });
108
+ }
109
+ export function accessTokenValid(grant, now = new Date()) {
110
+ return Date.parse(grant.expiresAt) - now.getTime() > 60_000;
111
+ }
112
+ export async function validAccessToken(store, refreshOpts) {
113
+ const grant = await loadGrant(store);
114
+ if (!grant)
115
+ throw new GscTokenError("Google is not connected.");
116
+ if (accessTokenValid(grant))
117
+ return grant.accessToken;
118
+ const next = await refreshAccessToken(grant, refreshOpts);
119
+ await saveGrant(store, next);
120
+ return next.accessToken;
121
+ }
122
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type GoogleHttp } from "./http.js";
2
+ export type VerificationMethod = "META" | "FILE" | "ANALYTICS" | "TAG_MANAGER" | "DNS_TXT";
3
+ export type VerificationToken = {
4
+ method: VerificationMethod;
5
+ token: string;
6
+ };
7
+ export type SiteVerificationClient = {
8
+ getToken: (identifier: string, method: VerificationMethod, type?: "SITE" | "INET_DOMAIN") => Promise<VerificationToken>;
9
+ insert: (identifier: string, method: VerificationMethod, type?: "SITE" | "INET_DOMAIN") => Promise<void>;
10
+ };
11
+ export declare function createSiteVerificationClient(opts: {
12
+ http: GoogleHttp;
13
+ getToken: () => Promise<string>;
14
+ }): SiteVerificationClient;
15
+ export declare function metaVerificationTag(token: string): string;
16
+ export declare function fileVerificationPath(token: string): string;
17
+ //# sourceMappingURL=verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../src/verification.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAIjE,MAAM,MAAM,kBAAkB,GAC5B,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,CACR,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,KAC1B,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,MAAM,EAAE,CACN,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,KAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC,GAAG,sBAAsB,CAiDzB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,51 @@
1
+ import { GscApiError, gscMessageForStatus } from "./errors.js";
2
+ import { bearer, googleFetch } from "./http.js";
3
+ const BASE = "https://www.googleapis.com/siteVerification/v1";
4
+ export function createSiteVerificationClient(opts) {
5
+ const request = async (url, init) => {
6
+ const token = await opts.getToken();
7
+ const hasBody = init?.body !== undefined;
8
+ const res = await googleFetch(opts.http, "gsc.other", "siteVerification", url, {
9
+ method: init?.method ?? "GET",
10
+ headers: bearer(token, hasBody ? { "Content-Type": "application/json" } : undefined),
11
+ ...(hasBody ? { body: JSON.stringify(init?.body) } : {}),
12
+ });
13
+ if (!res.ok) {
14
+ const body = await res.text().catch(() => "");
15
+ throw new GscApiError(res.status, gscMessageForStatus(res.status, body), body);
16
+ }
17
+ if (res.status === 204)
18
+ return undefined;
19
+ const text = await res.text();
20
+ if (!text)
21
+ return undefined;
22
+ return JSON.parse(text);
23
+ };
24
+ return {
25
+ async getToken(identifier, method, type = "SITE") {
26
+ const data = await request(`${BASE}/token`, {
27
+ method: "POST",
28
+ body: {
29
+ verificationMethod: method,
30
+ site: { type, identifier },
31
+ },
32
+ });
33
+ return { method, token: data.token ?? "" };
34
+ },
35
+ async insert(identifier, method, type = "SITE") {
36
+ await request(`${BASE}/webResource?verificationMethod=${encodeURIComponent(method)}`, {
37
+ method: "POST",
38
+ body: {
39
+ site: { type, identifier },
40
+ },
41
+ });
42
+ },
43
+ };
44
+ }
45
+ export function metaVerificationTag(token) {
46
+ return `<meta name="google-site-verification" content="${token}" />`;
47
+ }
48
+ export function fileVerificationPath(token) {
49
+ return `/${token}.html`;
50
+ }
51
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../src/verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAmB,MAAM,WAAW,CAAC;AAEjE,MAAM,IAAI,GAAG,gDAAgD,CAAC;AAuB9D,MAAM,UAAU,4BAA4B,CAAC,IAG5C;IACC,MAAM,OAAO,GAAG,KAAK,EACnB,GAAW,EACX,IAA0C,EAC9B,EAAE;QACd,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,kBAAkB,EAAE,GAAG,EAAE;YAC7E,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK;YAC7B,OAAO,EAAE,MAAM,CACb,KAAK,EACL,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,SAAS,CAC7D;YACD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,SAAc,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO,SAAc,CAAC;QACjC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM;YAC9C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAsC,GAAG,IAAI,QAAQ,EAAE;gBAC/E,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACJ,kBAAkB,EAAE,MAAM;oBAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;iBAC3B;aACF,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QAC7C,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAG,MAAM;YAC5C,MAAM,OAAO,CACX,GAAG,IAAI,mCAAmC,kBAAkB,CAAC,MAAM,CAAC,EAAE,EACtE;gBACE,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACJ,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;iBAC3B;aACF,CACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,kDAAkD,KAAK,MAAM,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,IAAI,KAAK,OAAO,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { SqliteDatabase } from "@agentsean/db";
2
+ import { type DiscrepancyCause } from "./causes.js";
3
+ export type WaterfallStep = DiscrepancyCause & {
4
+ applies: boolean;
5
+ estimatedShare: number | null;
6
+ detail: string;
7
+ };
8
+ export type WaterfallResult = {
9
+ windowStart: string;
10
+ windowEnd: string;
11
+ gscClicks: number;
12
+ queryDimensionClicks: number;
13
+ ga4OrganicSessions: number;
14
+ residual: number;
15
+ residualPct: number | null;
16
+ anonymizedQueryShare: number;
17
+ euInvisibleShare: number | null;
18
+ euProperty: boolean;
19
+ steps: WaterfallStep[];
20
+ notes: string;
21
+ };
22
+ export type WaterfallInput = {
23
+ gscClicks: number;
24
+ queryDimensionClicks: number;
25
+ ga4OrganicSessions: number;
26
+ windowStart: string;
27
+ windowEnd: string;
28
+ timeZone?: string | null | undefined;
29
+ sampled?: boolean | undefined;
30
+ thresholded?: boolean | undefined;
31
+ };
32
+ /**
33
+ * Named 17-cause waterfall. It explains the residual; it does not force
34
+ * GA4 and GSC to match. The leftover is the honest number.
35
+ */
36
+ export declare function buildWaterfall(input: WaterfallInput): WaterfallResult;
37
+ export declare function waterfallFromSite(db: SqliteDatabase, siteId: string, windowStart: string, windowEnd: string): WaterfallResult;
38
+ export declare function persistWaterfall(db: SqliteDatabase, siteId: string, result: WaterfallResult, now?: Date): void;
39
+ //# sourceMappingURL=waterfall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waterfall.d.ts","sourceRoot":"","sources":["../src/waterfall.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAQpD,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAGrB,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnC,CAAC;AASF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAoFrE;AAsBD,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,eAAe,CAwCjB;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,eAAe,EACvB,GAAG,OAAa,GACf,IAAI,CAwCN"}