@squiz/dx-common-lib 1.72.4 → 1.72.5
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/.npm/_logs/2026-09-08T06_40_25_662Z-debug-0.log +19 -0
- package/CHANGELOG.md +6 -0
- package/lib/cloudflare-api/CloudflareApiService.d.ts +16 -0
- package/lib/cloudflare-api/CloudflareApiService.js +45 -0
- package/lib/cloudflare-api/CloudflareApiService.js.map +1 -0
- package/lib/cloudflare-api/CloudflareApiService.spec.d.ts +1 -0
- package/lib/cloudflare-api/CloudflareApiService.spec.js +50 -0
- package/lib/cloudflare-api/CloudflareApiService.spec.js.map +1 -0
- package/lib/cloudflare-service-secret-key-service/getCloudflareServiceSecretService.d.ts +6 -0
- package/lib/cloudflare-service-secret-key-service/getCloudflareServiceSecretService.js +8 -0
- package/lib/cloudflare-service-secret-key-service/getCloudflareServiceSecretService.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/stream/EventStreamHandler.d.ts +3 -2
- package/lib/stream/EventStreamHandler.js.map +1 -1
- package/package.json +2 -2
- package/src/cloudflare-api/CloudflareApiService.spec.ts +66 -0
- package/src/cloudflare-api/CloudflareApiService.ts +61 -0
- package/src/cloudflare-service-secret-key-service/getCloudflareServiceSecretService.ts +11 -0
- package/src/index.ts +2 -0
- package/src/stream/EventStreamHandler.spec.ts +1 -1
- package/src/stream/EventStreamHandler.ts +4 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
0 verbose cli /usr/local/bin/node /usr/local/bin/npm
|
|
2
|
+
1 info using npm@10.8.1
|
|
3
|
+
2 info using node@v22.4.1
|
|
4
|
+
3 silly config load:file:/usr/local/lib/node_modules/npm/npmrc
|
|
5
|
+
4 info config found workspace root at /builds/developer-experience/cmp
|
|
6
|
+
5 silly config load:file:/builds/developer-experience/cmp/.npmrc
|
|
7
|
+
6 silly config load:file:/home/appuser/.npmrc
|
|
8
|
+
7 silly config load:file:/usr/local/etc/npmrc
|
|
9
|
+
8 verbose title npm run compile
|
|
10
|
+
9 verbose argv "run" "compile"
|
|
11
|
+
10 verbose logfile logs-max:10 dir:/builds/developer-experience/cmp/packages/dx-common-lib/.npm/_logs/2026-09-08T06_40_25_662Z-
|
|
12
|
+
11 verbose logfile /builds/developer-experience/cmp/packages/dx-common-lib/.npm/_logs/2026-09-08T06_40_25_662Z-debug-0.log
|
|
13
|
+
12 silly logfile done cleaning log files
|
|
14
|
+
13 verbose cwd /builds/developer-experience/cmp/packages/dx-common-lib
|
|
15
|
+
14 verbose os Linux 6.1.177-224.371.amzn2023.x86_64
|
|
16
|
+
15 verbose node v22.4.1
|
|
17
|
+
16 verbose npm v10.8.1
|
|
18
|
+
17 verbose exit 0
|
|
19
|
+
18 info ok
|
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CloudflareServiceSecretKeyService } from '../cloudflare-service-secret-key-service/getCloudflareServiceSecretService';
|
|
2
|
+
export interface CloudflareApiServiceInterface {
|
|
3
|
+
loadApiToken(): Promise<void>;
|
|
4
|
+
deleteDispatchScript(scriptName: string): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export type CloudflareApiServiceConfig = {
|
|
7
|
+
accountId: string;
|
|
8
|
+
dispatchNamespace: string;
|
|
9
|
+
apiTokenService: CloudflareServiceSecretKeyService;
|
|
10
|
+
};
|
|
11
|
+
export declare class CloudflareApiService implements CloudflareApiServiceInterface {
|
|
12
|
+
private readonly config;
|
|
13
|
+
constructor(config: CloudflareApiServiceConfig);
|
|
14
|
+
loadApiToken(): Promise<void>;
|
|
15
|
+
deleteDispatchScript(scriptName: string): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CloudflareApiService = void 0;
|
|
4
|
+
class CloudflareApiService {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
}
|
|
8
|
+
async loadApiToken() {
|
|
9
|
+
await this.config.apiTokenService.loadSecretKey();
|
|
10
|
+
}
|
|
11
|
+
async deleteDispatchScript(scriptName) {
|
|
12
|
+
var _a, _b, _c;
|
|
13
|
+
const apiToken = this.config.apiTokenService.getSecretKey();
|
|
14
|
+
if (!apiToken) {
|
|
15
|
+
throw new Error('Cloudflare API token is not loaded');
|
|
16
|
+
}
|
|
17
|
+
const { accountId, dispatchNamespace } = this.config;
|
|
18
|
+
if (!accountId || !dispatchNamespace) {
|
|
19
|
+
throw new Error('Cloudflare account ID and dispatch namespace must be configured');
|
|
20
|
+
}
|
|
21
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/dispatch/namespaces/${dispatchNamespace}/scripts/${encodeURIComponent(scriptName)}`;
|
|
22
|
+
const response = await fetch(url, {
|
|
23
|
+
method: 'DELETE',
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${apiToken}`,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
if (response.status === 404) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
let message = response.statusText;
|
|
33
|
+
try {
|
|
34
|
+
const body = (await response.json());
|
|
35
|
+
message = (_c = (_b = (_a = body.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : message;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// use statusText when response body is not JSON
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`Failed to delete Cloudflare dispatch script: ${message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.CloudflareApiService = CloudflareApiService;
|
|
45
|
+
//# sourceMappingURL=CloudflareApiService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudflareApiService.js","sourceRoot":"","sources":["../../src/cloudflare-api/CloudflareApiService.ts"],"names":[],"mappings":";;;AAiBA,MAAa,oBAAoB;IAC/B,YAA6B,MAAkC;QAAlC,WAAM,GAAN,MAAM,CAA4B;IAAG,CAAC;IAEnE,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAkB;;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,YAAY,EAAE,CAAC;QAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACrD,IAAI,CAAC,SAAS,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,GAAG,GAAG,iDAAiD,SAAS,gCAAgC,iBAAiB,YAAY,kBAAkB,CACnJ,UAAU,CACX,EAAE,CAAC;QACJ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,QAAQ,EAAE;aACpC;SACF,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA+B,CAAC;gBACnE,OAAO,GAAG,MAAA,MAAA,MAAA,IAAI,CAAC,MAAM,0CAAG,CAAC,CAAC,0CAAE,OAAO,mCAAI,OAAO,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,gDAAgD;YAClD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,gDAAgD,OAAO,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;CACF;AA3CD,oDA2CC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const CloudflareApiService_1 = require("./CloudflareApiService");
|
|
4
|
+
describe('CloudflareApiService', () => {
|
|
5
|
+
const apiTokenService = {
|
|
6
|
+
loadSecretKey: jest.fn().mockResolvedValue(undefined),
|
|
7
|
+
getSecretKey: jest.fn().mockReturnValue('cloudflare-api-token'),
|
|
8
|
+
};
|
|
9
|
+
let service;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
jest.mocked(apiTokenService.getSecretKey).mockReturnValue('cloudflare-api-token');
|
|
12
|
+
service = new CloudflareApiService_1.CloudflareApiService({
|
|
13
|
+
accountId: 'account-id',
|
|
14
|
+
dispatchNamespace: 'cmp_development',
|
|
15
|
+
apiTokenService,
|
|
16
|
+
});
|
|
17
|
+
jest.spyOn(global, 'fetch').mockReset();
|
|
18
|
+
});
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
jest.restoreAllMocks();
|
|
21
|
+
});
|
|
22
|
+
it('loads the API token from the secret service', async () => {
|
|
23
|
+
await service.loadApiToken();
|
|
24
|
+
expect(apiTokenService.loadSecretKey).toHaveBeenCalled();
|
|
25
|
+
});
|
|
26
|
+
it('deletes a dispatch namespace script from the Cloudflare API', async () => {
|
|
27
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({ ok: true, status: 200 });
|
|
28
|
+
await service.deleteDispatchScript('tenant__namespace__component__1.0.0');
|
|
29
|
+
expect(fetch).toHaveBeenCalledWith('https://api.cloudflare.com/client/v4/accounts/account-id/workers/dispatch/namespaces/cmp_development/scripts/tenant__namespace__component__1.0.0', {
|
|
30
|
+
method: 'DELETE',
|
|
31
|
+
headers: {
|
|
32
|
+
Authorization: 'Bearer cloudflare-api-token',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
it('treats a 404 response as already deleted', async () => {
|
|
37
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({ ok: false, status: 404, statusText: 'Not Found' });
|
|
38
|
+
await expect(service.deleteDispatchScript('missing-script')).resolves.toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
it('throws when the Cloudflare API returns an error', async () => {
|
|
41
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({
|
|
42
|
+
ok: false,
|
|
43
|
+
status: 500,
|
|
44
|
+
statusText: 'Internal Server Error',
|
|
45
|
+
json: async () => ({ errors: [{ message: 'Delete failed' }] }),
|
|
46
|
+
});
|
|
47
|
+
await expect(service.deleteDispatchScript('tenant__namespace__component__1.0.0')).rejects.toThrow('Failed to delete Cloudflare dispatch script: Delete failed');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=CloudflareApiService.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudflareApiService.spec.js","sourceRoot":"","sources":["../../src/cloudflare-api/CloudflareApiService.spec.ts"],"names":[],"mappings":";;AAAA,iEAA8D;AAG9D,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,MAAM,eAAe,GAAsC;QACzD,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;QACrD,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,sBAAsB,CAAC;KAChE,CAAC;IAEF,IAAI,OAA6B,CAAC;IAElC,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC;QAClF,OAAO,GAAG,IAAI,2CAAoB,CAAC;YACjC,SAAS,EAAE,YAAY;YACvB,iBAAiB,EAAE,iBAAiB;YACpC,eAAe;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;QAE7B,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAc,CAAC,CAAC;QAErF,MAAM,OAAO,CAAC,oBAAoB,CAAC,qCAAqC,CAAC,CAAC;QAE1E,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAChC,kJAAkJ,EAClJ;YACE,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE;gBACP,aAAa,EAAE,6BAA6B;aAC7C;SACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAc,CAAC,CAAC;QAE/G,MAAM,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,iBAAiB,CAAC;YAC5C,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,uBAAuB;YACnC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;QAEf,MAAM,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,qCAAqC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC/F,4DAA4D,CAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { EdgeComponentsSecretKeyService } from '../edge-components-secret-key-service/EdgeComponentsSecretKeyService';
|
|
2
|
+
export type CloudflareServiceSecretKeyService = EdgeComponentsSecretKeyService;
|
|
3
|
+
export declare function getCloudflareServiceSecretService(config: {
|
|
4
|
+
secretName?: string;
|
|
5
|
+
secretValue?: string;
|
|
6
|
+
}): CloudflareServiceSecretKeyService;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCloudflareServiceSecretService = getCloudflareServiceSecretService;
|
|
4
|
+
const getEdgeComponentsSecretService_1 = require("../edge-components-secret-key-service/getEdgeComponentsSecretService");
|
|
5
|
+
function getCloudflareServiceSecretService(config) {
|
|
6
|
+
return (0, getEdgeComponentsSecretService_1.getEdgeComponentsSecretService)(config);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=getCloudflareServiceSecretService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getCloudflareServiceSecretService.js","sourceRoot":"","sources":["../../src/cloudflare-service-secret-key-service/getCloudflareServiceSecretService.ts"],"names":[],"mappings":";;AAKA,8EAKC;AATD,yHAAsH;AAItH,SAAgB,iCAAiC,CAAC,MAGjD;IACC,OAAO,IAAA,+DAA8B,EAAC,MAAM,CAAC,CAAC;AAChD,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export * from './edge-components-secret-key-service/DevelopmentEdgeComponentsSec
|
|
|
14
14
|
export * from './edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService';
|
|
15
15
|
export * from './edge-components-secret-key-service/EdgeComponentsSecretKeyService';
|
|
16
16
|
export * from './edge-components-secret-key-service/getEdgeComponentsSecretService';
|
|
17
|
+
export * from './cloudflare-service-secret-key-service/getCloudflareServiceSecretService';
|
|
18
|
+
export * from './cloudflare-api/CloudflareApiService';
|
|
17
19
|
export * from './esi-mac-token-generator/EsiMacTokenGenerator';
|
|
18
20
|
export * from './secret-api-key-service/SecretApiKeyService';
|
|
19
21
|
export * from './secret-api-key-service/DevSecretApiKeyService';
|
package/lib/index.js
CHANGED
|
@@ -30,6 +30,8 @@ __exportStar(require("./edge-components-secret-key-service/DevelopmentEdgeCompon
|
|
|
30
30
|
__exportStar(require("./edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService"), exports);
|
|
31
31
|
__exportStar(require("./edge-components-secret-key-service/EdgeComponentsSecretKeyService"), exports);
|
|
32
32
|
__exportStar(require("./edge-components-secret-key-service/getEdgeComponentsSecretService"), exports);
|
|
33
|
+
__exportStar(require("./cloudflare-service-secret-key-service/getCloudflareServiceSecretService"), exports);
|
|
34
|
+
__exportStar(require("./cloudflare-api/CloudflareApiService"), exports);
|
|
33
35
|
__exportStar(require("./esi-mac-token-generator/EsiMacTokenGenerator"), exports);
|
|
34
36
|
__exportStar(require("./secret-api-key-service/SecretApiKeyService"), exports);
|
|
35
37
|
__exportStar(require("./secret-api-key-service/DevSecretApiKeyService"), exports);
|
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;AACrC,kDAAgC"}
|
|
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,4GAA0F;AAC1F,wEAAsD;AACtD,iFAA+D;AAC/D,+EAA6D;AAC7D,kFAAgE;AAChE,kFAAgE;AAChE,2DAAyC;AACzC,8DAA4C;AAC5C,uDAAqC;AACrC,kDAAgC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @license
|
|
3
3
|
* Copyright Squiz Australia Pty Ltd. All Rights Reserved.
|
|
4
4
|
*/
|
|
5
|
-
import { DynamoDBStreamEvent, DynamoDBRecord, Context, DynamoDBBatchResponse } from 'aws-lambda';
|
|
5
|
+
import type { DynamoDBStreamEvent, DynamoDBRecord, Context, DynamoDBBatchResponse } from 'aws-lambda';
|
|
6
6
|
import { Logger } from '@squiz/dx-logger-lib';
|
|
7
7
|
import { EventBusService } from '../events/EventBusService';
|
|
8
8
|
export interface EventPayload {
|
|
@@ -12,6 +12,7 @@ export interface EventPayload {
|
|
|
12
12
|
export type EventMapper = (record: DynamoDBRecord) => Promise<EventPayload[]>;
|
|
13
13
|
/** Resolves tenant id for publishing; use `record` when tenant is carried on the item rather than derivable from the table ARN. */
|
|
14
14
|
export type ExtractTenantId = (arn: string, tableServiceIdentifier: string, record: DynamoDBRecord) => string;
|
|
15
|
+
export type EventStreamHandler = (event: DynamoDBStreamEvent, context: Context) => Promise<DynamoDBBatchResponse>;
|
|
15
16
|
interface EventStreamHandlerConfig<T extends string> {
|
|
16
17
|
logger: Logger;
|
|
17
18
|
eventBusService: EventBusService;
|
|
@@ -34,5 +35,5 @@ interface EventStreamHandlerConfig<T extends string> {
|
|
|
34
35
|
* - Batch event publishing with retry tracking
|
|
35
36
|
* - Failure reporting for Lambda retry mechanism
|
|
36
37
|
*/
|
|
37
|
-
export declare function createEventStreamHandler<T extends string>(config: EventStreamHandlerConfig<T>):
|
|
38
|
+
export declare function createEventStreamHandler<T extends string>(config: EventStreamHandlerConfig<T>): EventStreamHandler;
|
|
38
39
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventStreamHandler.js","sourceRoot":"","sources":["../../src/stream/EventStreamHandler.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"EventStreamHandler.js","sourceRoot":"","sources":["../../src/stream/EventStreamHandler.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.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/archiver": "6.0.3",
|
|
29
|
+
"@types/aws-lambda": "^8.10.161",
|
|
29
30
|
"@types/express": "4.17.23",
|
|
30
31
|
"@types/fs-extra": "11.0.1",
|
|
31
32
|
"@types/jest": "28.1.8",
|
|
32
33
|
"@types/lodash.clonedeep": "4.5.9",
|
|
33
34
|
"@types/node": "22.10.5",
|
|
34
|
-
"aws-lambda": "^1.0.7",
|
|
35
35
|
"dotenv": "16.6.1",
|
|
36
36
|
"jest": "29.4.1",
|
|
37
37
|
"ts-jest": "29.0.5",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CloudflareApiService } from './CloudflareApiService';
|
|
2
|
+
import { CloudflareServiceSecretKeyService } from '../cloudflare-service-secret-key-service/getCloudflareServiceSecretService';
|
|
3
|
+
|
|
4
|
+
describe('CloudflareApiService', () => {
|
|
5
|
+
const apiTokenService: CloudflareServiceSecretKeyService = {
|
|
6
|
+
loadSecretKey: jest.fn().mockResolvedValue(undefined),
|
|
7
|
+
getSecretKey: jest.fn().mockReturnValue('cloudflare-api-token'),
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
let service: CloudflareApiService;
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.mocked(apiTokenService.getSecretKey).mockReturnValue('cloudflare-api-token');
|
|
14
|
+
service = new CloudflareApiService({
|
|
15
|
+
accountId: 'account-id',
|
|
16
|
+
dispatchNamespace: 'cmp_development',
|
|
17
|
+
apiTokenService,
|
|
18
|
+
});
|
|
19
|
+
jest.spyOn(global, 'fetch').mockReset();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
jest.restoreAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('loads the API token from the secret service', async () => {
|
|
27
|
+
await service.loadApiToken();
|
|
28
|
+
|
|
29
|
+
expect(apiTokenService.loadSecretKey).toHaveBeenCalled();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('deletes a dispatch namespace script from the Cloudflare API', async () => {
|
|
33
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({ ok: true, status: 200 } as Response);
|
|
34
|
+
|
|
35
|
+
await service.deleteDispatchScript('tenant__namespace__component__1.0.0');
|
|
36
|
+
|
|
37
|
+
expect(fetch).toHaveBeenCalledWith(
|
|
38
|
+
'https://api.cloudflare.com/client/v4/accounts/account-id/workers/dispatch/namespaces/cmp_development/scripts/tenant__namespace__component__1.0.0',
|
|
39
|
+
{
|
|
40
|
+
method: 'DELETE',
|
|
41
|
+
headers: {
|
|
42
|
+
Authorization: 'Bearer cloudflare-api-token',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('treats a 404 response as already deleted', async () => {
|
|
49
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({ ok: false, status: 404, statusText: 'Not Found' } as Response);
|
|
50
|
+
|
|
51
|
+
await expect(service.deleteDispatchScript('missing-script')).resolves.toBeUndefined();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('throws when the Cloudflare API returns an error', async () => {
|
|
55
|
+
jest.spyOn(global, 'fetch').mockResolvedValue({
|
|
56
|
+
ok: false,
|
|
57
|
+
status: 500,
|
|
58
|
+
statusText: 'Internal Server Error',
|
|
59
|
+
json: async () => ({ errors: [{ message: 'Delete failed' }] }),
|
|
60
|
+
} as Response);
|
|
61
|
+
|
|
62
|
+
await expect(service.deleteDispatchScript('tenant__namespace__component__1.0.0')).rejects.toThrow(
|
|
63
|
+
'Failed to delete Cloudflare dispatch script: Delete failed',
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CloudflareServiceSecretKeyService } from '../cloudflare-service-secret-key-service/getCloudflareServiceSecretService';
|
|
2
|
+
|
|
3
|
+
export interface CloudflareApiServiceInterface {
|
|
4
|
+
loadApiToken(): Promise<void>;
|
|
5
|
+
deleteDispatchScript(scriptName: string): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type CloudflareApiServiceConfig = {
|
|
9
|
+
accountId: string;
|
|
10
|
+
dispatchNamespace: string;
|
|
11
|
+
apiTokenService: CloudflareServiceSecretKeyService;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type CloudflareApiErrorResponse = {
|
|
15
|
+
errors?: { message?: string }[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export class CloudflareApiService implements CloudflareApiServiceInterface {
|
|
19
|
+
constructor(private readonly config: CloudflareApiServiceConfig) {}
|
|
20
|
+
|
|
21
|
+
async loadApiToken(): Promise<void> {
|
|
22
|
+
await this.config.apiTokenService.loadSecretKey();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async deleteDispatchScript(scriptName: string): Promise<void> {
|
|
26
|
+
const apiToken = this.config.apiTokenService.getSecretKey();
|
|
27
|
+
if (!apiToken) {
|
|
28
|
+
throw new Error('Cloudflare API token is not loaded');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { accountId, dispatchNamespace } = this.config;
|
|
32
|
+
if (!accountId || !dispatchNamespace) {
|
|
33
|
+
throw new Error('Cloudflare account ID and dispatch namespace must be configured');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/dispatch/namespaces/${dispatchNamespace}/scripts/${encodeURIComponent(
|
|
37
|
+
scriptName,
|
|
38
|
+
)}`;
|
|
39
|
+
const response = await fetch(url, {
|
|
40
|
+
method: 'DELETE',
|
|
41
|
+
headers: {
|
|
42
|
+
Authorization: `Bearer ${apiToken}`,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
if (response.status === 404) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
let message = response.statusText;
|
|
52
|
+
try {
|
|
53
|
+
const body = (await response.json()) as CloudflareApiErrorResponse;
|
|
54
|
+
message = body.errors?.[0]?.message ?? message;
|
|
55
|
+
} catch {
|
|
56
|
+
// use statusText when response body is not JSON
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Failed to delete Cloudflare dispatch script: ${message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EdgeComponentsSecretKeyService } from '../edge-components-secret-key-service/EdgeComponentsSecretKeyService';
|
|
2
|
+
import { getEdgeComponentsSecretService } from '../edge-components-secret-key-service/getEdgeComponentsSecretService';
|
|
3
|
+
|
|
4
|
+
export type CloudflareServiceSecretKeyService = EdgeComponentsSecretKeyService;
|
|
5
|
+
|
|
6
|
+
export function getCloudflareServiceSecretService(config: {
|
|
7
|
+
secretName?: string;
|
|
8
|
+
secretValue?: string;
|
|
9
|
+
}): CloudflareServiceSecretKeyService {
|
|
10
|
+
return getEdgeComponentsSecretService(config);
|
|
11
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,8 @@ export * from './edge-components-secret-key-service/DevelopmentEdgeComponentsSec
|
|
|
14
14
|
export * from './edge-components-secret-key-service/ProductionEdgeComponentsSecretKeyService';
|
|
15
15
|
export * from './edge-components-secret-key-service/EdgeComponentsSecretKeyService';
|
|
16
16
|
export * from './edge-components-secret-key-service/getEdgeComponentsSecretService';
|
|
17
|
+
export * from './cloudflare-service-secret-key-service/getCloudflareServiceSecretService';
|
|
18
|
+
export * from './cloudflare-api/CloudflareApiService';
|
|
17
19
|
export * from './esi-mac-token-generator/EsiMacTokenGenerator';
|
|
18
20
|
export * from './secret-api-key-service/SecretApiKeyService';
|
|
19
21
|
export * from './secret-api-key-service/DevSecretApiKeyService';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Copyright Squiz Australia Pty Ltd. All Rights Reserved.
|
|
4
4
|
*/
|
|
5
5
|
import { createEventStreamHandler, EventMapper } from './EventStreamHandler';
|
|
6
|
-
import { DynamoDBStreamEvent, DynamoDBRecord, Context } from 'aws-lambda';
|
|
6
|
+
import type { DynamoDBStreamEvent, DynamoDBRecord, Context } from 'aws-lambda';
|
|
7
7
|
|
|
8
8
|
interface MockLogger {
|
|
9
9
|
info: jest.Mock;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @license
|
|
3
3
|
* Copyright Squiz Australia Pty Ltd. All Rights Reserved.
|
|
4
4
|
*/
|
|
5
|
-
import { DynamoDBStreamEvent, DynamoDBRecord, Context, DynamoDBBatchResponse } from 'aws-lambda';
|
|
5
|
+
import type { DynamoDBStreamEvent, DynamoDBRecord, Context, DynamoDBBatchResponse } from 'aws-lambda';
|
|
6
6
|
import { Logger } from '@squiz/dx-logger-lib';
|
|
7
7
|
import { EventBusService } from '../events/EventBusService';
|
|
8
8
|
|
|
@@ -16,6 +16,8 @@ export type EventMapper = (record: DynamoDBRecord) => Promise<EventPayload[]>;
|
|
|
16
16
|
/** Resolves tenant id for publishing; use `record` when tenant is carried on the item rather than derivable from the table ARN. */
|
|
17
17
|
export type ExtractTenantId = (arn: string, tableServiceIdentifier: string, record: DynamoDBRecord) => string;
|
|
18
18
|
|
|
19
|
+
export type EventStreamHandler = (event: DynamoDBStreamEvent, context: Context) => Promise<DynamoDBBatchResponse>;
|
|
20
|
+
|
|
19
21
|
interface MappedRecord {
|
|
20
22
|
recordIndex: number;
|
|
21
23
|
record: DynamoDBRecord;
|
|
@@ -46,7 +48,7 @@ interface EventStreamHandlerConfig<T extends string> {
|
|
|
46
48
|
* - Batch event publishing with retry tracking
|
|
47
49
|
* - Failure reporting for Lambda retry mechanism
|
|
48
50
|
*/
|
|
49
|
-
export function createEventStreamHandler<T extends string>(config: EventStreamHandlerConfig<T>) {
|
|
51
|
+
export function createEventStreamHandler<T extends string>(config: EventStreamHandlerConfig<T>): EventStreamHandler {
|
|
50
52
|
const {
|
|
51
53
|
logger,
|
|
52
54
|
eventBusService,
|