Skip to content

Commit 9be1d56

Browse files
authored
ref(core): Change customHeaders option to customHeader (#84)
Rename `customHeaders` to `customHeader` and change user-facing data type to string. This change aligns the option with the Sentry Webpack Plugin.
1 parent db04eb5 commit 9be1d56

File tree

5 files changed

+50
-29
lines changed

5 files changed

+50
-29
lines changed

packages/bundler-plugin-core/src/options-mapping.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ type RequiredInternalOptions = Required<
1212
| "finalize"
1313
| "validate"
1414
| "vcsRemote"
15-
| "customHeaders"
1615
| "dryRun"
1716
| "debug"
1817
| "silent"
@@ -28,6 +27,7 @@ type OptionalInternalOptions = Partial<
2827
type NormalizedInternalOptions = {
2928
entries: (string | RegExp)[] | ((filePath: string) => boolean) | undefined;
3029
include: InternalIncludeEntry[];
30+
customHeader: Record<string, string>;
3131
};
3232

3333
export type InternalOptions = RequiredInternalOptions &
@@ -85,7 +85,7 @@ export function normalizeUserOptions(userOptions: UserOptions): InternalOptions
8585
finalize: userOptions.finalize ?? true,
8686
validate: userOptions.validate ?? false,
8787
vcsRemote: userOptions.vcsRemote ?? "origin",
88-
customHeaders: userOptions.customHeaders ?? {},
88+
customHeader: normalizeCustomHeader(userOptions.customHeader),
8989
dryRun: userOptions.dryRun ?? false,
9090
debug: userOptions.debug ?? false,
9191
silent: userOptions.silent ?? false,
@@ -134,3 +134,13 @@ function normalizeIncludeEntry(
134134
rewrite: includeEntry.rewrite ?? userOptions.rewrite ?? true,
135135
};
136136
}
137+
138+
function normalizeCustomHeader(
139+
userCustomHeader: UserOptions["customHeader"]
140+
): InternalOptions["customHeader"] {
141+
if (!userCustomHeader || !userCustomHeader.includes(":")) {
142+
return {};
143+
}
144+
const [key, value] = userCustomHeader.split(/:(.*)/, 2).map((s) => s.trim()) as [string, string];
145+
return { [key]: value };
146+
}

packages/bundler-plugin-core/src/sentry/api.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { Hub } from "@sentry/node";
22
import axios from "axios";
33
import FormData from "form-data";
4-
import { Options } from "../types";
4+
import { InternalOptions } from "../options-mapping";
55
import { captureMinimalError } from "./telemetry";
66

77
const API_PATH = "api/0";
88
const USER_AGENT = `sentry-bundler-plugin/${__PACKAGE_VERSION__}`;
99

1010
const sentryApiAxiosInstance = ({
1111
authToken,
12-
customHeaders,
13-
}: Required<Pick<Options, "authToken">> & Pick<Options, "customHeaders">) =>
12+
customHeader,
13+
}: Required<Pick<InternalOptions, "authToken">> & Pick<InternalOptions, "customHeader">) =>
1414
axios.create({
15-
headers: { ...customHeaders, "User-Agent": USER_AGENT, Authorization: `Bearer ${authToken}` },
15+
headers: { ...customHeader, "User-Agent": USER_AGENT, Authorization: `Bearer ${authToken}` },
1616
});
1717

