@deployagram/logger-client 0.0.0-stage → 0.2.0
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/LICENSE +14 -0
- package/README.md +59 -2
- package/dist/diagram-logger-client.d.ts +46 -0
- package/dist/diagram-logger-client.js +67 -0
- package/dist/diagram-logger-client.js.map +1 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.js +12 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/kafka.d.ts +11 -0
- package/dist/kafka.js +2 -0
- package/dist/kafka.js.map +1 -0
- package/package.json +38 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
DEPLOYAGRAM PROPRIETARY LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Deployagram, Cookiebit and Andy Muir.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted to use this software solely for its intended purpose.
|
|
6
|
+
|
|
7
|
+
RESTRICTIONS:
|
|
8
|
+
- No modification of the software is permitted
|
|
9
|
+
- No reverse engineering, decompilation, or disassembly
|
|
10
|
+
- No redistribution without explicit written permission
|
|
11
|
+
- Source code remains proprietary and confidential
|
|
12
|
+
- Usage is limited to the compiled npm package (the distributed tarball) artifact only
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
package/README.md
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @deployagram/logger-client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A client for the Deployagram Collector (`living-http-logger`), built on Node's `fetch`. It is the
|
|
4
|
+
Node.js equivalent of the Java `DiagramLoggerClient`.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install @deployagram/logger-client
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { DiagramLoggerClient } from '@deployagram/logger-client';
|
|
12
|
+
|
|
13
|
+
const logger = new DiagramLoggerClient({ baseUrl: 'http://localhost:1152' });
|
|
14
|
+
|
|
15
|
+
await logger.log({
|
|
16
|
+
timestamp: new Date().toISOString(),
|
|
17
|
+
protocol: 'HTTP',
|
|
18
|
+
source: 'EmailClient',
|
|
19
|
+
target: 'Emailer',
|
|
20
|
+
message: 'POST /Emailer/email',
|
|
21
|
+
body: '{"email":"eddie@eddie.com"}',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const all = await logger.read(); // GET /log/read
|
|
25
|
+
const marked = await logger.read('marker'); // GET /log/read/{id}
|
|
26
|
+
await logger.markEnd('marker'); // POST /log/markEnd/{id}
|
|
27
|
+
await logger.flushToCloud('Emailer', 'run-1'); // POST /run/markTestRunEnd/{container}/{run}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Method | Collector endpoint |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `log(log)` | `POST /log` |
|
|
33
|
+
| `read()` | `GET /log/read` |
|
|
34
|
+
| `read(id)` | `GET /log/read/{id}` |
|
|
35
|
+
| `markEnd(id)` | `POST /log/markEnd/{id}` |
|
|
36
|
+
| `flushToCloud(container, run)` | `POST /run/markTestRunEnd/{container}/{run}` |
|
|
37
|
+
| `configureKafkaBroker(bootstrapServers)` | `PUT /kafka/configuration` |
|
|
38
|
+
| `configureSchemaRegistry(url)` | `PUT /schemaRegistry/configuration` |
|
|
39
|
+
| `kafkaConsumerRead(read)` | `POST /kafka/consumer` |
|
|
40
|
+
|
|
41
|
+
Differences from the Java client:
|
|
42
|
+
|
|
43
|
+
* A non-2xx response throws `CollectorError`, which has `status` and `responseBody`. The Java
|
|
44
|
+
client ignores the status.
|
|
45
|
+
* Every method returns a Promise.
|
|
46
|
+
* The configure calls need the Collector in runtime configuration mode. In static mode the Collector
|
|
47
|
+
answers `409`, which throws, so a test never silently reads from the wrong broker.
|
|
48
|
+
* `flushToCloud` calls `markTestRunEnd`, as the Java client does. On a Collector with a Central
|
|
49
|
+
Logger configured, that also sends the run to the cloud.
|
|
50
|
+
|
|
51
|
+
## Testing
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm test
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The tests need no Collector. They stub the Collector's endpoints with
|
|
58
|
+
[MSW (Mock Service Worker)](https://mswjs.io), declaring each route the way a WireMock stub is
|
|
59
|
+
declared, then check the method, path, body and error handling. Any request without a matching
|
|
60
|
+
stub fails the test. `flushToCloud` is not tested.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DiagramLogger, Log, Logs } from '@deployagram/api';
|
|
2
|
+
import type { KafkaConsumerRead } from './kafka.js';
|
|
3
|
+
export interface DiagramLoggerClientOptions {
|
|
4
|
+
/** Base URL of the Collector, for example "http://localhost:1152". */
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
/** Replaces the global fetch. Mainly for tests. */
|
|
7
|
+
fetch?: typeof fetch;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Client for the Deployagram Collector. Mirrors the Java DiagramLoggerClient, with two changes:
|
|
11
|
+
* HTTP errors are thrown (the Java client ignores them), and calls return Promises.
|
|
12
|
+
*/
|
|
13
|
+
export declare class DiagramLoggerClient implements DiagramLogger {
|
|
14
|
+
private readonly baseUrl;
|
|
15
|
+
private readonly fetchImpl;
|
|
16
|
+
constructor(options: DiagramLoggerClientOptions);
|
|
17
|
+
/** POST /log: store one interaction. */
|
|
18
|
+
log(log: Log): Promise<void>;
|
|
19
|
+
/** GET /log/read: all logs held by the Collector. */
|
|
20
|
+
read(): Promise<Logs>;
|
|
21
|
+
/** GET /log/read/{logId}: the logs recorded under one marker. */
|
|
22
|
+
read(logId: string): Promise<Logs>;
|
|
23
|
+
/** POST /log/markEnd/{sequenceDiagramId}: close the current sequence diagram. */
|
|
24
|
+
markEnd(sequenceDiagramId: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* POST /run/markTestRunEnd/{containerId}/{testRunId}. As in the Java client, this is the call
|
|
27
|
+
* that ends a test run and, when a Central Logger is configured on the Collector, flushes it.
|
|
28
|
+
*/
|
|
29
|
+
flushToCloud(containerId: string, testRunId: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* PUT /kafka/configuration: the broker the Collector reads Kafka records from. Needs the Collector
|
|
32
|
+
* in runtime configuration mode; otherwise it answers 409, which throws.
|
|
33
|
+
*/
|
|
34
|
+
configureKafkaBroker(bootstrapServers: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* PUT /schemaRegistry/configuration: the registry the Collector decodes Avro and JSON-schema
|
|
37
|
+
* records with. Needs runtime mode, as configureKafkaBroker does.
|
|
38
|
+
*/
|
|
39
|
+
configureSchemaRegistry(url: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* POST /kafka/consumer: tell the Collector a record was consumed. The Collector answers 204 and
|
|
42
|
+
* reads the record in the background.
|
|
43
|
+
*/
|
|
44
|
+
kafkaConsumerRead(read: KafkaConsumerRead): Promise<void>;
|
|
45
|
+
private request;
|
|
46
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CollectorError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Client for the Deployagram Collector. Mirrors the Java DiagramLoggerClient, with two changes:
|
|
4
|
+
* HTTP errors are thrown (the Java client ignores them), and calls return Promises.
|
|
5
|
+
*/
|
|
6
|
+
export class DiagramLoggerClient {
|
|
7
|
+
baseUrl;
|
|
8
|
+
fetchImpl;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, '');
|
|
11
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
12
|
+
}
|
|
13
|
+
/** POST /log: store one interaction. */
|
|
14
|
+
async log(log) {
|
|
15
|
+
await this.request('POST', '/log', log);
|
|
16
|
+
}
|
|
17
|
+
async read(logId) {
|
|
18
|
+
const path = logId === undefined ? '/log/read' : `/log/read/${encodeURIComponent(logId)}`;
|
|
19
|
+
return (await this.request('GET', path));
|
|
20
|
+
}
|
|
21
|
+
/** POST /log/markEnd/{sequenceDiagramId}: close the current sequence diagram. */
|
|
22
|
+
async markEnd(sequenceDiagramId) {
|
|
23
|
+
await this.request('POST', `/log/markEnd/${encodeURIComponent(sequenceDiagramId)}`);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* POST /run/markTestRunEnd/{containerId}/{testRunId}. As in the Java client, this is the call
|
|
27
|
+
* that ends a test run and, when a Central Logger is configured on the Collector, flushes it.
|
|
28
|
+
*/
|
|
29
|
+
async flushToCloud(containerId, testRunId) {
|
|
30
|
+
await this.request('POST', `/run/markTestRunEnd/${encodeURIComponent(containerId)}/${encodeURIComponent(testRunId)}`);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* PUT /kafka/configuration: the broker the Collector reads Kafka records from. Needs the Collector
|
|
34
|
+
* in runtime configuration mode; otherwise it answers 409, which throws.
|
|
35
|
+
*/
|
|
36
|
+
async configureKafkaBroker(bootstrapServers) {
|
|
37
|
+
await this.request('PUT', '/kafka/configuration', { bootstrapServers });
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* PUT /schemaRegistry/configuration: the registry the Collector decodes Avro and JSON-schema
|
|
41
|
+
* records with. Needs runtime mode, as configureKafkaBroker does.
|
|
42
|
+
*/
|
|
43
|
+
async configureSchemaRegistry(url) {
|
|
44
|
+
await this.request('PUT', '/schemaRegistry/configuration', { url });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* POST /kafka/consumer: tell the Collector a record was consumed. The Collector answers 204 and
|
|
48
|
+
* reads the record in the background.
|
|
49
|
+
*/
|
|
50
|
+
async kafkaConsumerRead(read) {
|
|
51
|
+
await this.request('POST', '/kafka/consumer', read);
|
|
52
|
+
}
|
|
53
|
+
async request(method, path, body) {
|
|
54
|
+
const init = { method, headers: { Accept: 'application/json' } };
|
|
55
|
+
if (body !== undefined) {
|
|
56
|
+
init.headers = { ...init.headers, 'Content-Type': 'application/json' };
|
|
57
|
+
init.body = JSON.stringify(body);
|
|
58
|
+
}
|
|
59
|
+
const response = await this.fetchImpl(this.baseUrl + path, init);
|
|
60
|
+
const text = await response.text();
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new CollectorError(method, path, response.status, text);
|
|
63
|
+
}
|
|
64
|
+
return text ? JSON.parse(text) : undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=diagram-logger-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagram-logger-client.js","sourceRoot":"","sources":["../src/diagram-logger-client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
package/dist/errors.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Thrown when the Collector answers with a non-2xx status. */
|
|
2
|
+
export class CollectorError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
responseBody;
|
|
5
|
+
constructor(method, path, status, responseBody) {
|
|
6
|
+
super(`Collector ${method} ${path} failed with HTTP ${status}${responseBody ? `: ${responseBody}` : ''}`);
|
|
7
|
+
this.name = 'CollectorError';
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.responseBody = responseBody;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,MAAM,CAAS;IACf,YAAY,CAAS;IAE9B,YAAY,MAAc,EAAE,IAAY,EAAE,MAAc,EAAE,YAAoB;QAC5E,KAAK,CAAC,aAAa,MAAM,IAAI,IAAI,qBAAqB,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/kafka.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Kafka record a test observed being consumed. The Collector reads the record's key and value
|
|
3
|
+
* from the broker itself, so only its coordinates are sent. Mirrors the Java consumer interceptor.
|
|
4
|
+
*/
|
|
5
|
+
export interface KafkaConsumerRead {
|
|
6
|
+
nameOfConsumingApp: string;
|
|
7
|
+
protocol: 'KAFKA Consumer';
|
|
8
|
+
topic: string;
|
|
9
|
+
partition: number;
|
|
10
|
+
offset: number;
|
|
11
|
+
}
|
package/dist/kafka.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kafka.js","sourceRoot":"","sources":["../src/kafka.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deployagram/logger-client",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "HTTP client for the Deployagram Collector (living-http-logger), built on fetch. Node.js 22+.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=22"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json",
|
|
28
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
29
|
+
"test": "vitest run"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@deployagram/api": "^0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.20.5",
|
|
36
|
+
"msw": "^3.0.4",
|
|
37
|
+
"typescript": "^7.0.2",
|
|
38
|
+
"vitest": "^5.1.0"
|
|
39
|
+
}
|
|
40
|
+
}
|