ssrwire 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/CHANGELOG.md +20 -0
- package/CONTRIBUTING.md +49 -0
- package/LICENSE +21 -0
- package/PUBLISHING.md +134 -0
- package/README.md +403 -0
- package/SECURITY.md +26 -0
- package/dist/agents.d.ts +14 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +100 -0
- package/dist/agents.js.map +1 -0
- package/dist/analyze.d.ts +4 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +494 -0
- package/dist/analyze.js.map +1 -0
- package/dist/audit.d.ts +3 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +69 -0
- package/dist/audit.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +4 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +262 -0
- package/dist/config.js.map +1 -0
- package/dist/http-probe.d.ts +7 -0
- package/dist/http-probe.d.ts.map +1 -0
- package/dist/http-probe.js +406 -0
- package/dist/http-probe.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/redact.d.ts +10 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +154 -0
- package/dist/redact.js.map +1 -0
- package/dist/reporters.d.ts +9 -0
- package/dist/reporters.d.ts.map +1 -0
- package/dist/reporters.js +220 -0
- package/dist/reporters.js.map +1 -0
- package/dist/stream-parser.d.ts +9 -0
- package/dist/stream-parser.d.ts.map +1 -0
- package/dist/stream-parser.js +366 -0
- package/dist/stream-parser.js.map +1 -0
- package/dist/types.d.ts +134 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +14 -0
- package/dist/version.js.map +1 -0
- package/examples/github-actions.yml +73 -0
- package/examples/ssrwire.config.yml +37 -0
- package/package.json +91 -0
- package/src/agents.ts +129 -0
- package/src/analyze.ts +628 -0
- package/src/audit.ts +89 -0
- package/src/bin.ts +5 -0
- package/src/cli.ts +207 -0
- package/src/config.ts +313 -0
- package/src/http-probe.ts +461 -0
- package/src/index.ts +34 -0
- package/src/redact.ts +173 -0
- package/src/reporters.ts +274 -0
- package/src/stream-parser.ts +424 -0
- package/src/types.ts +160 -0
- package/src/version.ts +19 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
export type Severity = "info" | "warning" | "error";
|
|
2
|
+
|
|
3
|
+
export type ElementLocation = "head" | "body" | "document";
|
|
4
|
+
|
|
5
|
+
export interface TimingMark {
|
|
6
|
+
readonly atMs: number;
|
|
7
|
+
readonly observedByByte: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ElementSignal extends TimingMark {
|
|
11
|
+
readonly value: string;
|
|
12
|
+
readonly location: ElementLocation;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type RobotsAudience = "robots" | "googlebot" | "bingbot";
|
|
16
|
+
|
|
17
|
+
export interface RobotsSignal extends ElementSignal {
|
|
18
|
+
readonly audience: RobotsAudience;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface JsonLdSignal extends TimingMark {
|
|
22
|
+
readonly location: ElementLocation;
|
|
23
|
+
readonly valid?: boolean;
|
|
24
|
+
readonly types: readonly string[];
|
|
25
|
+
readonly bytes: number;
|
|
26
|
+
readonly analysisLimit?: string;
|
|
27
|
+
readonly error?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DocumentSignals {
|
|
31
|
+
readonly title?: ElementSignal;
|
|
32
|
+
readonly titles?: readonly ElementSignal[];
|
|
33
|
+
readonly descriptions: readonly ElementSignal[];
|
|
34
|
+
readonly canonicals: readonly ElementSignal[];
|
|
35
|
+
readonly robots: readonly RobotsSignal[];
|
|
36
|
+
readonly h1s: readonly ElementSignal[];
|
|
37
|
+
readonly firstMainText?: ElementSignal;
|
|
38
|
+
readonly jsonLd: readonly JsonLdSignal[];
|
|
39
|
+
readonly headClosed?: TimingMark;
|
|
40
|
+
readonly bodyStarted?: TimingMark;
|
|
41
|
+
readonly documentClosed?: TimingMark;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface AgentProfile {
|
|
45
|
+
readonly key: string;
|
|
46
|
+
readonly label: string;
|
|
47
|
+
readonly userAgent: string;
|
|
48
|
+
readonly requiresHeadMetadata: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface RedirectHop {
|
|
52
|
+
readonly url: string;
|
|
53
|
+
readonly status: number;
|
|
54
|
+
readonly location: string;
|
|
55
|
+
readonly durationMs: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface HeaderSnapshot {
|
|
59
|
+
readonly values: Readonly<Record<string, string>>;
|
|
60
|
+
readonly setCookiePresent: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface ProbeTimings {
|
|
64
|
+
readonly headersMs: number;
|
|
65
|
+
readonly firstByteMs?: number;
|
|
66
|
+
readonly completeMs?: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type ProbeCompletion =
|
|
70
|
+
| "complete"
|
|
71
|
+
| "max-bytes-exceeded"
|
|
72
|
+
| "timeout"
|
|
73
|
+
| "network-error"
|
|
74
|
+
| "invalid-response";
|
|
75
|
+
|
|
76
|
+
export interface ProbeOptions {
|
|
77
|
+
readonly url: string;
|
|
78
|
+
readonly agent: AgentProfile;
|
|
79
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
80
|
+
readonly timeoutMs: number;
|
|
81
|
+
readonly maxBytes: number;
|
|
82
|
+
readonly maxRedirects: number;
|
|
83
|
+
/** Keep reflected header values internal so callers can analyze raw evidence before redaction. */
|
|
84
|
+
readonly redactHeaderValues?: boolean;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ProbeResult {
|
|
88
|
+
readonly requestedUrl: string;
|
|
89
|
+
readonly finalUrl: string;
|
|
90
|
+
readonly agent: AgentProfile;
|
|
91
|
+
readonly status?: number;
|
|
92
|
+
readonly redirects: readonly RedirectHop[];
|
|
93
|
+
readonly headers: HeaderSnapshot;
|
|
94
|
+
readonly timings: ProbeTimings;
|
|
95
|
+
readonly bytesRead: number;
|
|
96
|
+
readonly bodySha256?: string;
|
|
97
|
+
readonly signals: DocumentSignals;
|
|
98
|
+
readonly completion: ProbeCompletion;
|
|
99
|
+
readonly error?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface TargetExpectations {
|
|
103
|
+
readonly statuses: readonly number[];
|
|
104
|
+
readonly finalUrl?: string;
|
|
105
|
+
readonly requireTitle: boolean;
|
|
106
|
+
readonly requireDescription: boolean;
|
|
107
|
+
readonly requireCanonical: boolean;
|
|
108
|
+
readonly requireH1: boolean;
|
|
109
|
+
readonly requireMainText: boolean;
|
|
110
|
+
readonly maxFirstByteMs?: number;
|
|
111
|
+
readonly maxCriticalMs?: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface AuditTarget {
|
|
115
|
+
readonly url: string;
|
|
116
|
+
readonly expectations: TargetExpectations;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface SsrWireConfig {
|
|
120
|
+
readonly targets: readonly AuditTarget[];
|
|
121
|
+
readonly agents: readonly AgentProfile[];
|
|
122
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
123
|
+
readonly timeoutMs: number;
|
|
124
|
+
readonly maxBytes: number;
|
|
125
|
+
readonly maxRedirects: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface Finding {
|
|
129
|
+
readonly code: string;
|
|
130
|
+
readonly severity: Severity;
|
|
131
|
+
readonly message: string;
|
|
132
|
+
readonly url: string;
|
|
133
|
+
readonly agent?: string;
|
|
134
|
+
readonly evidence?: Readonly<Record<string, string | number | boolean>>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface TargetAuditResult {
|
|
138
|
+
readonly target: AuditTarget;
|
|
139
|
+
readonly probes: readonly ProbeResult[];
|
|
140
|
+
readonly findings: readonly Finding[];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface AuditSummary {
|
|
144
|
+
readonly targets: number;
|
|
145
|
+
readonly probes: number;
|
|
146
|
+
readonly errors: number;
|
|
147
|
+
readonly warnings: number;
|
|
148
|
+
readonly info: number;
|
|
149
|
+
readonly incomplete: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface AuditResult {
|
|
153
|
+
readonly version: string;
|
|
154
|
+
readonly generatedAt: string;
|
|
155
|
+
readonly durationMs: number;
|
|
156
|
+
readonly results: readonly TargetAuditResult[];
|
|
157
|
+
readonly summary: AuditSummary;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export type ReportFormat = "terminal" | "json" | "sarif";
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const packageJson: unknown = require("../package.json");
|
|
5
|
+
|
|
6
|
+
function readVersion(value: unknown): string {
|
|
7
|
+
if (
|
|
8
|
+
typeof value === "object" &&
|
|
9
|
+
value !== null &&
|
|
10
|
+
"version" in value &&
|
|
11
|
+
typeof value.version === "string"
|
|
12
|
+
) {
|
|
13
|
+
return value.version;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
throw new Error("SSRWire could not read its package version.");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const VERSION = readVersion(packageJson);
|