1818
export async function createRelease({
@@ -22,15 +22,15 @@ export async function createRelease({
2222
authToken,
2323
sentryUrl,
2424
sentryHub,
25-
customHeaders,
25+
customHeader,
2626
}: {
2727
release: string;
2828
project: string;
2929
org: string;
3030
authToken: string;
3131
sentryUrl: string;
3232
sentryHub: Hub;
33-
customHeaders?: Record<string, string>;
33+
customHeader: Record<string, string>;
3434
}): Promise<void> {
3535
const requestUrl = `${sentryUrl}${API_PATH}/organizations/${org}/releases/`;
3636

@@ -42,7 +42,7 @@ export async function createRelease({
4242
};
4343

4444
try {
45-
await sentryApiAxiosInstance({ authToken, customHeaders }).post(requestUrl, releasePayload, {
45+
await sentryApiAxiosInstance({ authToken, customHeader }).post(requestUrl, releasePayload, {
4646
headers: { Authorization: `Bearer ${authToken}` },
4747
});
4848
} catch (e) {
@@ -58,20 +58,20 @@ export async function deleteAllReleaseArtifacts({
5858
authToken,
5959
sentryUrl,
6060
sentryHub,
61-
customHeaders,
61+
customHeader,
6262
}: {
6363
org: string;
6464
release: string;
6565
sentryUrl: string;
6666
authToken: string;
6767
project: string;
6868
sentryHub: Hub;
69-
customHeaders?: Record<string, string>;
69+
customHeader: Record<string, string>;
7070
}): Promise<void> {
7171
const requestUrl = `${sentryUrl}${API_PATH}/projects/${org}/${project}/files/source-maps/?name=${release}`;
7272

7373
try {
74-
await sentryApiAxiosInstance({ authToken, customHeaders }).delete(requestUrl, {
74+
await sentryApiAxiosInstance({ authToken, customHeader }).delete(requestUrl, {
7575
headers: {
7676
Authorization: `Bearer ${authToken}`,
7777
},
@@ -89,15 +89,15 @@ export async function updateRelease({
8989
sentryUrl,
9090
project,
9191
sentryHub,
92-
customHeaders,
92+
customHeader,
9393
}: {
9494
release: string;
9595
org: string;
9696
authToken: string;
9797
sentryUrl: string;
9898
project: string;
9999
sentryHub: Hub;
100-
customHeaders?: Record<string, string>;
100+
customHeader: Record<string, string>;
101101
}): Promise<void> {
102102
const requestUrl = `${sentryUrl}${API_PATH}/projects/${org}/${project}/releases/${release}/`;
103103

@@ -106,7 +106,7 @@ export async function updateRelease({
106106
};
107107

108108
try {
109-
await sentryApiAxiosInstance({ authToken, customHeaders }).put(requestUrl, releasePayload, {
109+
await sentryApiAxiosInstance({ authToken, customHeader }).put(requestUrl, releasePayload, {
110110
headers: { Authorization: `Bearer ${authToken}` },
111111
});
112112
} catch (e) {
@@ -124,7 +124,7 @@ export async function uploadReleaseFile({
124124
filename,
125125
fileContent,
126126
sentryHub,
127-
customHeaders,
127+
customHeader,
128128
}: {
129129
org: string;
130130
release: string;
@@ -134,7 +134,7 @@ export async function uploadReleaseFile({
134134
filename: string;
135135
fileContent: string;
136136
sentryHub: Hub;
137-
customHeaders?: Record<string, string>;
137+
customHeader: Record<string, string>;
138138
}) {
139139
const requestUrl = `${sentryUrl}${API_PATH}/projects/${org}/${project}/releases/${release}/files/`;
140140

@@ -143,7 +143,7 @@ export async function uploadReleaseFile({
143143
form.append("file", Buffer.from(fileContent, "utf-8"), { filename });
144144

145145
try {
146-
await sentryApiAxiosInstance({ authToken, customHeaders }).post(requestUrl, form, {
146+
await sentryApiAxiosInstance({ authToken, customHeader }).post(requestUrl, form, {
147147
headers: {
148148
Authorization: `Bearer ${authToken}`,
149149
"Content-Type": "multipart/form-data",

packages/bundler-plugin-core/src/sentry/releasePipeline.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export async function createNewRelease(
4040
project: options.project,
4141
sentryUrl: options.url,
4242
sentryHub: ctx.hub,
43-
customHeaders: options.customHeaders,
43+
customHeader: options.customHeader,
4444
});
4545

4646
ctx.logger.info("Successfully created release.");
@@ -130,7 +130,7 @@ export async function uploadSourceMaps(
130130
filename: file.name,
131131
fileContent: file.content,
132132
sentryHub: ctx.hub,
133-
customHeaders: options.customHeaders,
133+
customHeader: options.customHeader,
134134
})
135135
)
136136
).then(() => {
@@ -160,7 +160,7 @@ export async function finalizeRelease(
160160
sentryUrl: url,
161161
project,
162162
sentryHub: ctx.hub,
163-
customHeaders: options.customHeaders,
163+
customHeader: options.customHeader,
164164
});
165165

166166
ctx.logger.info("Successfully finalized release.");
@@ -196,7 +196,7 @@ export async function cleanArtifacts(options: InternalOptions, ctx: BuildContext
196196
sentryUrl: options.url,
197197
project: options.project,
198198
sentryHub: ctx.hub,
199-
customHeaders: options.customHeaders,
199+
customHeader: options.customHeader,
200200
});
201201

202202
ctx.logger.info("Successfully cleaned previous artifacts.");

packages/bundler-plugin-core/src/types.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,8 @@ export type Options = Omit<IncludeEntry, "paths"> & {
107107
/**
108108
* A header added to every outgoing network request.
109109
* The format should be `header-key: header-value`.
110-
*
111-
* TODO: This is currently different from the webpack plugin. There, this property is
112-
* called `customHeader` and it only accepts one header as a string.
113-
* Change in follow-up PR.
114110
*/
115-
customHeaders?: Record<string, string>;
111+
customHeader?: string;
116112

117113
/**
118114
* Attempts a dry run (useful for dev environments).

packages/bundler-plugin-core/test/option-mappings.test.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe("normalizeUserOptions()", () => {
1414
expect(normalizeUserOptions(userOptions)).toEqual({
1515
authToken: "my-auth-token",
1616
cleanArtifacts: false,
17-
customHeaders: {},
17+
customHeader: {},
1818
debug: false,
1919
dryRun: false,
2020
finalize: true,
@@ -58,7 +58,7 @@ describe("normalizeUserOptions()", () => {
5858
expect(normalizeUserOptions(userOptions)).toEqual({
5959
authToken: "my-auth-token",
6060
cleanArtifacts: false,
61-
customHeaders: {},
61+
customHeader: {},
6262
debug: false,
6363
dryRun: false,
6464
finalize: true,
@@ -82,4 +82,19 @@ describe("normalizeUserOptions()", () => {
8282
vcsRemote: "origin",
8383
});
8484
});
85+
86+
test("should convert string customHeader to internal representation", () => {
87+
const userOptions: Options = {
88+
org: "my-org",
89+
project: "my-project",
90+
authToken: "my-auth-token",
91+
release: "my-release",
92+
include: "dist",
93+
customHeader: "customKey: CustomValue",
94+
};
95+
96+
expect(normalizeUserOptions(userOptions)).toEqual(
97+
expect.objectContaining({ customHeader: { customKey: "CustomValue" } })
98+
);
99+
});
85100
});

0 commit comments

Comments
 (0)