-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextractPages.js
More file actions
152 lines (135 loc) · 4.4 KB
/
Copy pathextractPages.js
File metadata and controls
152 lines (135 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { getProjects } from './getProjects.js';
import { getBuilds } from './getBuilds.js';
import { getSessions } from './getSessions.js';
import { getPageUrls } from './getNetworkLogs.js';
import { isMainModule, parseArgs } from './lib/cli.js';
const DEFAULT_OUTPUT = 'output/pages.json';
/**
* Run the full pipeline: projects → builds → sessions → page URLs.
*
* Narrow the scope with optional IDs. When an ID is provided, that stage
* is skipped and the pipeline starts from that level.
*
* @param {{
* projectId?: string|number,
* buildId?: string,
* sessionId?: string,
* buildLimit?: number,
* quiet?: boolean
* }} [options]
* @returns {Promise<object[]>}
*/
export async function extractPages({
projectId,
buildId,
sessionId,
buildLimit = 100,
quiet = false,
} = {}) {
const log = quiet ? () => {} : console.log;
const results = [];
// Start from a single session
if (sessionId) {
const urls = await getPageUrls(sessionId);
results.push({ sessionId, urls });
return results;
}
// Start from a single build
if (buildId) {
const sessions = await getSessions(buildId);
log(`Build ${buildId}: ${sessions.length} session(s)`);
for (const session of sessions) {
const id = session.hashed_id;
try {
const urls = await getPageUrls(id);
results.push({ projectId, buildId, sessionId: id, urls });
log(` Session ${id}: ${urls.length} page URL(s)`);
} catch (error) {
log(` Session ${id}: skipped (${error.message})`);
results.push({ projectId, buildId, sessionId: id, urls: [], error: error.message });
}
}
return results;
}
// Resolve project list
let projects;
if (projectId) {
projects = [{ id: projectId }];
} else {
projects = await getProjects();
log(`Found ${projects.length} project(s)`);
}
for (const project of projects) {
const pid = project.id;
const builds = await getBuilds(pid, { limit: buildLimit });
log(`Project ${pid}: ${builds.length} build(s)`);
for (const build of builds) {
const bid = build.hashed_id;
const sessions = await getSessions(bid);
log(` Build ${bid}: ${sessions.length} session(s)`);
for (const session of sessions) {
const sid = session.hashed_id;
try {
const urls = await getPageUrls(sid);
results.push({ projectId: pid, buildId: bid, sessionId: sid, urls });
log(` Session ${sid}: ${urls.length} page URL(s)`);
} catch (error) {
log(` Session ${sid}: skipped (${error.message})`);
results.push({
projectId: pid,
buildId: bid,
sessionId: sid,
urls: [],
error: error.message,
});
}
}
}
}
return results;
}
async function writeResults(results, outputPath) {
const absolutePath = resolve(outputPath);
await mkdir(dirname(absolutePath), { recursive: true });
await writeFile(absolutePath, JSON.stringify(results, null, 2) + '\n', 'utf8');
return absolutePath;
}
async function main() {
const args = parseArgs(process.argv.slice(2));
if (args.help || args.h) {
console.log(`Usage:
node extractPages.js [options]
Options:
--projectId <id> Limit to one project
--buildId <id> Start from a build (skips projects)
--sessionId <id> Extract pages from one session only
--buildLimit <n> Max builds per project (default: 100)
--out <path> Write JSON results to this file (default: ${DEFAULT_OUTPUT})
--quiet Suppress progress logs
`);
return;
}
const outputPath = args.out || args.output || DEFAULT_OUTPUT;
const quiet = Boolean(args.quiet);
const results = await extractPages({
projectId: args.projectId || process.env.BROWSERSTACK_PROJECT_ID,
buildId: args.buildId || process.env.BROWSERSTACK_BUILD_ID,
sessionId: args.sessionId || process.env.BROWSERSTACK_SESSION_ID,
buildLimit: args.buildLimit ? Number(args.buildLimit) : 100,
quiet,
});
const writtenTo = await writeResults(results, outputPath);
if (!quiet) {
console.log(`Wrote ${results.length} result(s) to ${writtenTo}`);
} else {
console.log(writtenTo);
}
}
if (isMainModule(import.meta.url)) {
main().catch((error) => {
console.error('Pipeline failed:', error.message);
process.exit(1);
});
}