Skip to content

Commit 42d0a6f

Browse files
committed
feat(utils): Introduce Baggage API
1 parent f715933 commit 42d0a6f

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

packages/utils/src/baggage.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
export type AllowedBaggageKeys = 'environment' | 'release'; // TODO: Add remaining allowed baggage keys | 'transaction' | 'userid' | 'usersegment';
2+
export type Baggage = Partial<Record<AllowedBaggageKeys, string> & Record<string, string>>;
3+
4+
export const BAGGAGE_HEADER_NAME = 'baggage';
5+
6+
/**
7+
* Max length of a serialized baggage string
8+
*
9+
* https://www.w3.org/TR/baggage/#limits
10+
*/
11+
export const MAX_BAGGAGE_STRING_LENGTH = 8192;
12+
13+
/** Create an instance of Baggage */
14+
export function createBaggage(initItems: Baggage): Baggage {
15+
return { ...initItems };
16+
}
17+
18+
/** Add a value to baggage */
19+
export function getBaggageValue(baggage: Baggage, key: keyof Baggage): Baggage[keyof Baggage] {
20+
return baggage[key];
21+
}
22+
23+
/** Add a value to baggage */
24+
export function setBaggageValue(baggage: Baggage, key: keyof Baggage, value: Baggage[keyof Baggage]): void {
25+
baggage[key] = value;
26+
}
27+
28+
/** remove a value from baggage */
29+
// TODO: Is this even useful?
30+
// export function removeBaggageValue(baggage: Baggage, key: keyof Baggage): void {
31+
// // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
32+
// delete baggage[key];
33+
// }
34+
35+
/** Serialize a baggage object */
36+
export function serializeBaggage(baggage: Baggage): string {
37+
return Object.keys(baggage).reduce((prev, key) => {
38+
const newVal = `${prev};${key}=${baggage[key as keyof Baggage]}`;
39+
return newVal.length > MAX_BAGGAGE_STRING_LENGTH ? prev : newVal;
40+
}, '');
41+
}
42+
43+
/** Parse a baggage header to a string */
44+
export function parseBaggageString(baggageString: string): Baggage {
45+
// TODO: Should we check validity with regex? How much should we check for malformed baggage keys?
46+
// Perhaps we shouldn't worry about this being used in the frontend, so bundle size isn't that much of a concern
47+
return baggageString.split(';').reduce((prevBaggage, curr) => {
48+
const [key, val] = curr.split('=');
49+
return {
50+
...prevBaggage,
51+
[key]: val,
52+
};
53+
}, {} as Baggage);
54+
}

packages/utils/test/baggage.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { createBaggage, getBaggageValue } from '../src/baggage';
2+
3+
describe('Baggage', () => {
4+
describe('createBaggage', () => {
5+
it.each([
6+
['creates an empty baggage instance', {}, {}],
7+
[
8+
'creates a baggage instance with initial values',
9+
{ environment: 'production', anyKey: 'anyValue' },
10+
{ environment: 'production', anyKey: 'anyValue' },
11+
],
12+
])('%s', (_: string, input, output) => {
13+
expect(createBaggage(input)).toEqual(output);
14+
});
15+
});
16+
17+
describe('getBaggageValue', () => {
18+
it.each([
19+
['gets a baggage item', { environment: 'production', anyKey: 'anyValue' }, 'environment', 'production'],
20+
['finds undefined items', {}, 'environment', undefined],
21+
])('%s', (_: string, baggage, key, value) => {
22+
expect(getBaggageValue(baggage, key)).toEqual(value);
23+
});
24+
});
25+
});

0 commit comments

Comments
 (0)