• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

marekdedic / rollup-plugin-htaccess / 9420583740

07 Jun 2024 05:03PM UTC coverage: 22.449%. First build
9420583740

Pull #2

github

marekdedic
Added automatic spec testing
Pull Request #2: Added test configuration

6 of 77 branches covered (7.79%)

2 of 7 new or added lines in 6 files covered. (28.57%)

22 of 98 relevant lines covered (22.45%)

6.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

38.46
/src/headers.ts
1
import {
2
  buildContentSecurityPolicyValue,
3
  type ContentSecurityPolicySpec,
4
} from "./headers/ContentSecurityPolicy";
5
import {
6
  buildPermissionsPolicyValue,
7
  type PermissionsPolicySpec,
8
} from "./headers/PermissionsPolicy";
9
import {
10
  buildReferrerPolicyValue,
11
  type ReferrerPolicySpec,
12
} from "./headers/ReferrerPolicy";
13
import {
14
  buildStrictTransportSecurityValue,
15
  type StrictTransportSecuritySpec,
16
} from "./headers/StrictTransportSecurity";
17
import {
18
  buildXContentTypeOptionsValue,
19
  type XContentTypeOptionsSpec,
20
} from "./headers/XContentTypeOptions";
21
import {
22
  buildXFrameOptionsValue,
23
  type XFrameOptionsSpec,
24
} from "./headers/XFrameOptions";
25
import {
26
  buildXXssProtectionValue,
27
  type XXssProtectionSpec,
28
} from "./headers/XXssProtection";
29
import { escapeValue } from "./utils";
30

31
/* eslint-disable @typescript-eslint/naming-convention -- These are header names */
32
interface HeaderValueSpecMap {
33
  "Content-Security-Policy": ContentSecurityPolicySpec;
34
  "Permissions-Policy": PermissionsPolicySpec;
35
  "Referrer-Policy": ReferrerPolicySpec;
36
  "Strict-Transport-Security": StrictTransportSecuritySpec;
37
  "X-Content-Type-Options": XContentTypeOptionsSpec;
38
  "X-Frame-Options": XFrameOptionsSpec;
39
  "X-Xss-Protection": XXssProtectionSpec;
40
}
41
/* eslint-enable */
42

43
type HeaderSpec<T extends keyof HeaderValueSpecMap> = {
44
  header: T;
45
  always?: boolean;
46
  condition?:
47
    | {
48
        envVar: string;
49
        requireUnset?: boolean;
50
      }
51
    | {
52
        expression: string;
53
      };
54
} & (
55
  | {
56
      action: "add" | "append" | "merge" | "set" | "setifempty";
57
      value: HeaderValueSpecMap[T];
58
    }
59
  | {
60
      action: "echo" | "note" | "unset";
61
    }
62
  | {
63
      action: "edit" | "edit*";
64
      value: string;
65
      replacement: string;
66
    }
67
);
68

69
export type HeaderSpecUnion = {
70
  [K in keyof HeaderValueSpecMap]: HeaderSpec<K>;
71
}[keyof HeaderValueSpecMap];
72

73
function buildHeaderValue<
74
  T extends keyof HeaderValueSpecMap,
75
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Needed to correctly infer value type
76
  V extends HeaderValueSpecMap[T] & Record<T, any>,
77
>(header: T, value: V[T]): string {
78
  if (header === "Referrer-Policy") {
12!
79
    return buildReferrerPolicyValue(value);
×
80
  }
81
  switch (header) {
12!
82
    case "Content-Security-Policy":
83
      return buildContentSecurityPolicyValue(value);
×
84
    case "Permissions-Policy":
85
      return buildPermissionsPolicyValue(value);
×
86
    case "Referrer-Policy":
87
      return buildReferrerPolicyValue(value);
×
88
    case "Strict-Transport-Security":
89
      return buildStrictTransportSecurityValue(value);
×
90
    case "X-Content-Type-Options":
91
      return buildXContentTypeOptionsValue();
12✔
92
    case "X-Frame-Options":
93
      return buildXFrameOptionsValue(value);
×
94
    case "X-Xss-Protection":
95
      return buildXXssProtectionValue(value);
×
96
  }
97
  throw new Error('Unknown header type "' + header + '".');
×
98
}
99

100
export function buildHeader(spec: HeaderSpecUnion): string {
101
  const parts = ["Header"];
12✔
102
  if (spec.always === true) {
12!
103
    parts.push("always");
×
104
  }
105
  parts.push(spec.action, spec.header);
12✔
106
  if (["add", "append", "merge", "set", "setifempty"].includes(spec.action)) {
12!
107
    parts.push(
12✔
108
      buildHeaderValue(
109
        spec.header,
110
        (spec as { value: HeaderValueSpecMap[keyof HeaderValueSpecMap] }).value,
111
      ),
112
    );
113
  } else if (["edit", "edit*"].includes(spec.action)) {
×
NEW
114
    parts.push('"' + escapeValue((spec as { value: string }).value) + '"');
×
115
    parts.push(
×
116
      '"' + escapeValue((spec as { replacement: string }).replacement) + '"',
117
    );
118
  }
119
  if (spec.condition !== undefined) {
12!
120
    if ("envVar" in spec.condition) {
×
121
      parts.push(
×
122
        "env=" +
123
          (spec.condition.requireUnset === true ? "!" : "") +
×
124
          spec.condition.envVar,
125
      );
126
    } else if ("expression" in spec.condition) {
×
127
      parts.push("expr=" + spec.condition.expression);
×
128
    }
129
  }
130
  return parts.join(" ");
12✔
131
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc