seo-testing-tool 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.
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/dist/auth/GoogleOAuthService.d.ts +31 -0
- package/dist/auth/GoogleOAuthService.d.ts.map +1 -0
- package/dist/auth/GoogleOAuthService.js +69 -0
- package/dist/auth/GoogleOAuthService.js.map +1 -0
- package/dist/auth/TokenManager.d.ts +56 -0
- package/dist/auth/TokenManager.d.ts.map +1 -0
- package/dist/auth/TokenManager.js +190 -0
- package/dist/auth/TokenManager.js.map +1 -0
- package/dist/cli/commands.d.ts +36 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +471 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/formatters.d.ts +24 -0
- package/dist/cli/formatters.d.ts.map +1 -0
- package/dist/cli/formatters.js +175 -0
- package/dist/cli/formatters.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/AnalysisConfig.d.ts +13 -0
- package/dist/config/AnalysisConfig.d.ts.map +1 -0
- package/dist/config/AnalysisConfig.js +10 -0
- package/dist/config/AnalysisConfig.js.map +1 -0
- package/dist/config/env.d.ts +30 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +77 -0
- package/dist/config/env.js.map +1 -0
- package/dist/database/DatabaseService.d.ts +106 -0
- package/dist/database/DatabaseService.d.ts.map +1 -0
- package/dist/database/DatabaseService.js +180 -0
- package/dist/database/DatabaseService.js.map +1 -0
- package/dist/database/TimeSeriesService.d.ts +53 -0
- package/dist/database/TimeSeriesService.d.ts.map +1 -0
- package/dist/database/TimeSeriesService.js +122 -0
- package/dist/database/TimeSeriesService.js.map +1 -0
- package/dist/database/db.d.ts +20 -0
- package/dist/database/db.d.ts.map +1 -0
- package/dist/database/db.js +60 -0
- package/dist/database/db.js.map +1 -0
- package/dist/database/schema.d.ts +687 -0
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/database/schema.js +62 -0
- package/dist/database/schema.js.map +1 -0
- package/dist/demo.d.ts +13 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +149 -0
- package/dist/demo.js.map +1 -0
- package/dist/gsc/GSCDataFetcher.d.ts +100 -0
- package/dist/gsc/GSCDataFetcher.d.ts.map +1 -0
- package/dist/gsc/GSCDataFetcher.js +398 -0
- package/dist/gsc/GSCDataFetcher.js.map +1 -0
- package/dist/gsc/GSCPermissionService.d.ts +20 -0
- package/dist/gsc/GSCPermissionService.d.ts.map +1 -0
- package/dist/gsc/GSCPermissionService.js +84 -0
- package/dist/gsc/GSCPermissionService.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/notifications/NotificationService.d.ts +64 -0
- package/dist/notifications/NotificationService.d.ts.map +1 -0
- package/dist/notifications/NotificationService.js +115 -0
- package/dist/notifications/NotificationService.js.map +1 -0
- package/dist/orchestrator/SEOExperimentOrchestrator.d.ts +69 -0
- package/dist/orchestrator/SEOExperimentOrchestrator.d.ts.map +1 -0
- package/dist/orchestrator/SEOExperimentOrchestrator.js +199 -0
- package/dist/orchestrator/SEOExperimentOrchestrator.js.map +1 -0
- package/dist/services/ExportService.d.ts +52 -0
- package/dist/services/ExportService.d.ts.map +1 -0
- package/dist/services/ExportService.js +238 -0
- package/dist/services/ExportService.js.map +1 -0
- package/dist/smoke-test.d.ts +10 -0
- package/dist/smoke-test.d.ts.map +1 -0
- package/dist/smoke-test.js +73 -0
- package/dist/smoke-test.js.map +1 -0
- package/dist/stats/StatisticalEngine.d.ts +48 -0
- package/dist/stats/StatisticalEngine.d.ts.map +1 -0
- package/dist/stats/StatisticalEngine.js +205 -0
- package/dist/stats/StatisticalEngine.js.map +1 -0
- package/dist/stats/TDistribution.d.ts +28 -0
- package/dist/stats/TDistribution.d.ts.map +1 -0
- package/dist/stats/TDistribution.js +120 -0
- package/dist/stats/TDistribution.js.map +1 -0
- package/drizzle/0000_hot_whiplash.sql +51 -0
- package/drizzle/0001_open_photon.sql +9 -0
- package/drizzle/0002_faulty_the_watchers.sql +1 -0
- package/drizzle/meta/0000_snapshot.json +360 -0
- package/drizzle/meta/0001_snapshot.json +428 -0
- package/drizzle/meta/0002_snapshot.json +420 -0
- package/drizzle/meta/_journal.json +27 -0
- package/package.json +89 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { sqliteTable, text, integer, real, uniqueIndex, index } from 'drizzle-orm/sqlite-core';
|
|
2
|
+
import { sql } from 'drizzle-orm';
|
|
3
|
+
// ── Users ───────────────────────────────────────────────────────────────────
|
|
4
|
+
export const users = sqliteTable('User', {
|
|
5
|
+
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
6
|
+
email: text('email').notNull().unique(),
|
|
7
|
+
createdAt: text('createdAt').notNull().default(sql `(datetime('now'))`),
|
|
8
|
+
});
|
|
9
|
+
// ── Tests ───────────────────────────────────────────────────────────────────
|
|
10
|
+
export const tests = sqliteTable('Test', {
|
|
11
|
+
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
12
|
+
name: text('name').notNull(),
|
|
13
|
+
urls: text('urls').notNull().default('[]'),
|
|
14
|
+
siteUrl: text('siteUrl').notNull(),
|
|
15
|
+
startDate: text('startDate').notNull(),
|
|
16
|
+
splitDate: text('splitDate').notNull(),
|
|
17
|
+
status: text('status').notNull().default('running'),
|
|
18
|
+
lastSyncAt: text('lastSyncAt'),
|
|
19
|
+
lastPValue: real('lastPValue'),
|
|
20
|
+
lastImprovement: real('lastImprovement'),
|
|
21
|
+
userId: text('userId').notNull().references(() => users.id),
|
|
22
|
+
createdAt: text('createdAt').notNull().default(sql `(datetime('now'))`),
|
|
23
|
+
updatedAt: text('updatedAt').notNull().default(sql `(datetime('now'))`),
|
|
24
|
+
}, (table) => [
|
|
25
|
+
index('Test_userId_idx').on(table.userId),
|
|
26
|
+
index('Test_status_idx').on(table.status),
|
|
27
|
+
]);
|
|
28
|
+
// ── Metrics ─────────────────────────────────────────────────────────────────
|
|
29
|
+
export const metrics = sqliteTable('Metric', {
|
|
30
|
+
id: integer('id').primaryKey({ autoIncrement: true }),
|
|
31
|
+
testId: text('testId').notNull().references(() => tests.id, { onDelete: 'cascade' }),
|
|
32
|
+
date: text('date').notNull(),
|
|
33
|
+
clicks: integer('clicks').notNull(),
|
|
34
|
+
impressions: integer('impressions').notNull(),
|
|
35
|
+
gapFilled: integer('gapFilled', { mode: 'boolean' }).notNull().default(false),
|
|
36
|
+
filledAt: text('filledAt'),
|
|
37
|
+
createdAt: text('createdAt').notNull().default(sql `(datetime('now'))`),
|
|
38
|
+
}, (table) => [
|
|
39
|
+
uniqueIndex('Metric_testId_date_key').on(table.testId, table.date),
|
|
40
|
+
index('Metric_testId_date_idx').on(table.testId, table.date),
|
|
41
|
+
]);
|
|
42
|
+
// ── OAuth Tokens ─────────────────────────────────────────────────────────────
|
|
43
|
+
export const oauthTokens = sqliteTable('OAuthToken', {
|
|
44
|
+
userId: text('userId').primaryKey().references(() => users.id),
|
|
45
|
+
accessToken: text('accessToken').notNull(),
|
|
46
|
+
refreshToken: text('refreshToken').notNull(),
|
|
47
|
+
expiresAt: integer('expiresAt').notNull(), // Unix timestamp in ms
|
|
48
|
+
createdAt: text('createdAt').notNull().default(sql `(datetime('now'))`),
|
|
49
|
+
updatedAt: text('updatedAt').notNull().default(sql `(datetime('now'))`),
|
|
50
|
+
});
|
|
51
|
+
// ── Audit Log ───────────────────────────────────────────────────────────────
|
|
52
|
+
export const auditLogs = sqliteTable('AuditLog', {
|
|
53
|
+
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
54
|
+
testId: text('testId').notNull(),
|
|
55
|
+
action: text('action').notNull(),
|
|
56
|
+
userId: text('userId').notNull(),
|
|
57
|
+
timestamp: text('timestamp').notNull().default(sql `(datetime('now'))`),
|
|
58
|
+
}, (table) => [
|
|
59
|
+
index('AuditLog_testId_idx').on(table.testId),
|
|
60
|
+
index('AuditLog_userId_idx').on(table.userId),
|
|
61
|
+
]);
|
|
62
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/database/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/demo.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo — Popola il database con dati finti per provare il tool
|
|
3
|
+
*
|
|
4
|
+
* Crea due esperimenti di esempio:
|
|
5
|
+
* 1. "Esperimento Positivo" — incremento reale di click (+50%) nel periodo post
|
|
6
|
+
* 2. "Esperimento Neutro" — nessuna differenza significativa tra pre e post
|
|
7
|
+
*
|
|
8
|
+
* Ogni esperimento ha 35 giorni di metriche pre-split e 35 giorni post-split.
|
|
9
|
+
*
|
|
10
|
+
* Uso: npx tsx src/demo.ts oppure npm run demo
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
package/dist/demo.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo — Popola il database con dati finti per provare il tool
|
|
3
|
+
*
|
|
4
|
+
* Crea due esperimenti di esempio:
|
|
5
|
+
* 1. "Esperimento Positivo" — incremento reale di click (+50%) nel periodo post
|
|
6
|
+
* 2. "Esperimento Neutro" — nessuna differenza significativa tra pre e post
|
|
7
|
+
*
|
|
8
|
+
* Ogni esperimento ha 35 giorni di metriche pre-split e 35 giorni post-split.
|
|
9
|
+
*
|
|
10
|
+
* Uso: npx tsx src/demo.ts oppure npm run demo
|
|
11
|
+
*/
|
|
12
|
+
import { config } from 'dotenv';
|
|
13
|
+
config();
|
|
14
|
+
import { eq } from 'drizzle-orm';
|
|
15
|
+
import { db, migrateDB, closeDb } from './database/db.js';
|
|
16
|
+
import { users, tests, metrics } from './database/schema.js';
|
|
17
|
+
// ── Generatore pseudo-random deterministico (seeded LCG) ─────────────────
|
|
18
|
+
class SeededRng {
|
|
19
|
+
state;
|
|
20
|
+
constructor(seed) {
|
|
21
|
+
this.state = seed;
|
|
22
|
+
}
|
|
23
|
+
/** Restituisce un float in [0, 1) */
|
|
24
|
+
next() {
|
|
25
|
+
this.state = (this.state * 1664525 + 1013904223) & 0x7fffffff;
|
|
26
|
+
return this.state / 0x7fffffff;
|
|
27
|
+
}
|
|
28
|
+
/** Distribuzione normale approssimata (Box-Muller) */
|
|
29
|
+
normal(mean, stdDev) {
|
|
30
|
+
const u1 = this.next() || 0.0001;
|
|
31
|
+
const u2 = this.next();
|
|
32
|
+
const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
|
33
|
+
return mean + z * stdDev;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
37
|
+
/** Genera una data ISO (YYYY-MM-DD) a partire da un offset in giorni da oggi */
|
|
38
|
+
function dateOffset(daysFromToday) {
|
|
39
|
+
const d = new Date();
|
|
40
|
+
d.setDate(d.getDate() + daysFromToday);
|
|
41
|
+
return d.toISOString().slice(0, 10);
|
|
42
|
+
}
|
|
43
|
+
/** Genera N giorni di metriche (clicks/impressions) con rumore realistico */
|
|
44
|
+
function generateMetrics(rng, testId, startOffset, days, clickMean, clickStdDev, impressionMultiplier) {
|
|
45
|
+
const rows = [];
|
|
46
|
+
for (let i = 0; i < days; i++) {
|
|
47
|
+
const clicks = Math.max(0, Math.round(rng.normal(clickMean, clickStdDev)));
|
|
48
|
+
const impressions = Math.max(clicks, Math.round(rng.normal(clicks * impressionMultiplier, clicks * impressionMultiplier * 0.15)));
|
|
49
|
+
rows.push({
|
|
50
|
+
testId,
|
|
51
|
+
date: dateOffset(startOffset + i),
|
|
52
|
+
clicks,
|
|
53
|
+
impressions,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return rows;
|
|
57
|
+
}
|
|
58
|
+
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
59
|
+
function demo() {
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log('╔══════════════════════════════════════════╗');
|
|
62
|
+
console.log('║ SEO Testing Tool — Modalità Demo ║');
|
|
63
|
+
console.log('╚══════════════════════════════════════════╝');
|
|
64
|
+
console.log('');
|
|
65
|
+
try {
|
|
66
|
+
migrateDB();
|
|
67
|
+
console.log('[OK] Database pronto');
|
|
68
|
+
// ── Utente demo ──────────────────────────────────────────────────────
|
|
69
|
+
const DEMO_USER_ID = 'demo-user';
|
|
70
|
+
const existing = db.select().from(users).where(eq(users.id, DEMO_USER_ID)).get();
|
|
71
|
+
if (!existing) {
|
|
72
|
+
db.insert(users).values({ id: DEMO_USER_ID, email: 'demo@seo-tool.local' }).run();
|
|
73
|
+
}
|
|
74
|
+
console.log('[OK] Utente demo pronto');
|
|
75
|
+
// ── Configurazione esperimenti ───────────────────────────────────────
|
|
76
|
+
const DAYS_PRE = 35;
|
|
77
|
+
const DAYS_POST = 35;
|
|
78
|
+
const START_OFFSET = -(DAYS_PRE + DAYS_POST); // inizio = 70 giorni fa
|
|
79
|
+
const SPLIT_OFFSET = START_OFFSET + DAYS_PRE; // split = 35 giorni fa
|
|
80
|
+
const startDate = dateOffset(START_OFFSET);
|
|
81
|
+
const splitDate = dateOffset(SPLIT_OFFSET);
|
|
82
|
+
// ── 1. Esperimento Positivo ──────────────────────────────────────────
|
|
83
|
+
const rngPositive = new SeededRng(42);
|
|
84
|
+
const testPositive = db.insert(tests).values({
|
|
85
|
+
name: 'Esperimento Positivo',
|
|
86
|
+
siteUrl: 'sc-domain:esempio-positivo.it',
|
|
87
|
+
urls: JSON.stringify(['https://esempio-positivo.it/landing-page']),
|
|
88
|
+
startDate,
|
|
89
|
+
splitDate,
|
|
90
|
+
status: 'completed',
|
|
91
|
+
lastPValue: 0.001,
|
|
92
|
+
lastImprovement: 46.6,
|
|
93
|
+
userId: DEMO_USER_ID,
|
|
94
|
+
}).returning().get();
|
|
95
|
+
// Pre-split: ~50 click/giorno, post-split: ~75 click/giorno (+50%)
|
|
96
|
+
const prePositive = generateMetrics(rngPositive, testPositive.id, START_OFFSET, DAYS_PRE, 1500, 100, 10);
|
|
97
|
+
const postPositive = generateMetrics(rngPositive, testPositive.id, SPLIT_OFFSET, DAYS_POST, 2200, 150, 10);
|
|
98
|
+
for (const row of [...prePositive, ...postPositive]) {
|
|
99
|
+
db.insert(metrics).values(row).run();
|
|
100
|
+
}
|
|
101
|
+
console.log(`[OK] Esperimento Positivo creato — ID: ${testPositive.id.slice(0, 8)}...`);
|
|
102
|
+
console.log(` Pre: ${DAYS_PRE} giorni (~1500 click/giorno)`);
|
|
103
|
+
console.log(` Post: ${DAYS_POST} giorni (~2200 click/giorno, +46%)`);
|
|
104
|
+
// ── 2. Esperimento Neutro ────────────────────────────────────────────
|
|
105
|
+
const rngNeutral = new SeededRng(123);
|
|
106
|
+
const testNeutral = db.insert(tests).values({
|
|
107
|
+
name: 'Esperimento Neutro',
|
|
108
|
+
siteUrl: 'sc-domain:esempio-neutro.it',
|
|
109
|
+
urls: JSON.stringify(['https://esempio-neutro.it/pagina-test']),
|
|
110
|
+
startDate,
|
|
111
|
+
splitDate,
|
|
112
|
+
status: 'completed',
|
|
113
|
+
lastPValue: 0.72,
|
|
114
|
+
lastImprovement: 1.2,
|
|
115
|
+
userId: DEMO_USER_ID,
|
|
116
|
+
}).returning().get();
|
|
117
|
+
// Pre-split: ~50 click/giorno, post-split: ~51 click/giorno (nessun cambiamento reale)
|
|
118
|
+
const preNeutral = generateMetrics(rngNeutral, testNeutral.id, START_OFFSET, DAYS_PRE, 50, 8, 10);
|
|
119
|
+
const postNeutral = generateMetrics(rngNeutral, testNeutral.id, SPLIT_OFFSET, DAYS_POST, 51, 8, 10);
|
|
120
|
+
for (const row of [...preNeutral, ...postNeutral]) {
|
|
121
|
+
db.insert(metrics).values(row).run();
|
|
122
|
+
}
|
|
123
|
+
console.log(`[OK] Esperimento Neutro creato — ID: ${testNeutral.id.slice(0, 8)}...`);
|
|
124
|
+
console.log(` Pre: ${DAYS_PRE} giorni (~50 click/giorno)`);
|
|
125
|
+
console.log(` Post: ${DAYS_POST} giorni (~51 click/giorno, nessun effetto)`);
|
|
126
|
+
// ── Riepilogo ────────────────────────────────────────────────────────
|
|
127
|
+
console.log('');
|
|
128
|
+
console.log('════════════════════════════════════════════');
|
|
129
|
+
console.log(' Demo completata! Prova questi comandi:');
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log(` npx tsx src/cli.ts list`);
|
|
132
|
+
console.log(` npx tsx src/cli.ts status ${testPositive.id.slice(0, 8)}`);
|
|
133
|
+
console.log(` npx tsx src/cli.ts status ${testNeutral.id.slice(0, 8)}`);
|
|
134
|
+
console.log(` npx tsx src/cli.ts export ${testPositive.id.slice(0, 8)}`);
|
|
135
|
+
console.log('════════════════════════════════════════════');
|
|
136
|
+
console.log('');
|
|
137
|
+
closeDb();
|
|
138
|
+
process.exit(0);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
console.error('');
|
|
142
|
+
console.error('[ERRORE] Demo fallita:');
|
|
143
|
+
console.error(error instanceof Error ? error.message : error);
|
|
144
|
+
closeDb();
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
demo();
|
|
149
|
+
//# sourceMappingURL=demo.js.map
|
package/dist/demo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,MAAM,EAAE,CAAC;AAET,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE7D,4EAA4E;AAC5E,MAAM,SAAS;IACL,KAAK,CAAS;IACtB,YAAY,IAAY;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,qCAAqC;IACrC,IAAI;QACF,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC;QAC9D,OAAO,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;IACjC,CAAC;IACD,sDAAsD;IACtD,MAAM,CAAC,IAAY,EAAE,MAAc;QACjC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC;QACjC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACpE,OAAO,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC;IAC3B,CAAC;CACF;AAED,gFAAgF;AAEhF,gFAAgF;AAChF,SAAS,UAAU,CAAC,aAAqB;IACvC,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,6EAA6E;AAC7E,SAAS,eAAe,CACtB,GAAc,EACd,MAAc,EACd,WAAmB,EACnB,IAAY,EACZ,SAAiB,EACjB,WAAmB,EACnB,oBAA4B;IAE5B,MAAM,IAAI,GAA4E,EAAE,CAAC;IACzF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC1B,MAAM,EACN,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,oBAAoB,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAAC,CAAC,CAC5F,CAAC;QACF,IAAI,CAAC,IAAI,CAAC;YACR,MAAM;YACN,IAAI,EAAE,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC;YACjC,MAAM;YACN,WAAW;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gFAAgF;AAEhF,SAAS,IAAI;IACX,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,IAAI,CAAC;QACH,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QAEpC,wEAAwE;QACxE,MAAM,YAAY,GAAG,WAAW,CAAC;QACjC,MAAM,QAAQ,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QACjF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;QACpF,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAEvC,wEAAwE;QACxE,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,CAAC,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,wBAAwB;QACtE,MAAM,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC,CAAE,uBAAuB;QAEtE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QAE3C,wEAAwE;QACxE,MAAM,WAAW,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC;QAEtC,MAAM,YAAY,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;YAC3C,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,+BAA+B;YACxC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,0CAA0C,CAAC,CAAC;YAClE,SAAS;YACT,SAAS;YACT,MAAM,EAAE,WAAW;YACnB,UAAU,EAAE,KAAK;YACjB,eAAe,EAAE,IAAI;YACrB,MAAM,EAAE,YAAY;SACrB,CAAC,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC;QAErB,mEAAmE;QACnE,MAAM,WAAW,GAAG,eAAe,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACzG,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QAE3G,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,WAAW,EAAE,GAAG,YAAY,CAAC,EAAE,CAAC;YACpD,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACvC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,0CAA0C,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACxF,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,8BAA8B,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,oCAAoC,CAAC,CAAC;QAEzE,wEAAwE;QACxE,MAAM,UAAU,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAEtC,MAAM,WAAW,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;YAC1C,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE,6BAA6B;YACtC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,uCAAuC,CAAC,CAAC;YAC/D,SAAS;YACT,SAAS;YACT,MAAM,EAAE,WAAW;YACnB,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,GAAG;YACpB,MAAM,EAAE,YAAY;SACrB,CAAC,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC;QAErB,uFAAuF;QACvF,MAAM,UAAU,GAAG,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAClG,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAEpG,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,UAAU,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC;YAClD,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACvC,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,yCAAyC,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACtF,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,4BAA4B,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,4CAA4C,CAAC,CAAC;QAEjF,wEAAwE;QACxE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,+BAA+B,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,+BAA+B,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACzE,OAAO,CAAC,GAAG,CAAC,+BAA+B,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSCDataFetcher - Fetch dati da Google Search Console
|
|
3
|
+
*/
|
|
4
|
+
import { GSCPermissionService } from './GSCPermissionService.js';
|
|
5
|
+
interface SearchAnalyticsParams {
|
|
6
|
+
siteUrl: string;
|
|
7
|
+
startDate: string;
|
|
8
|
+
endDate: string;
|
|
9
|
+
timezone?: string;
|
|
10
|
+
dimensions?: string[];
|
|
11
|
+
startRow?: number;
|
|
12
|
+
concurrentRequests?: number;
|
|
13
|
+
onProgress?: (progress: number) => void;
|
|
14
|
+
maxMemoryMB?: number;
|
|
15
|
+
accessToken?: string;
|
|
16
|
+
}
|
|
17
|
+
interface SearchAnalyticsRow {
|
|
18
|
+
keys: string[];
|
|
19
|
+
clicks: number;
|
|
20
|
+
impressions: number;
|
|
21
|
+
ctr?: number;
|
|
22
|
+
position?: number;
|
|
23
|
+
date?: string;
|
|
24
|
+
}
|
|
25
|
+
interface SearchAnalyticsData {
|
|
26
|
+
rows: SearchAnalyticsRow[];
|
|
27
|
+
hasDataGap?: boolean;
|
|
28
|
+
gapDays?: number;
|
|
29
|
+
message?: string;
|
|
30
|
+
lastAvailableDate?: string;
|
|
31
|
+
timezone?: string;
|
|
32
|
+
timezoneWarning?: string;
|
|
33
|
+
dstHandling?: string;
|
|
34
|
+
totalRows?: number;
|
|
35
|
+
stats?: {
|
|
36
|
+
averageClicks: number;
|
|
37
|
+
totalClicks: number;
|
|
38
|
+
totalImpressions: number;
|
|
39
|
+
daysWithData: number;
|
|
40
|
+
daysRequested: number;
|
|
41
|
+
};
|
|
42
|
+
processingInfo?: {
|
|
43
|
+
totalPages: number;
|
|
44
|
+
pageSize: number;
|
|
45
|
+
retriesPerformed: number;
|
|
46
|
+
progressCallbackInvoked: boolean;
|
|
47
|
+
peakMemoryUsageMB: number;
|
|
48
|
+
memoryLimitReached: boolean;
|
|
49
|
+
};
|
|
50
|
+
warnings?: Array<{
|
|
51
|
+
type: string;
|
|
52
|
+
message?: string;
|
|
53
|
+
startRow?: number;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
export declare class GSCDataFetcher {
|
|
57
|
+
private readonly MAX_RETRIES;
|
|
58
|
+
private readonly INITIAL_DELAY;
|
|
59
|
+
private permissionService;
|
|
60
|
+
private retryCount;
|
|
61
|
+
private retryWarnings;
|
|
62
|
+
constructor(permissionService?: GSCPermissionService);
|
|
63
|
+
private resetRetryTracking;
|
|
64
|
+
/**
|
|
65
|
+
* Metodo interno per fare richieste alle API Google Search Console
|
|
66
|
+
*/
|
|
67
|
+
private makeRequest;
|
|
68
|
+
/**
|
|
69
|
+
* Implementa exponential backoff per gestire rate limiting
|
|
70
|
+
*/
|
|
71
|
+
private delay;
|
|
72
|
+
/**
|
|
73
|
+
* Fetch con retry e exponential backoff
|
|
74
|
+
*/
|
|
75
|
+
private fetchWithRetry;
|
|
76
|
+
/**
|
|
77
|
+
* Calcola i giorni tra due date
|
|
78
|
+
*/
|
|
79
|
+
private daysBetween;
|
|
80
|
+
/**
|
|
81
|
+
* Rileva gap temporali nei dati
|
|
82
|
+
*/
|
|
83
|
+
private detectDataGap;
|
|
84
|
+
/**
|
|
85
|
+
* Calcola statistiche dai dati
|
|
86
|
+
*/
|
|
87
|
+
private calculateStats;
|
|
88
|
+
fetchSearchAnalytics(accessToken: string, propertyUrl: string, options: {
|
|
89
|
+
startDate: string;
|
|
90
|
+
endDate: string;
|
|
91
|
+
}): Promise<SearchAnalyticsData>;
|
|
92
|
+
fetchSearchAnalytics(params: SearchAnalyticsParams): Promise<SearchAnalyticsData>;
|
|
93
|
+
private fetchSearchAnalyticsInternal;
|
|
94
|
+
/**
|
|
95
|
+
* Fetch con richieste parallele per migliorare le performance
|
|
96
|
+
*/
|
|
97
|
+
private fetchWithConcurrency;
|
|
98
|
+
}
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=GSCDataFetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GSCDataFetcher.d.ts","sourceRoot":"","sources":["../../src/gsc/GSCDataFetcher.ts"],"names":[],"mappings":"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"}
|