@squiz/dx-common-lib 1.72.3 → 1.72.4
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 +6 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/outbound-http/createServiceUserAgent.d.ts +6 -0
- package/lib/outbound-http/createServiceUserAgent.js +13 -0
- package/lib/outbound-http/createServiceUserAgent.js.map +1 -0
- package/lib/outbound-http/createServiceUserAgent.spec.d.ts +1 -0
- package/lib/outbound-http/createServiceUserAgent.spec.js +12 -0
- package/lib/outbound-http/createServiceUserAgent.spec.js.map +1 -0
- package/lib/outbound-http/index.d.ts +2 -0
- package/lib/outbound-http/index.js +8 -0
- package/lib/outbound-http/index.js.map +1 -0
- package/lib/outbound-http/outboundHttp.d.ts +2 -0
- package/lib/outbound-http/outboundHttp.js +23 -0
- package/lib/outbound-http/outboundHttp.js.map +1 -0
- package/lib/outbound-http/outboundHttp.spec.d.ts +1 -0
- package/lib/outbound-http/outboundHttp.spec.js +59 -0
- package/lib/outbound-http/outboundHttp.spec.js.map +1 -0
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/outbound-http/createServiceUserAgent.spec.ts +11 -0
- package/src/outbound-http/createServiceUserAgent.ts +9 -0
- package/src/outbound-http/index.ts +2 -0
- package/src/outbound-http/outboundHttp.spec.ts +69 -0
- package/src/outbound-http/outboundHttp.ts +26 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -37,4 +37,5 @@ __exportStar(require("./secret-api-key-service/getSecretApiKeyService"), exports
|
|
|
37
37
|
__exportStar(require("./events/EventBusService"), exports);
|
|
38
38
|
__exportStar(require("./stream/EventStreamHandler"), exports);
|
|
39
39
|
__exportStar(require("./stream/StreamUtils"), exports);
|
|
40
|
+
__exportStar(require("./outbound-http"), exports);
|
|
40
41
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0CAAwB;AACxB,yCAAuB;AACvB,qDAAmC;AACnC,iEAA+C;AAC/C,+DAA6C;AAC7C,+EAA6D;AAC7D,+EAA6D;AAC7D,gFAA8D;AAC9D,wEAAsD;AACtD,0CAAwB;AACxB,+CAA6B;AAC7B,iHAA+F;AAC/F,gHAA8F;AAC9F,sGAAoF;AACpF,sGAAoF;AACpF,iFAA+D;AAC/D,+EAA6D;AAC7D,kFAAgE;AAChE,kFAAgE;AAChE,2DAAyC;AACzC,8DAA4C;AAC5C,uDAAqC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,0CAAwB;AACxB,yCAAuB;AACvB,qDAAmC;AACnC,iEAA+C;AAC/C,+DAA6C;AAC7C,+EAA6D;AAC7D,+EAA6D;AAC7D,gFAA8D;AAC9D,wEAAsD;AACtD,0CAAwB;AACxB,+CAA6B;AAC7B,iHAA+F;AAC/F,gHAA8F;AAC9F,sGAAoF;AACpF,sGAAoF;AACpF,iFAA+D;AAC/D,+EAA6D;AAC7D,kFAAgE;AAChE,kFAAgE;AAChE,2DAAyC;AACzC,8DAA4C;AAC5C,uDAAqC;AACrC,kDAAgC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createServiceUserAgent = createServiceUserAgent;
|
|
4
|
+
/**
|
|
5
|
+
* Builds a User-Agent string for outbound service-to-service HTTP requests.
|
|
6
|
+
*
|
|
7
|
+
* @param serviceName Service identifier, e.g. `content-api` or `@squiz/content-api`
|
|
8
|
+
*/
|
|
9
|
+
function createServiceUserAgent(serviceName) {
|
|
10
|
+
const name = serviceName.replace(/^@squiz\//, '');
|
|
11
|
+
return `Squiz/${name}`;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=createServiceUserAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createServiceUserAgent.js","sourceRoot":"","sources":["../../src/outbound-http/createServiceUserAgent.ts"],"names":[],"mappings":";;AAKA,wDAGC;AARD;;;;GAIG;AACH,SAAgB,sBAAsB,CAAC,WAAmB;IACxD,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAClD,OAAO,SAAS,IAAI,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createServiceUserAgent_1 = require("./createServiceUserAgent");
|
|
4
|
+
describe('createServiceUserAgent', () => {
|
|
5
|
+
it('returns Squiz/<name> for a scoped package name', () => {
|
|
6
|
+
expect((0, createServiceUserAgent_1.createServiceUserAgent)('@squiz/content-api')).toBe('Squiz/content-api');
|
|
7
|
+
});
|
|
8
|
+
it('returns Squiz/<name> for an unscoped service name', () => {
|
|
9
|
+
expect((0, createServiceUserAgent_1.createServiceUserAgent)('content-api')).toBe('Squiz/content-api');
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=createServiceUserAgent.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createServiceUserAgent.spec.js","sourceRoot":"","sources":["../../src/outbound-http/createServiceUserAgent.spec.ts"],"names":[],"mappings":";;AAAA,qEAAkE;AAElE,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,IAAA,+CAAsB,EAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,IAAA,+CAAsB,EAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.outboundFetch = exports.createServiceUserAgent = void 0;
|
|
4
|
+
var createServiceUserAgent_1 = require("./createServiceUserAgent");
|
|
5
|
+
Object.defineProperty(exports, "createServiceUserAgent", { enumerable: true, get: function () { return createServiceUserAgent_1.createServiceUserAgent; } });
|
|
6
|
+
var outboundHttp_1 = require("./outboundHttp");
|
|
7
|
+
Object.defineProperty(exports, "outboundFetch", { enumerable: true, get: function () { return outboundHttp_1.outboundFetch; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/outbound-http/index.ts"],"names":[],"mappings":";;;AAAA,mEAAkE;AAAzD,gIAAA,sBAAsB,OAAA;AAC/B,+CAAwE;AAA/D,6GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.outboundFetch = outboundFetch;
|
|
4
|
+
function buildOutboundHeaders(userAgent, input, init) {
|
|
5
|
+
const headers = new Headers();
|
|
6
|
+
if (input instanceof Request) {
|
|
7
|
+
input.headers.forEach((value, key) => {
|
|
8
|
+
headers.set(key, value);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
if (init === null || init === void 0 ? void 0 : init.headers) {
|
|
12
|
+
new Headers(init.headers).forEach((value, key) => {
|
|
13
|
+
headers.set(key, value);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
headers.set('User-Agent', userAgent);
|
|
17
|
+
return headers;
|
|
18
|
+
}
|
|
19
|
+
function outboundFetch(userAgent, input, init) {
|
|
20
|
+
const headers = buildOutboundHeaders(userAgent, input, init);
|
|
21
|
+
return fetch(input, { ...init, headers });
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=outboundHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outboundHttp.js","sourceRoot":"","sources":["../../src/outbound-http/outboundHttp.ts"],"names":[],"mappings":";;AAsBA,sCAGC;AAvBD,SAAS,oBAAoB,CAAC,SAAiB,EAAE,KAAyB,EAAE,IAAkB;IAC5F,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;QAC7B,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACnC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,EAAE,CAAC;QAClB,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAErC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAgB,aAAa,CAAC,SAAiB,EAAE,KAAyB,EAAE,IAAkB;IAC5F,MAAM,OAAO,GAAG,oBAAoB,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const outboundHttp_1 = require("./outboundHttp");
|
|
4
|
+
describe('outboundFetch', () => {
|
|
5
|
+
const userAgent = 'Squiz/test-service';
|
|
6
|
+
const originalFetch = global.fetch;
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
global.fetch = jest.fn().mockResolvedValue(new Response());
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
global.fetch = originalFetch;
|
|
12
|
+
});
|
|
13
|
+
it('adds User-Agent to string URL requests with init headers', async () => {
|
|
14
|
+
await (0, outboundHttp_1.outboundFetch)(userAgent, 'https://example.com/resource', {
|
|
15
|
+
headers: { 'x-api-key': 'secret' },
|
|
16
|
+
});
|
|
17
|
+
const init = global.fetch.mock.calls[0][1];
|
|
18
|
+
const headers = init.headers;
|
|
19
|
+
expect(headers.get('x-api-key')).toBe('secret');
|
|
20
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
21
|
+
});
|
|
22
|
+
it('preserves headers from a Request input and adds User-Agent', async () => {
|
|
23
|
+
const request = new Request('https://example.com/resource', {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
headers: {
|
|
26
|
+
Authorization: 'Bearer token',
|
|
27
|
+
'x-dxp-tenant': 'tenant-1',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
await (0, outboundHttp_1.outboundFetch)(userAgent, request);
|
|
31
|
+
const init = global.fetch.mock.calls[0][1];
|
|
32
|
+
const headers = init.headers;
|
|
33
|
+
expect(headers.get('Authorization')).toBe('Bearer token');
|
|
34
|
+
expect(headers.get('x-dxp-tenant')).toBe('tenant-1');
|
|
35
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
36
|
+
});
|
|
37
|
+
it('merges init headers on top of Request headers without dropping existing values', async () => {
|
|
38
|
+
const request = new Request('https://example.com/resource', {
|
|
39
|
+
headers: { 'x-api-key': 'from-request' },
|
|
40
|
+
});
|
|
41
|
+
await (0, outboundHttp_1.outboundFetch)(userAgent, request, {
|
|
42
|
+
headers: { 'x-dxp-session': 'session-token' },
|
|
43
|
+
});
|
|
44
|
+
const init = global.fetch.mock.calls[0][1];
|
|
45
|
+
const headers = init.headers;
|
|
46
|
+
expect(headers.get('x-api-key')).toBe('from-request');
|
|
47
|
+
expect(headers.get('x-dxp-session')).toBe('session-token');
|
|
48
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
49
|
+
});
|
|
50
|
+
it('Overrides an explicit User-Agent header', async () => {
|
|
51
|
+
await (0, outboundHttp_1.outboundFetch)(userAgent, 'https://example.com/resource', {
|
|
52
|
+
headers: { 'User-Agent': 'custom-agent' },
|
|
53
|
+
});
|
|
54
|
+
const init = global.fetch.mock.calls[0][1];
|
|
55
|
+
const headers = init.headers;
|
|
56
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=outboundHttp.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outboundHttp.spec.js","sourceRoot":"","sources":["../../src/outbound-http/outboundHttp.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squiz/dx-common-lib",
|
|
3
|
-
"version": "1.72.
|
|
3
|
+
"version": "1.72.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"author": "",
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@aws-sdk/client-secrets-manager": "^3.
|
|
19
|
+
"@aws-sdk/client-secrets-manager": "^3.1057.0",
|
|
20
20
|
"@squiz/dx-logger-lib": "^1.65.1",
|
|
21
21
|
"archiver": "7.0.1",
|
|
22
22
|
"escape-string-regexp": "4.0.0",
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createServiceUserAgent } from './createServiceUserAgent';
|
|
2
|
+
|
|
3
|
+
describe('createServiceUserAgent', () => {
|
|
4
|
+
it('returns Squiz/<name> for a scoped package name', () => {
|
|
5
|
+
expect(createServiceUserAgent('@squiz/content-api')).toBe('Squiz/content-api');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('returns Squiz/<name> for an unscoped service name', () => {
|
|
9
|
+
expect(createServiceUserAgent('content-api')).toBe('Squiz/content-api');
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds a User-Agent string for outbound service-to-service HTTP requests.
|
|
3
|
+
*
|
|
4
|
+
* @param serviceName Service identifier, e.g. `content-api` or `@squiz/content-api`
|
|
5
|
+
*/
|
|
6
|
+
export function createServiceUserAgent(serviceName: string): string {
|
|
7
|
+
const name = serviceName.replace(/^@squiz\//, '');
|
|
8
|
+
return `Squiz/${name}`;
|
|
9
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { outboundFetch } from './outboundHttp';
|
|
2
|
+
|
|
3
|
+
describe('outboundFetch', () => {
|
|
4
|
+
const userAgent = 'Squiz/test-service';
|
|
5
|
+
const originalFetch = global.fetch;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
global.fetch = jest.fn().mockResolvedValue(new Response());
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
global.fetch = originalFetch;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('adds User-Agent to string URL requests with init headers', async () => {
|
|
16
|
+
await outboundFetch(userAgent, 'https://example.com/resource', {
|
|
17
|
+
headers: { 'x-api-key': 'secret' },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const init = (global.fetch as jest.Mock).mock.calls[0][1] as RequestInit;
|
|
21
|
+
const headers = init.headers as Headers;
|
|
22
|
+
expect(headers.get('x-api-key')).toBe('secret');
|
|
23
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('preserves headers from a Request input and adds User-Agent', async () => {
|
|
27
|
+
const request = new Request('https://example.com/resource', {
|
|
28
|
+
method: 'GET',
|
|
29
|
+
headers: {
|
|
30
|
+
Authorization: 'Bearer token',
|
|
31
|
+
'x-dxp-tenant': 'tenant-1',
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
await outboundFetch(userAgent, request);
|
|
36
|
+
|
|
37
|
+
const init = (global.fetch as jest.Mock).mock.calls[0][1] as RequestInit;
|
|
38
|
+
const headers = init.headers as Headers;
|
|
39
|
+
expect(headers.get('Authorization')).toBe('Bearer token');
|
|
40
|
+
expect(headers.get('x-dxp-tenant')).toBe('tenant-1');
|
|
41
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('merges init headers on top of Request headers without dropping existing values', async () => {
|
|
45
|
+
const request = new Request('https://example.com/resource', {
|
|
46
|
+
headers: { 'x-api-key': 'from-request' },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
await outboundFetch(userAgent, request, {
|
|
50
|
+
headers: { 'x-dxp-session': 'session-token' },
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const init = (global.fetch as jest.Mock).mock.calls[0][1] as RequestInit;
|
|
54
|
+
const headers = init.headers as Headers;
|
|
55
|
+
expect(headers.get('x-api-key')).toBe('from-request');
|
|
56
|
+
expect(headers.get('x-dxp-session')).toBe('session-token');
|
|
57
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('Overrides an explicit User-Agent header', async () => {
|
|
61
|
+
await outboundFetch(userAgent, 'https://example.com/resource', {
|
|
62
|
+
headers: { 'User-Agent': 'custom-agent' },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const init = (global.fetch as jest.Mock).mock.calls[0][1] as RequestInit;
|
|
66
|
+
const headers = init.headers as Headers;
|
|
67
|
+
expect(headers.get('User-Agent')).toBe(userAgent);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type OutboundFetchInput = string | URL | Request;
|
|
2
|
+
|
|
3
|
+
function buildOutboundHeaders(userAgent: string, input: OutboundFetchInput, init?: RequestInit): Headers {
|
|
4
|
+
const headers = new Headers();
|
|
5
|
+
|
|
6
|
+
if (input instanceof Request) {
|
|
7
|
+
input.headers.forEach((value, key) => {
|
|
8
|
+
headers.set(key, value);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (init?.headers) {
|
|
13
|
+
new Headers(init.headers).forEach((value, key) => {
|
|
14
|
+
headers.set(key, value);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
headers.set('User-Agent', userAgent);
|
|
19
|
+
|
|
20
|
+
return headers;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function outboundFetch(userAgent: string, input: OutboundFetchInput, init?: RequestInit): Promise<Response> {
|
|
24
|
+
const headers = buildOutboundHeaders(userAgent, input, init);
|
|
25
|
+
return fetch(input, { ...init, headers });
|
|
26
|
+
}
|