document360-capture 0.1.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 +80 -0
- package/dist/annotate/compose.d.ts +7 -0
- package/dist/annotate/compose.js +65 -0
- package/dist/annotate/compose.js.map +1 -0
- package/dist/annotate/svg.d.ts +5 -0
- package/dist/annotate/svg.js +42 -0
- package/dist/annotate/svg.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +66 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.js +52 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/capture.d.ts +5 -0
- package/dist/commands/capture.js +77 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.js +88 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +97 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +33 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +24 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/authState.d.ts +10 -0
- package/dist/config/authState.js +27 -0
- package/dist/config/authState.js.map +1 -0
- package/dist/config/projectConfig.d.ts +27 -0
- package/dist/config/projectConfig.js +43 -0
- package/dist/config/projectConfig.js.map +1 -0
- package/dist/config/userConfig.d.ts +6 -0
- package/dist/config/userConfig.js +24 -0
- package/dist/config/userConfig.js.map +1 -0
- package/dist/helpers/dumpAnnotations.d.ts +3 -0
- package/dist/helpers/dumpAnnotations.js +39 -0
- package/dist/helpers/dumpAnnotations.js.map +1 -0
- package/dist/helpers/index.d.ts +3 -0
- package/dist/helpers/index.js +3 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/types.d.ts +37 -0
- package/dist/helpers/types.js +2 -0
- package/dist/helpers/types.js.map +1 -0
- package/dist/helpers/waitPastLogin.d.ts +2 -0
- package/dist/helpers/waitPastLogin.js +7 -0
- package/dist/helpers/waitPastLogin.js.map +1 -0
- package/dist/runner/expiryDetect.d.ts +1 -0
- package/dist/runner/expiryDetect.js +19 -0
- package/dist/runner/expiryDetect.js.map +1 -0
- package/dist/runner/playwrightConfig.d.ts +8 -0
- package/dist/runner/playwrightConfig.js +33 -0
- package/dist/runner/playwrightConfig.js.map +1 -0
- package/dist/runner/runSpecs.d.ts +14 -0
- package/dist/runner/runSpecs.js +62 -0
- package/dist/runner/runSpecs.js.map +1 -0
- package/dist/scripts/postinstall.d.ts +1 -0
- package/dist/scripts/postinstall.js +18 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { input, confirm } from '@inquirer/prompts';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { basename, join } from 'node:path';
|
|
4
|
+
import { findProjectConfigPath, writeProjectConfig, } from '../config/projectConfig.js';
|
|
5
|
+
export async function initCommand() {
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const path = findProjectConfigPath(cwd);
|
|
8
|
+
if (existsSync(path)) {
|
|
9
|
+
const overwrite = await confirm({
|
|
10
|
+
message: `${path} already exists. Overwrite?`,
|
|
11
|
+
default: false,
|
|
12
|
+
});
|
|
13
|
+
if (!overwrite) {
|
|
14
|
+
console.log('Init cancelled.');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const defaultProjectId = readPackageName(cwd) ?? basename(cwd);
|
|
19
|
+
const projectId = await input({
|
|
20
|
+
message: 'Project ID (used to scope auth-state on disk):',
|
|
21
|
+
default: defaultProjectId,
|
|
22
|
+
validate: v => (v.trim().length > 0 ? true : 'Project ID is required'),
|
|
23
|
+
});
|
|
24
|
+
const captureDir = await input({
|
|
25
|
+
message: 'Capture directory (where .spec.ts files live):',
|
|
26
|
+
default: 'user-docs/_capture',
|
|
27
|
+
});
|
|
28
|
+
const outputDir = await input({
|
|
29
|
+
message: 'Output directory (where final .png files land):',
|
|
30
|
+
default: 'user-docs/_screenshots',
|
|
31
|
+
});
|
|
32
|
+
const viewportInput = await input({
|
|
33
|
+
message: 'Viewport (WIDTHxHEIGHT):',
|
|
34
|
+
default: '1440x900',
|
|
35
|
+
validate: v => /^\d+x\d+$/.test(v) || 'Use WIDTHxHEIGHT, e.g. 1440x900',
|
|
36
|
+
});
|
|
37
|
+
const [w, h] = viewportInput.split('x').map(Number);
|
|
38
|
+
const stagingUrl = await input({
|
|
39
|
+
message: 'Staging URL (where captures start):',
|
|
40
|
+
default: 'https://example.com/',
|
|
41
|
+
validate: v => (v.startsWith('http') ? true : 'Must be a full URL'),
|
|
42
|
+
});
|
|
43
|
+
const authBoundary = await input({
|
|
44
|
+
message: 'Auth boundary URL pattern (regex matching post-login routes):',
|
|
45
|
+
default: '/\\/(home|app|projects|dashboard)(/|$)/',
|
|
46
|
+
});
|
|
47
|
+
const addProd = await confirm({
|
|
48
|
+
message: 'Add a "prod" environment too?',
|
|
49
|
+
default: true,
|
|
50
|
+
});
|
|
51
|
+
const environments = {
|
|
52
|
+
staging: { startUrl: stagingUrl, authBoundaryUrlPattern: authBoundary },
|
|
53
|
+
};
|
|
54
|
+
if (addProd) {
|
|
55
|
+
const prodUrl = await input({
|
|
56
|
+
message: 'Prod URL:',
|
|
57
|
+
default: stagingUrl.replace(/staging\./, ''),
|
|
58
|
+
validate: v => (v.startsWith('http') ? true : 'Must be a full URL'),
|
|
59
|
+
});
|
|
60
|
+
environments.prod = { startUrl: prodUrl, authBoundaryUrlPattern: authBoundary };
|
|
61
|
+
}
|
|
62
|
+
const annotate = await confirm({
|
|
63
|
+
message: 'Enable annotation overlays (highlights, callouts, redactions) by default?',
|
|
64
|
+
default: true,
|
|
65
|
+
});
|
|
66
|
+
const cfg = {
|
|
67
|
+
projectId,
|
|
68
|
+
captureDir,
|
|
69
|
+
outputDir,
|
|
70
|
+
viewport: { width: w, height: h },
|
|
71
|
+
loginTimeoutMs: 0,
|
|
72
|
+
annotation: { enabled: annotate },
|
|
73
|
+
environments,
|
|
74
|
+
defaultEnvironment: 'staging',
|
|
75
|
+
};
|
|
76
|
+
writeProjectConfig(path, cfg);
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log(`✓ Wrote ${path}`);
|
|
79
|
+
console.log('');
|
|
80
|
+
console.log('Next steps:');
|
|
81
|
+
console.log(' 1. d360-capture auth --env staging # log in once, no timeout');
|
|
82
|
+
console.log(' 2. d360-capture capture # run all specs in captureDir');
|
|
83
|
+
console.log('');
|
|
84
|
+
}
|
|
85
|
+
function readPackageName(cwd) {
|
|
86
|
+
const path = join(cwd, 'package.json');
|
|
87
|
+
if (!existsSync(path))
|
|
88
|
+
return null;
|
|
89
|
+
try {
|
|
90
|
+
const pkg = JSON.parse(readFileSync(path, 'utf8'));
|
|
91
|
+
return pkg.name ?? null;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function listCommand(): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import { findProjectConfigPath, readProjectConfig } from '../config/projectConfig.js';
|
|
4
|
+
export async function listCommand() {
|
|
5
|
+
const cwd = process.cwd();
|
|
6
|
+
const cfg = readProjectConfig(findProjectConfigPath(cwd));
|
|
7
|
+
const captureDirAbs = isAbsolute(cfg.captureDir) ? cfg.captureDir : resolve(cwd, cfg.captureDir);
|
|
8
|
+
const outputDirAbs = isAbsolute(cfg.outputDir) ? cfg.outputDir : resolve(cwd, cfg.outputDir);
|
|
9
|
+
if (!existsSync(captureDirAbs)) {
|
|
10
|
+
console.log(`Capture dir does not exist: ${captureDirAbs}`);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const specs = readdirSync(captureDirAbs)
|
|
14
|
+
.filter(f => f.endsWith('.spec.ts'))
|
|
15
|
+
.sort();
|
|
16
|
+
if (specs.length === 0) {
|
|
17
|
+
console.log(`No specs found in ${cfg.captureDir}.`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log(' Spec ID Last capture');
|
|
22
|
+
console.log(' ─────────────────────────────────────────────── ───────────────────');
|
|
23
|
+
for (const f of specs) {
|
|
24
|
+
const id = f.replace(/\.spec\.ts$/, '');
|
|
25
|
+
const finalPath = join(outputDirAbs, `${id}.png`);
|
|
26
|
+
const lastCapture = existsSync(finalPath)
|
|
27
|
+
? new Date(statSync(finalPath).mtimeMs).toISOString().slice(0, 19).replace('T', ' ')
|
|
28
|
+
: '(never)';
|
|
29
|
+
console.log(` ${id.padEnd(47)} ${lastCapture}`);
|
|
30
|
+
}
|
|
31
|
+
console.log('');
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEtF,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,iBAAiB,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACjG,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAE7F,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,+BAA+B,aAAa,EAAE,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,aAAa,CAAC;SACrC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SACnC,IAAI,EAAE,CAAC;IAEV,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IACrF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC;YACvC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;YACpF,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function statusCommand(): Promise<void>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { findProjectConfigPath, readProjectConfig } from '../config/projectConfig.js';
|
|
2
|
+
import { getAuthStateInfo } from '../config/authState.js';
|
|
3
|
+
export async function statusCommand() {
|
|
4
|
+
const cfg = readProjectConfig(findProjectConfigPath());
|
|
5
|
+
console.log('');
|
|
6
|
+
console.log(`projectId: ${cfg.projectId}`);
|
|
7
|
+
console.log(`captureDir: ${cfg.captureDir}`);
|
|
8
|
+
console.log(`outputDir: ${cfg.outputDir}`);
|
|
9
|
+
console.log(`viewport: ${cfg.viewport.width}x${cfg.viewport.height}`);
|
|
10
|
+
console.log(`annotation enabled: ${cfg.annotation.enabled}`);
|
|
11
|
+
console.log(`defaultEnvironment: ${cfg.defaultEnvironment}`);
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log('Environments:');
|
|
14
|
+
for (const [name, env] of Object.entries(cfg.environments)) {
|
|
15
|
+
const info = getAuthStateInfo(cfg.projectId, name);
|
|
16
|
+
const authStatus = info.exists
|
|
17
|
+
? `auth saved ${info.ageMs != null ? Math.floor(info.ageMs / 86_400_000) + 'd ago' : ''}`
|
|
18
|
+
: 'no auth-state';
|
|
19
|
+
console.log(` ${name.padEnd(10)} ${env.startUrl}`);
|
|
20
|
+
console.log(` ${authStatus}`);
|
|
21
|
+
}
|
|
22
|
+
console.log('');
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,GAAG,GAAG,iBAAiB,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAEvD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACnD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM;YAC5B,CAAC,CAAC,cAAc,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzF,CAAC,CAAC,eAAe,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function authStateDir(): string;
|
|
2
|
+
export declare function authStatePath(projectId: string, envName: string): string;
|
|
3
|
+
export declare function ensureAuthStateDir(projectId: string): void;
|
|
4
|
+
export type AuthStateInfo = {
|
|
5
|
+
path: string;
|
|
6
|
+
exists: boolean;
|
|
7
|
+
ageMs?: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function getAuthStateInfo(projectId: string, envName: string): AuthStateInfo;
|
|
10
|
+
export declare function ensureParentDir(path: string): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
export function authStateDir() {
|
|
5
|
+
return join(homedir(), '.document360-capture', 'auth-states');
|
|
6
|
+
}
|
|
7
|
+
export function authStatePath(projectId, envName) {
|
|
8
|
+
return join(authStateDir(), projectId, `${envName}.json`);
|
|
9
|
+
}
|
|
10
|
+
export function ensureAuthStateDir(projectId) {
|
|
11
|
+
const dir = join(authStateDir(), projectId);
|
|
12
|
+
if (!existsSync(dir))
|
|
13
|
+
mkdirSync(dir, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
export function getAuthStateInfo(projectId, envName) {
|
|
16
|
+
const path = authStatePath(projectId, envName);
|
|
17
|
+
if (!existsSync(path))
|
|
18
|
+
return { path, exists: false };
|
|
19
|
+
const stat = statSync(path);
|
|
20
|
+
return { path, exists: true, ageMs: Date.now() - stat.mtimeMs };
|
|
21
|
+
}
|
|
22
|
+
export function ensureParentDir(path) {
|
|
23
|
+
const parent = dirname(path);
|
|
24
|
+
if (!existsSync(parent))
|
|
25
|
+
mkdirSync(parent, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=authState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authState.js","sourceRoot":"","sources":["../../src/config/authState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,sBAAsB,EAAE,aAAa,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,OAAe;IAC9D,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC;AAQD,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,OAAe;IACjE,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type EnvironmentConfig = {
|
|
2
|
+
startUrl: string;
|
|
3
|
+
authBoundaryUrlPattern: string;
|
|
4
|
+
};
|
|
5
|
+
export type ProjectConfig = {
|
|
6
|
+
projectId: string;
|
|
7
|
+
captureDir: string;
|
|
8
|
+
outputDir: string;
|
|
9
|
+
viewport: {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
};
|
|
13
|
+
loginTimeoutMs: number;
|
|
14
|
+
annotation: {
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
};
|
|
17
|
+
environments: Record<string, EnvironmentConfig>;
|
|
18
|
+
defaultEnvironment: string;
|
|
19
|
+
};
|
|
20
|
+
export declare const PROJECT_CONFIG_FILENAME = ".d360-capture.json";
|
|
21
|
+
export declare function findProjectConfigPath(cwd?: string): string;
|
|
22
|
+
export declare function readProjectConfig(path: string): ProjectConfig;
|
|
23
|
+
export declare function writeProjectConfig(path: string, cfg: ProjectConfig): void;
|
|
24
|
+
export declare function resolveEnv(cfg: ProjectConfig, name?: string): {
|
|
25
|
+
name: string;
|
|
26
|
+
env: EnvironmentConfig;
|
|
27
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const PROJECT_CONFIG_FILENAME = '.d360-capture.json';
|
|
4
|
+
export function findProjectConfigPath(cwd = process.cwd()) {
|
|
5
|
+
return join(cwd, PROJECT_CONFIG_FILENAME);
|
|
6
|
+
}
|
|
7
|
+
export function readProjectConfig(path) {
|
|
8
|
+
if (!existsSync(path)) {
|
|
9
|
+
throw new Error(`No project config at ${path}. Run \`d360-capture init\` to create one.`);
|
|
10
|
+
}
|
|
11
|
+
const raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
12
|
+
validateProjectConfig(raw, path);
|
|
13
|
+
return raw;
|
|
14
|
+
}
|
|
15
|
+
export function writeProjectConfig(path, cfg) {
|
|
16
|
+
writeFileSync(path, JSON.stringify(cfg, null, 2) + '\n', 'utf8');
|
|
17
|
+
}
|
|
18
|
+
export function resolveEnv(cfg, name) {
|
|
19
|
+
const resolved = name ?? cfg.defaultEnvironment;
|
|
20
|
+
const env = cfg.environments[resolved];
|
|
21
|
+
if (!env) {
|
|
22
|
+
const available = Object.keys(cfg.environments).join(', ');
|
|
23
|
+
throw new Error(`Unknown environment "${resolved}". Available: ${available}`);
|
|
24
|
+
}
|
|
25
|
+
return { name: resolved, env };
|
|
26
|
+
}
|
|
27
|
+
function validateProjectConfig(cfg, path) {
|
|
28
|
+
const missing = [];
|
|
29
|
+
if (!cfg.projectId)
|
|
30
|
+
missing.push('projectId');
|
|
31
|
+
if (!cfg.captureDir)
|
|
32
|
+
missing.push('captureDir');
|
|
33
|
+
if (!cfg.outputDir)
|
|
34
|
+
missing.push('outputDir');
|
|
35
|
+
if (!cfg.environments || Object.keys(cfg.environments).length === 0)
|
|
36
|
+
missing.push('environments');
|
|
37
|
+
if (!cfg.defaultEnvironment)
|
|
38
|
+
missing.push('defaultEnvironment');
|
|
39
|
+
if (missing.length > 0) {
|
|
40
|
+
throw new Error(`Invalid config at ${path}: missing ${missing.join(', ')}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=projectConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectConfig.js","sourceRoot":"","sources":["../../src/config/projectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAkBjC,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAE5D,MAAM,UAAU,qBAAqB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC/D,OAAO,IAAI,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,4CAA4C,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,CAAC;IACpE,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACjC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAkB;IACjE,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAkB,EAAE,IAAa;IAC1D,MAAM,QAAQ,GAAG,IAAI,IAAI,GAAG,CAAC,kBAAkB,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,iBAAiB,SAAS,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAkB,EAAE,IAAY;IAC7D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG,CAAC,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,CAAC,GAAG,CAAC,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAClG,IAAI,CAAC,GAAG,CAAC,kBAAkB;QAAE,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
const PATH = join(homedir(), '.document360-capture', 'config.json');
|
|
5
|
+
export function userConfigPath() {
|
|
6
|
+
return PATH;
|
|
7
|
+
}
|
|
8
|
+
export function readUserConfig() {
|
|
9
|
+
if (!existsSync(PATH))
|
|
10
|
+
return {};
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(readFileSync(PATH, 'utf8'));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function writeUserConfig(cfg) {
|
|
19
|
+
const dir = dirname(PATH);
|
|
20
|
+
if (!existsSync(dir))
|
|
21
|
+
mkdirSync(dir, { recursive: true });
|
|
22
|
+
writeFileSync(PATH, JSON.stringify(cfg, null, 2) + '\n', 'utf8');
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=userConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userConfig.js","sourceRoot":"","sources":["../../src/config/userConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAM1C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,sBAAsB,EAAE,aAAa,CAAC,CAAC;AAEpE,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAe,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAe;IAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
async function bboxOrNull(page, selector) {
|
|
4
|
+
try {
|
|
5
|
+
const loc = page.locator(selector).first();
|
|
6
|
+
await loc.waitFor({ state: 'visible', timeout: 2_000 });
|
|
7
|
+
return await loc.boundingBox();
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function dumpAnnotations(page, ph) {
|
|
14
|
+
const rawPath = ph.saveTo;
|
|
15
|
+
const finalPath = rawPath.replace(/\.raw\.png$/, '.png');
|
|
16
|
+
const highlight = [];
|
|
17
|
+
for (const selector of ph.highlight ?? []) {
|
|
18
|
+
const bbox = await bboxOrNull(page, selector);
|
|
19
|
+
if (bbox)
|
|
20
|
+
highlight.push({ selector, bbox });
|
|
21
|
+
}
|
|
22
|
+
const annotations = [];
|
|
23
|
+
for (const ann of ph.annotations ?? []) {
|
|
24
|
+
const bbox = await bboxOrNull(page, ann.target);
|
|
25
|
+
if (bbox)
|
|
26
|
+
annotations.push({ label: ann.label, text: ann.text, selector: ann.target, bbox });
|
|
27
|
+
}
|
|
28
|
+
const redact = [];
|
|
29
|
+
for (const selector of ph.redact ?? []) {
|
|
30
|
+
const bbox = await bboxOrNull(page, selector);
|
|
31
|
+
if (bbox)
|
|
32
|
+
redact.push({ selector, bbox });
|
|
33
|
+
}
|
|
34
|
+
const resolved = { id: ph.id, rawPath, finalPath, highlight, annotations, redact };
|
|
35
|
+
const jsonPath = rawPath.replace(/\.raw\.png$/, '.annotations.json');
|
|
36
|
+
mkdirSync(dirname(jsonPath), { recursive: true });
|
|
37
|
+
writeFileSync(jsonPath, JSON.stringify(resolved, null, 2), 'utf8');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=dumpAnnotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dumpAnnotations.js","sourceRoot":"","sources":["../../src/helpers/dumpAnnotations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,KAAK,UAAU,UAAU,CAAC,IAAU,EAAE,QAAgB;IACpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3C,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,OAAO,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,EAAe;IAC/D,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;IAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAEzD,MAAM,SAAS,GAAqC,EAAE,CAAC;IACvD,KAAK,MAAM,QAAQ,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9C,IAAI,IAAI;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,WAAW,GAAuC,EAAE,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,IAAI;YAAE,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,MAAM,GAAkC,EAAE,CAAC;IACjD,KAAK,MAAM,QAAQ,IAAI,EAAE,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9C,IAAI,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,QAAQ,GAAwB,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IACxG,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;IACrE,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type Bbox = {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
};
|
|
7
|
+
export type Annotation = {
|
|
8
|
+
target: string;
|
|
9
|
+
label: string;
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
export type Placeholder = {
|
|
13
|
+
id: string;
|
|
14
|
+
saveTo: string;
|
|
15
|
+
highlight?: string[];
|
|
16
|
+
annotations?: Annotation[];
|
|
17
|
+
redact?: string[];
|
|
18
|
+
};
|
|
19
|
+
export type ResolvedAnnotations = {
|
|
20
|
+
id: string;
|
|
21
|
+
rawPath: string;
|
|
22
|
+
finalPath: string;
|
|
23
|
+
highlight: {
|
|
24
|
+
selector: string;
|
|
25
|
+
bbox: Bbox;
|
|
26
|
+
}[];
|
|
27
|
+
annotations: {
|
|
28
|
+
label: string;
|
|
29
|
+
text: string;
|
|
30
|
+
selector: string;
|
|
31
|
+
bbox: Bbox;
|
|
32
|
+
}[];
|
|
33
|
+
redact: {
|
|
34
|
+
selector: string;
|
|
35
|
+
bbox: Bbox;
|
|
36
|
+
}[];
|
|
37
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/helpers/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export async function waitPastLogin(page, pattern, timeoutMs = 0) {
|
|
2
|
+
if (pattern.test(page.url()))
|
|
3
|
+
return;
|
|
4
|
+
const effective = timeoutMs > 0 ? timeoutMs : 600_000;
|
|
5
|
+
await page.waitForURL(pattern, { timeout: effective });
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=waitPastLogin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waitPastLogin.js","sourceRoot":"","sources":["../../src/helpers/waitPastLogin.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAU,EACV,OAAe,EACf,YAAoB,CAAC;IAErB,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,OAAO;IACrC,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IACtD,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;AACzD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function looksLikeSessionExpiry(output: string): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const LOGIN_REDIRECT_PATTERNS = [
|
|
2
|
+
/login\.microsoftonline\.com/i,
|
|
3
|
+
/login\.live\.com/i,
|
|
4
|
+
/accounts\.google\.com/i,
|
|
5
|
+
/\/oauth(2)?\/authorize/i,
|
|
6
|
+
/\/sign[- ]?in/i,
|
|
7
|
+
/\bauthn\b/i,
|
|
8
|
+
];
|
|
9
|
+
const EXPIRY_HINT_PATTERNS = [
|
|
10
|
+
/waitForURL.*timed?[- ]?out/i,
|
|
11
|
+
/page\.goto.*redirected/i,
|
|
12
|
+
/storageState.*invalid/i,
|
|
13
|
+
];
|
|
14
|
+
export function looksLikeSessionExpiry(output) {
|
|
15
|
+
if (LOGIN_REDIRECT_PATTERNS.some(p => p.test(output)))
|
|
16
|
+
return true;
|
|
17
|
+
return EXPIRY_HINT_PATTERNS.some(p => p.test(output));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=expiryDetect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiryDetect.js","sourceRoot":"","sources":["../../src/runner/expiryDetect.ts"],"names":[],"mappings":"AAAA,MAAM,uBAAuB,GAAG;IAC9B,8BAA8B;IAC9B,mBAAmB;IACnB,wBAAwB;IACxB,yBAAyB;IACzB,gBAAgB;IAChB,YAAY;CACb,CAAC;AAEF,MAAM,oBAAoB,GAAG;IAC3B,6BAA6B;IAC7B,yBAAyB;IACzB,wBAAwB;CACzB,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ProjectConfig } from '../config/projectConfig.js';
|
|
2
|
+
export type RuntimeConfigArgs = {
|
|
3
|
+
cwd: string;
|
|
4
|
+
cfg: ProjectConfig;
|
|
5
|
+
envName: string;
|
|
6
|
+
storageStatePath: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function writeRuntimePlaywrightConfig(args: RuntimeConfigArgs): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join, isAbsolute, resolve } from 'node:path';
|
|
3
|
+
export function writeRuntimePlaywrightConfig(args) {
|
|
4
|
+
const { cwd, cfg, envName, storageStatePath } = args;
|
|
5
|
+
const cacheDir = join(cwd, '.d360-capture-cache');
|
|
6
|
+
if (!existsSync(cacheDir))
|
|
7
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
8
|
+
const path = join(cacheDir, `playwright.${envName}.config.cjs`);
|
|
9
|
+
const captureDirAbs = isAbsolute(cfg.captureDir) ? cfg.captureDir : resolve(cwd, cfg.captureDir);
|
|
10
|
+
const storageAbs = isAbsolute(storageStatePath) ? storageStatePath : resolve(cwd, storageStatePath);
|
|
11
|
+
const body = `// Generated by document360-capture — do not edit by hand.
|
|
12
|
+
const { defineConfig } = require('@playwright/test');
|
|
13
|
+
module.exports = defineConfig({
|
|
14
|
+
testDir: ${JSON.stringify(captureDirAbs)},
|
|
15
|
+
testMatch: '**/*.spec.ts',
|
|
16
|
+
fullyParallel: false,
|
|
17
|
+
workers: 1,
|
|
18
|
+
retries: 0,
|
|
19
|
+
reporter: [['list']],
|
|
20
|
+
use: {
|
|
21
|
+
headless: false,
|
|
22
|
+
viewport: ${JSON.stringify(cfg.viewport)},
|
|
23
|
+
storageState: ${JSON.stringify(storageAbs)},
|
|
24
|
+
actionTimeout: 15000,
|
|
25
|
+
navigationTimeout: 30000,
|
|
26
|
+
contextOptions: { reducedMotion: 'reduce' },
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
`;
|
|
30
|
+
writeFileSync(path, body, 'utf8');
|
|
31
|
+
return path;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=playwrightConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwrightConfig.js","sourceRoot":"","sources":["../../src/runner/playwrightConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUtD,MAAM,UAAU,4BAA4B,CAAC,IAAuB;IAClE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,OAAO,aAAa,CAAC,CAAC;IAEhE,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACjG,MAAM,UAAU,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAEpG,MAAM,IAAI,GAAG;;;aAGF,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC;;;;;;;;gBAQ1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;oBACxB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;;;;;;CAM7C,CAAC;IAEA,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type RunSpecsArgs = {
|
|
2
|
+
cwd: string;
|
|
3
|
+
configPath: string;
|
|
4
|
+
startUrl: string;
|
|
5
|
+
authBoundaryUrlPattern: string;
|
|
6
|
+
specId?: string;
|
|
7
|
+
captureDirAbs: string;
|
|
8
|
+
};
|
|
9
|
+
export type RunSpecsResult = {
|
|
10
|
+
exitCode: number;
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function runSpecs(args: RunSpecsArgs): Promise<RunSpecsResult>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
export async function runSpecs(args) {
|
|
6
|
+
const { cwd, configPath, startUrl, authBoundaryUrlPattern, specId, captureDirAbs } = args;
|
|
7
|
+
const cliPath = resolvePlaywrightCli();
|
|
8
|
+
if (!cliPath) {
|
|
9
|
+
return {
|
|
10
|
+
exitCode: 127,
|
|
11
|
+
stdout: '',
|
|
12
|
+
stderr: 'Cannot locate @playwright/test CLI. Try: npm install -g document360-capture (reinstall)',
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const cliArgs = [cliPath, 'test', '--config', configPath];
|
|
16
|
+
if (specId)
|
|
17
|
+
cliArgs.push(join(captureDirAbs, `${specId}.spec.ts`));
|
|
18
|
+
return new Promise(resolve => {
|
|
19
|
+
let stdout = '';
|
|
20
|
+
let stderr = '';
|
|
21
|
+
const child = spawn(process.execPath, cliArgs, {
|
|
22
|
+
cwd,
|
|
23
|
+
env: {
|
|
24
|
+
...process.env,
|
|
25
|
+
CAPTURE_START_URL: startUrl,
|
|
26
|
+
CAPTURE_AUTH_BOUNDARY: authBoundaryUrlPattern,
|
|
27
|
+
},
|
|
28
|
+
shell: false,
|
|
29
|
+
});
|
|
30
|
+
child.stdout.on('data', (chunk) => {
|
|
31
|
+
const s = chunk.toString();
|
|
32
|
+
stdout += s;
|
|
33
|
+
process.stdout.write(s);
|
|
34
|
+
});
|
|
35
|
+
child.stderr.on('data', (chunk) => {
|
|
36
|
+
const s = chunk.toString();
|
|
37
|
+
stderr += s;
|
|
38
|
+
process.stderr.write(s);
|
|
39
|
+
});
|
|
40
|
+
child.on('error', err => {
|
|
41
|
+
stderr += `\n[spawn error] ${err.message}`;
|
|
42
|
+
resolve({ exitCode: 127, stdout, stderr });
|
|
43
|
+
});
|
|
44
|
+
child.on('close', code => {
|
|
45
|
+
resolve({ exitCode: code ?? 1, stdout, stderr });
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function resolvePlaywrightCli() {
|
|
50
|
+
try {
|
|
51
|
+
return require.resolve('@playwright/test/cli.js');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
try {
|
|
55
|
+
return require.resolve('playwright/cli.js');
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=runSpecs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runSpecs.js","sourceRoot":"","sources":["../../src/runner/runSpecs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAiBjC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAkB;IAC/C,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAC1F,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,yFAAyF;SAClG,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IAC1D,IAAI,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,MAAM,UAAU,CAAC,CAAC,CAAC;IAEnE,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE;YAC7C,GAAG;YACH,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,iBAAiB,EAAE,QAAQ;gBAC3B,qBAAqB,EAAE,sBAAsB;aAC9C;YACD,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;QAEH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;YACtB,MAAM,IAAI,mBAAmB,GAAG,CAAC,OAAO,EAAE,CAAC;YAC3C,OAAO,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;YACvB,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,oBAAoB;IAC3B,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|