@hasna/testers 0.0.13 → 0.0.14
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/dist/cli/index.js +823 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/scan-issues.d.ts +29 -0
- package/dist/db/scan-issues.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/lib/health-scan.d.ts +22 -0
- package/dist/lib/health-scan.d.ts.map +1 -0
- package/dist/lib/scanners/console.d.ts +12 -0
- package/dist/lib/scanners/console.d.ts.map +1 -0
- package/dist/lib/scanners/links.d.ts +12 -0
- package/dist/lib/scanners/links.d.ts.map +1 -0
- package/dist/lib/scanners/network.d.ts +15 -0
- package/dist/lib/scanners/network.d.ts.map +1 -0
- package/dist/lib/scanners/performance.d.ts +19 -0
- package/dist/lib/scanners/performance.d.ts.map +1 -0
- package/dist/mcp/index.js +1243 -435
- package/dist/server/index.js +23 -0
- package/dist/types/index.d.ts +54 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,iBAAS,GAAG,IAAI,MAAM,CAErB;AAED,iBAAS,IAAI,IAAI,MAAM,CAEtB;AAED,iBAAS,SAAS,IAAI,MAAM,CAE3B;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAOtC,iBAAS,GAAG,IAAI,MAAM,CAErB;AAED,iBAAS,IAAI,IAAI,MAAM,CAEtB;AAED,iBAAS,SAAS,IAAI,MAAM,CAE3B;AAiRD,wBAAgB,WAAW,IAAI,QAAQ,CAwBtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAgBpC;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAOf;AAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type PersistedScanIssue, type ScanIssue } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Derive a stable fingerprint from an issue.
|
|
4
|
+
* Normalises the page URL to its pathname (ignores query/fragment) so the same
|
|
5
|
+
* error on foo.com/page?x=1 and foo.com/page?x=2 is treated as the same issue.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fingerprintIssue(issue: ScanIssue): string;
|
|
8
|
+
export type UpsertOutcome = "new" | "existing" | "regressed";
|
|
9
|
+
export interface UpsertResult {
|
|
10
|
+
issue: PersistedScanIssue;
|
|
11
|
+
outcome: UpsertOutcome;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Upsert a scan issue by fingerprint:
|
|
15
|
+
* - New (never seen): insert with status=open
|
|
16
|
+
* - Known open: bump occurrence_count + last_seen_at
|
|
17
|
+
* - Known resolved: mark as regressed (status=regressed, increment count)
|
|
18
|
+
*/
|
|
19
|
+
export declare function upsertScanIssue(issue: ScanIssue, projectId?: string): UpsertResult;
|
|
20
|
+
export declare function resolveScanIssue(id: string): boolean;
|
|
21
|
+
export declare function setScanIssueTodoTaskId(id: string, todoTaskId: string): void;
|
|
22
|
+
export declare function listScanIssues(opts?: {
|
|
23
|
+
status?: string;
|
|
24
|
+
type?: string;
|
|
25
|
+
projectId?: string;
|
|
26
|
+
limit?: number;
|
|
27
|
+
}): PersistedScanIssue[];
|
|
28
|
+
export declare function getScanIssue(id: string): PersistedScanIssue | null;
|
|
29
|
+
//# sourceMappingURL=scan-issues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-issues.d.ts","sourceRoot":"","sources":["../../src/db/scan-issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,SAAS,EAAuC,MAAM,mBAAmB,CAAC;AAKjH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAezD;AAID,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,YAAY,CAoDd;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAMpD;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAG3E;AAED,wBAAgB,cAAc,CAAC,IAAI,GAAE;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,GAAG,kBAAkB,EAAE,CAc5B;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAIlE"}
|
package/dist/index.js
CHANGED
|
@@ -299,6 +299,7 @@ function resetDatabase() {
|
|
|
299
299
|
database.exec("DELETE FROM runs");
|
|
300
300
|
database.exec("DELETE FROM scenarios");
|
|
301
301
|
database.exec("DELETE FROM agents");
|
|
302
|
+
database.exec("DELETE FROM scan_issues");
|
|
302
303
|
database.exec("DELETE FROM projects");
|
|
303
304
|
}
|
|
304
305
|
function resolvePartialId(table, partialId) {
|
|
@@ -506,6 +507,29 @@ var init_database = __esm(() => {
|
|
|
506
507
|
`,
|
|
507
508
|
`
|
|
508
509
|
ALTER TABLE runs ADD COLUMN is_baseline INTEGER NOT NULL DEFAULT 0;
|
|
510
|
+
`,
|
|
511
|
+
`
|
|
512
|
+
CREATE TABLE IF NOT EXISTS scan_issues (
|
|
513
|
+
id TEXT PRIMARY KEY,
|
|
514
|
+
fingerprint TEXT NOT NULL UNIQUE,
|
|
515
|
+
type TEXT NOT NULL,
|
|
516
|
+
severity TEXT NOT NULL DEFAULT 'medium',
|
|
517
|
+
page_url TEXT NOT NULL,
|
|
518
|
+
message TEXT NOT NULL,
|
|
519
|
+
detail TEXT,
|
|
520
|
+
status TEXT NOT NULL DEFAULT 'open',
|
|
521
|
+
occurrence_count INTEGER NOT NULL DEFAULT 1,
|
|
522
|
+
first_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
523
|
+
last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
524
|
+
resolved_at TEXT,
|
|
525
|
+
todo_task_id TEXT,
|
|
526
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
CREATE INDEX IF NOT EXISTS idx_scan_issues_fingerprint ON scan_issues(fingerprint);
|
|
530
|
+
CREATE INDEX IF NOT EXISTS idx_scan_issues_status ON scan_issues(status);
|
|
531
|
+
CREATE INDEX IF NOT EXISTS idx_scan_issues_type ON scan_issues(type);
|
|
532
|
+
CREATE INDEX IF NOT EXISTS idx_scan_issues_project ON scan_issues(project_id);
|
|
509
533
|
`
|
|
510
534
|
];
|
|
511
535
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ScanResult } from "../types/index.js";
|
|
2
|
+
export interface HealthScanOptions {
|
|
3
|
+
url: string;
|
|
4
|
+
pages?: string[];
|
|
5
|
+
projectId?: string;
|
|
6
|
+
headed?: boolean;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
scanners?: ("console" | "network" | "links" | "performance")[];
|
|
9
|
+
maxPages?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface HealthScanSummary {
|
|
12
|
+
url: string;
|
|
13
|
+
scannedAt: string;
|
|
14
|
+
durationMs: number;
|
|
15
|
+
totalIssues: number;
|
|
16
|
+
newIssues: number;
|
|
17
|
+
regressedIssues: number;
|
|
18
|
+
existingIssues: number;
|
|
19
|
+
results: ScanResult[];
|
|
20
|
+
}
|
|
21
|
+
export declare function runHealthScan(options: HealthScanOptions): Promise<HealthScanSummary>;
|
|
22
|
+
//# sourceMappingURL=health-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-scan.d.ts","sourceRoot":"","sources":["../../src/lib/health-scan.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AAI/D,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC,EAAE,CAAC;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAID,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0D1F"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ScanResult } from "../../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Visit each page and collect JS/React/unhandled errors from the browser console.
|
|
4
|
+
* Captures: console.error(), uncaught exceptions, unhandled promise rejections.
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanConsoleErrors(options: {
|
|
7
|
+
url: string;
|
|
8
|
+
pages?: string[];
|
|
9
|
+
headed?: boolean;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}): Promise<ScanResult>;
|
|
12
|
+
//# sourceMappingURL=console.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../../src/lib/scanners/console.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAQlE;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,UAAU,CAAC,CAqEtB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ScanResult } from "../../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Crawl the app starting from rootUrl, follow all internal links,
|
|
4
|
+
* and flag any that return 404 or redirect loops.
|
|
5
|
+
*/
|
|
6
|
+
export declare function scanBrokenLinks(options: {
|
|
7
|
+
url: string;
|
|
8
|
+
maxPages?: number;
|
|
9
|
+
headed?: boolean;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}): Promise<ScanResult>;
|
|
12
|
+
//# sourceMappingURL=links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/lib/scanners/links.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElE;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,UAAU,CAAC,CA0FtB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ScanResult } from "../../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Visit each page and intercept network requests, flagging:
|
|
4
|
+
* - HTTP 5xx (server errors)
|
|
5
|
+
* - HTTP 4xx on API routes
|
|
6
|
+
* - CORS errors
|
|
7
|
+
* - Request failures (net::ERR_*)
|
|
8
|
+
*/
|
|
9
|
+
export declare function scanNetworkErrors(options: {
|
|
10
|
+
url: string;
|
|
11
|
+
pages?: string[];
|
|
12
|
+
headed?: boolean;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}): Promise<ScanResult>;
|
|
15
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../../src/lib/scanners/network.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAWlE;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,UAAU,CAAC,CA0EtB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ScanResult } from "../../types/index.js";
|
|
2
|
+
interface PerfThresholds {
|
|
3
|
+
loadTimeMs: number;
|
|
4
|
+
domContentLoadedMs: number;
|
|
5
|
+
lcpMs: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Visit each page and collect Web Performance API metrics.
|
|
9
|
+
* Flags pages that exceed configurable thresholds.
|
|
10
|
+
*/
|
|
11
|
+
export declare function scanPerformance(options: {
|
|
12
|
+
url: string;
|
|
13
|
+
pages?: string[];
|
|
14
|
+
headed?: boolean;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
thresholds?: Partial<PerfThresholds>;
|
|
17
|
+
}): Promise<ScanResult>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=performance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../../src/lib/scanners/performance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAYlE,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAQD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACtC,GAAG,OAAO,CAAC,UAAU,CAAC,CA2GtB"}
|