@gomessaging/messaging 0.0.1

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.
Files changed (47) hide show
  1. package/README.md +185 -0
  2. package/dist/cloudevents.d.ts +73 -0
  3. package/dist/cloudevents.d.ts.map +1 -0
  4. package/dist/cloudevents.js +148 -0
  5. package/dist/cloudevents.js.map +1 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +15 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/metrics.d.ts +40 -0
  11. package/dist/metrics.d.ts.map +1 -0
  12. package/dist/metrics.js +11 -0
  13. package/dist/metrics.js.map +1 -0
  14. package/dist/naming.d.ts +54 -0
  15. package/dist/naming.d.ts.map +1 -0
  16. package/dist/naming.js +78 -0
  17. package/dist/naming.js.map +1 -0
  18. package/dist/routing.d.ts +10 -0
  19. package/dist/routing.d.ts.map +1 -0
  20. package/dist/routing.js +41 -0
  21. package/dist/routing.js.map +1 -0
  22. package/dist/topology.d.ts +2 -0
  23. package/dist/topology.d.ts.map +1 -0
  24. package/dist/topology.js +4 -0
  25. package/dist/topology.js.map +1 -0
  26. package/dist/types.d.ts +73 -0
  27. package/dist/types.d.ts.map +1 -0
  28. package/dist/types.js +5 -0
  29. package/dist/types.js.map +1 -0
  30. package/dist/validate.d.ts +12 -0
  31. package/dist/validate.d.ts.map +1 -0
  32. package/dist/validate.js +138 -0
  33. package/dist/validate.js.map +1 -0
  34. package/dist/visualize.d.ts +10 -0
  35. package/dist/visualize.d.ts.map +1 -0
  36. package/dist/visualize.js +134 -0
  37. package/dist/visualize.js.map +1 -0
  38. package/package.json +34 -0
  39. package/src/cloudevents.ts +166 -0
  40. package/src/index.ts +86 -0
  41. package/src/metrics.ts +58 -0
  42. package/src/naming.ts +94 -0
  43. package/src/routing.ts +39 -0
  44. package/src/topology.ts +13 -0
  45. package/src/types.ts +101 -0
  46. package/src/validate.ts +183 -0
  47. package/src/visualize.ts +167 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Returns true if routingKey matches the binding pattern.
3
+ * Supports AMQP/NATS wildcard syntax: `*` matches one word, `#` matches zero or more.
4
+ */
5
+ export declare function matchRoutingKey(pattern: string, routingKey: string): boolean;
6
+ /**
7
+ * Returns true if two binding patterns could match the same routing key.
8
+ */
9
+ export declare function routingKeyOverlaps(p1: string, p2: string): boolean;
10
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAM5E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAKlE"}
@@ -0,0 +1,41 @@
1
+ // MIT License
2
+ // Copyright (c) 2026 sparetimecoders
3
+ /**
4
+ * Converts an AMQP/NATS binding pattern to a regular expression string.
5
+ *
6
+ * - `.` is escaped to `\.`
7
+ * - `*` matches a single word: `[^.]*`
8
+ * - `#` matches zero or more words: `.*`
9
+ */
10
+ function routingKeyToRegex(pattern) {
11
+ const escaped = pattern
12
+ .replaceAll(".", "\\.")
13
+ .replaceAll("*", "[^.]*")
14
+ .replaceAll("#", ".*");
15
+ return `^${escaped}$`;
16
+ }
17
+ /**
18
+ * Returns true if routingKey matches the binding pattern.
19
+ * Supports AMQP/NATS wildcard syntax: `*` matches one word, `#` matches zero or more.
20
+ */
21
+ export function matchRoutingKey(pattern, routingKey) {
22
+ try {
23
+ return new RegExp(routingKeyToRegex(pattern)).test(routingKey);
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ }
29
+ /**
30
+ * Returns true if two binding patterns could match the same routing key.
31
+ */
32
+ export function routingKeyOverlaps(p1, p2) {
33
+ if (p1 === p2)
34
+ return true;
35
+ if (matchRoutingKey(p1, p2))
36
+ return true;
37
+ if (matchRoutingKey(p2, p1))
38
+ return true;
39
+ return false;
40
+ }
41
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,qCAAqC;AAErC;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,OAAO,GAAG,OAAO;SACpB,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC;SACtB,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,OAAO,GAAG,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,UAAkB;IACjE,IAAI,CAAC;QACH,OAAO,IAAI,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAU,EAAE,EAAU;IACvD,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type { Transport, EndpointDirection, ExchangeKind, Pattern, Endpoint, Topology, } from "./types.js";
2
+ //# sourceMappingURL=topology.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topology.d.ts","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,QAAQ,GACT,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ // MIT License
2
+ // Copyright (c) 2026 sparetimecoders
3
+ export {};
4
+ //# sourceMappingURL=topology.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topology.js","sourceRoot":"","sources":["../src/topology.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,qCAAqC"}
@@ -0,0 +1,73 @@
1
+ /** Transport identifies the messaging transport implementation. */
2
+ export type Transport = "amqp" | "nats";
3
+ /** EndpointDirection indicates whether an endpoint publishes or consumes messages. */
4
+ export type EndpointDirection = "publish" | "consume";
5
+ /** ExchangeKind represents the type of an exchange. */
6
+ export type ExchangeKind = "topic" | "direct" | "headers";
7
+ /** Pattern identifies the communication pattern an endpoint participates in. */
8
+ export type Pattern = "event-stream" | "custom-stream" | "service-request" | "service-response" | "queue-publish";
9
+ /** Headers represent all meta-data for the message. */
10
+ export type Headers = Record<string, unknown>;
11
+ /** Metadata holds the metadata of an event. */
12
+ export interface Metadata {
13
+ id: string;
14
+ correlationId: string;
15
+ timestamp: string;
16
+ source: string;
17
+ type: string;
18
+ subject: string;
19
+ dataContentType: string;
20
+ specVersion: string;
21
+ }
22
+ /** DeliveryInfo holds transport-agnostic delivery metadata. */
23
+ export interface DeliveryInfo {
24
+ destination: string;
25
+ source: string;
26
+ key: string;
27
+ headers: Headers;
28
+ }
29
+ /** ConsumableEvent represents an event that can be consumed. */
30
+ export interface ConsumableEvent<T> extends Metadata {
31
+ deliveryInfo: DeliveryInfo;
32
+ payload: T;
33
+ }
34
+ /** Endpoint describes a single exchange/queue/binding that a service declares. */
35
+ export interface Endpoint {
36
+ direction: EndpointDirection;
37
+ pattern: Pattern;
38
+ exchangeName: string;
39
+ exchangeKind: ExchangeKind;
40
+ queueName?: string;
41
+ routingKey?: string;
42
+ messageType?: string;
43
+ ephemeral?: boolean;
44
+ }
45
+ /** Topology describes the full messaging topology declared by a single service. */
46
+ export interface Topology {
47
+ transport?: Transport;
48
+ serviceName: string;
49
+ endpoints: Endpoint[];
50
+ }
51
+ /** EventHandler is a function that handles events of a specific type. */
52
+ export type EventHandler<T> = (event: ConsumableEvent<T>) => Promise<void>;
53
+ /** RequestResponseEventHandler handles events and returns a response. */
54
+ export type RequestResponseEventHandler<T, R> = (event: ConsumableEvent<T>) => Promise<R>;
55
+ /** NotificationSource identifies the origin of a notification. */
56
+ export type NotificationSource = "CONSUMER";
57
+ /** Notification represents a successful event processing notification. */
58
+ export interface Notification {
59
+ deliveryInfo: DeliveryInfo;
60
+ durationMs: number;
61
+ source: NotificationSource;
62
+ }
63
+ /** ErrorNotification represents a failed event processing notification. */
64
+ export interface ErrorNotification extends Notification {
65
+ error: Error;
66
+ }
67
+ /** NotificationHandler is called after successful event processing. */
68
+ export type NotificationHandler = (n: Notification) => void;
69
+ /** ErrorNotificationHandler is called after failed event processing. */
70
+ export type ErrorNotificationHandler = (n: ErrorNotification) => void;
71
+ /** ErrParseJSON sentinel error message. */
72
+ export declare const ErrParseJSON = "failed to parse";
73
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAExC,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtD,uDAAuD;AACvD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1D,gFAAgF;AAChF,MAAM,MAAM,OAAO,GACf,cAAc,GACd,eAAe,GACf,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,CAAC;AAEpB,uDAAuD;AACvD,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,+CAA+C;AAC/C,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,gEAAgE;AAChE,MAAM,WAAW,eAAe,CAAC,CAAC,CAAE,SAAQ,QAAQ;IAClD,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,kFAAkF;AAClF,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAC5B,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,yEAAyE;AACzE,MAAM,MAAM,2BAA2B,CAAC,CAAC,EAAE,CAAC,IAAI,CAC9C,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KACtB,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAE5C,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,KAAK,EAAE,KAAK,CAAC;CACd;AAED,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAC;AAE5D,wEAAwE;AACxE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEtE,2CAA2C;AAC3C,eAAO,MAAM,YAAY,oBAAoB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ // MIT License
2
+ // Copyright (c) 2026 sparetimecoders
3
+ /** ErrParseJSON sentinel error message. */
4
+ export const ErrParseJSON = "failed to parse";
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,qCAAqC;AAkGrC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Topology } from "./types.js";
2
+ /**
3
+ * Validate checks a single service's topology for internal consistency.
4
+ * Returns null if valid, or an error message string if invalid.
5
+ */
6
+ export declare function validate(t: Topology): string | null;
7
+ /**
8
+ * ValidateTopologies checks cross-service consistency across multiple topologies.
9
+ * Returns null if valid, or an error message string if invalid.
10
+ */
11
+ export declare function validateTopologies(topologies: Topology[]): string | null;
12
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,QAAQ,EAAa,MAAM,YAAY,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CA2CnD;AA+DD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,IAAI,CA2BxE"}
@@ -0,0 +1,138 @@
1
+ // MIT License
2
+ // Copyright (c) 2026 sparetimecoders
3
+ /**
4
+ * Validate checks a single service's topology for internal consistency.
5
+ * Returns null if valid, or an error message string if invalid.
6
+ */
7
+ export function validate(t) {
8
+ if (!t.serviceName) {
9
+ return "service name must not be empty";
10
+ }
11
+ const errs = [];
12
+ for (let i = 0; i < (t.endpoints ?? []).length; i++) {
13
+ const ep = t.endpoints[i];
14
+ if (!ep.exchangeName) {
15
+ errs.push(`endpoint[${i}]: exchange name must not be empty`);
16
+ }
17
+ if (ep.direction === "consume" && !ep.queueName && !ep.ephemeral) {
18
+ errs.push(`endpoint[${i}]: consume endpoint must have a queue name`);
19
+ }
20
+ if (!ep.routingKey && ep.exchangeKind !== "headers") {
21
+ errs.push(`endpoint[${i}]: routing key must not be empty for ${ep.exchangeKind} exchange`);
22
+ }
23
+ if (ep.routingKey && ep.routingKey.includes(">")) {
24
+ errs.push(`endpoint[${i}]: routing key must not contain '>' (use '#' for multi-level wildcard)`);
25
+ }
26
+ const transportErr = validateExchangeNameForTransport(t.transport, ep, i);
27
+ if (transportErr) {
28
+ errs.push(transportErr);
29
+ }
30
+ }
31
+ return errs.length > 0 ? errs.join("\n") : null;
32
+ }
33
+ function validateExchangeNameForTransport(transport, ep, index) {
34
+ switch (transport) {
35
+ case "amqp":
36
+ return validateAMQPExchangeName(ep, index);
37
+ case "nats":
38
+ return validateNATSExchangeName(ep, index);
39
+ default:
40
+ return null;
41
+ }
42
+ }
43
+ function validateAMQPExchangeName(ep, index) {
44
+ const name = ep.exchangeName;
45
+ switch (ep.exchangeKind) {
46
+ case "topic":
47
+ if (!name.endsWith(".topic.exchange")) {
48
+ return `endpoint[${index}]: topic exchange "${name}" must end with .topic.exchange`;
49
+ }
50
+ break;
51
+ case "direct":
52
+ if (!name.endsWith(".direct.exchange.request")) {
53
+ return `endpoint[${index}]: direct exchange "${name}" must end with .direct.exchange.request`;
54
+ }
55
+ break;
56
+ case "headers":
57
+ if (!name.endsWith(".headers.exchange.response")) {
58
+ return `endpoint[${index}]: headers exchange "${name}" must end with .headers.exchange.response`;
59
+ }
60
+ break;
61
+ }
62
+ return null;
63
+ }
64
+ function validateNATSExchangeName(ep, index) {
65
+ const name = ep.exchangeName;
66
+ const amqpSuffixes = [
67
+ ".topic.exchange",
68
+ ".direct.exchange.request",
69
+ ".headers.exchange.response",
70
+ ];
71
+ for (const suffix of amqpSuffixes) {
72
+ if (name.endsWith(suffix)) {
73
+ return `endpoint[${index}]: NATS exchange "${name}" must not use AMQP suffix "${suffix}"`;
74
+ }
75
+ }
76
+ if (/[\s]/.test(name)) {
77
+ return `endpoint[${index}]: NATS exchange "${name}" must not contain whitespace`;
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * ValidateTopologies checks cross-service consistency across multiple topologies.
83
+ * Returns null if valid, or an error message string if invalid.
84
+ */
85
+ export function validateTopologies(topologies) {
86
+ const errs = [];
87
+ for (const t of topologies) {
88
+ const err = validate(t);
89
+ if (err) {
90
+ errs.push(`service "${t.serviceName}": ${err}`);
91
+ }
92
+ }
93
+ // Group topologies by transport for cross-validation.
94
+ const groups = new Map();
95
+ for (const t of topologies) {
96
+ const key = t.transport ?? "";
97
+ const group = groups.get(key) ?? [];
98
+ group.push(t);
99
+ groups.set(key, group);
100
+ }
101
+ for (const group of groups.values()) {
102
+ const err = crossValidateGroup(group);
103
+ if (err) {
104
+ errs.push(err);
105
+ }
106
+ }
107
+ return errs.length > 0 ? errs.join("\n") : null;
108
+ }
109
+ function crossValidateGroup(topologies) {
110
+ const errs = [];
111
+ // Build a set of all published routing keys per exchange.
112
+ const published = new Map(); // "exchange|routingKey" -> service name
113
+ for (const t of topologies) {
114
+ for (const ep of t.endpoints ?? []) {
115
+ if (ep.direction === "publish" && ep.routingKey) {
116
+ published.set(`${ep.exchangeName}|${ep.routingKey}`, t.serviceName);
117
+ }
118
+ }
119
+ }
120
+ // Check that each consumer has a matching publisher.
121
+ for (const t of topologies) {
122
+ for (const ep of t.endpoints ?? []) {
123
+ if (ep.direction !== "consume")
124
+ continue;
125
+ if (!ep.routingKey)
126
+ continue;
127
+ // Skip wildcard consumers.
128
+ if (/[#*>]/.test(ep.routingKey))
129
+ continue;
130
+ const key = `${ep.exchangeName}|${ep.routingKey}`;
131
+ if (!published.has(key)) {
132
+ errs.push(`service "${t.serviceName}" consumes "${ep.routingKey}" on exchange "${ep.exchangeName}" but no service publishes it`);
133
+ }
134
+ }
135
+ }
136
+ return errs.length > 0 ? errs.join("\n") : null;
137
+ }
138
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Topology } from "./types.js";
2
+ /**
3
+ * Generates a Mermaid flowchart diagram from one or more topologies.
4
+ * The diagram shows services as rectangle nodes, exchanges as shaped nodes
5
+ * (based on exchange kind), and edges for publish/consume relationships.
6
+ * When topologies use multiple transports, exchanges are grouped into
7
+ * subgraphs by transport (e.g. AMQP, NATS).
8
+ */
9
+ export declare function mermaid(topologies: Topology[]): string;
10
+ //# sourceMappingURL=visualize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualize.d.ts","sourceRoot":"","sources":["../src/visualize.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAoCzD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,CAwHtD"}
@@ -0,0 +1,134 @@
1
+ // MIT License
2
+ // Copyright (c) 2026 sparetimecoders
3
+ function sanitizeID(name) {
4
+ return name.replace(/[^a-zA-Z0-9_]/g, "_");
5
+ }
6
+ function exchangeNode(id, name, kind, indent) {
7
+ switch (kind) {
8
+ case "topic":
9
+ return `${indent}${id}{{"${name}"}}\n`;
10
+ case "headers":
11
+ return `${indent}${id}(("${name}"))\n`;
12
+ case "direct":
13
+ default:
14
+ return `${indent}${id}["${name}"]\n`;
15
+ }
16
+ }
17
+ /**
18
+ * Generates a Mermaid flowchart diagram from one or more topologies.
19
+ * The diagram shows services as rectangle nodes, exchanges as shaped nodes
20
+ * (based on exchange kind), and edges for publish/consume relationships.
21
+ * When topologies use multiple transports, exchanges are grouped into
22
+ * subgraphs by transport (e.g. AMQP, NATS).
23
+ */
24
+ export function mermaid(topologies) {
25
+ const services = new Set();
26
+ const exchanges = new Map();
27
+ const edges = [];
28
+ const transports = new Set();
29
+ for (const t of topologies) {
30
+ if (!t.serviceName)
31
+ continue;
32
+ services.add(t.serviceName);
33
+ if (t.transport) {
34
+ transports.add(t.transport);
35
+ }
36
+ for (const ep of t.endpoints) {
37
+ if (!ep.exchangeName)
38
+ continue;
39
+ exchanges.set(ep.exchangeName, {
40
+ kind: ep.exchangeKind,
41
+ transport: t.transport ?? "",
42
+ });
43
+ const arrow = ep.pattern === "service-response" ? "-.->" : "-->";
44
+ if (ep.direction === "publish") {
45
+ edges.push({
46
+ from: t.serviceName,
47
+ to: ep.exchangeName,
48
+ label: ep.routingKey ?? "",
49
+ style: arrow,
50
+ transport: t.transport ?? "",
51
+ });
52
+ }
53
+ else if (ep.direction === "consume") {
54
+ edges.push({
55
+ from: ep.exchangeName,
56
+ to: t.serviceName,
57
+ label: ep.routingKey ?? "",
58
+ style: arrow,
59
+ transport: t.transport ?? "",
60
+ });
61
+ }
62
+ }
63
+ }
64
+ const useSubgraphs = transports.size > 1;
65
+ const exchID = (transport, name) => {
66
+ if (useSubgraphs) {
67
+ return sanitizeID(`${transport}_${name}`);
68
+ }
69
+ return sanitizeID(name);
70
+ };
71
+ let out = "graph LR\n";
72
+ // Service nodes (sorted)
73
+ const sortedServices = [...services].sort();
74
+ for (const svc of sortedServices) {
75
+ out += ` ${sanitizeID(svc)}["${svc}"]\n`;
76
+ }
77
+ const sortedExchangeNames = [...exchanges.keys()].sort();
78
+ if (useSubgraphs) {
79
+ // Group exchanges by transport into subgraphs
80
+ const sortedTransports = [...transports].sort();
81
+ for (const tr of sortedTransports) {
82
+ out += ` subgraph ${tr.toUpperCase()}\n`;
83
+ for (const name of sortedExchangeNames) {
84
+ const entry = exchanges.get(name);
85
+ if (entry.transport !== tr)
86
+ continue;
87
+ out += exchangeNode(exchID(tr, name), name, entry.kind, " ");
88
+ }
89
+ out += " end\n";
90
+ }
91
+ }
92
+ else {
93
+ // Single transport or no transport — flat list (backward compatible)
94
+ for (const name of sortedExchangeNames) {
95
+ const entry = exchanges.get(name);
96
+ out += exchangeNode(exchID(entry.transport, name), name, entry.kind, " ");
97
+ }
98
+ }
99
+ // Edges (sorted by from/to/label for deterministic output)
100
+ edges.sort((a, b) => {
101
+ if (a.from !== b.from)
102
+ return a.from < b.from ? -1 : 1;
103
+ if (a.to !== b.to)
104
+ return a.to < b.to ? -1 : 1;
105
+ return a.label < b.label ? -1 : a.label > b.label ? 1 : 0;
106
+ });
107
+ for (const e of edges) {
108
+ const fromID = services.has(e.from)
109
+ ? sanitizeID(e.from)
110
+ : exchID(e.transport, e.from);
111
+ const toID = services.has(e.to)
112
+ ? sanitizeID(e.to)
113
+ : exchID(e.transport, e.to);
114
+ if (e.label) {
115
+ out += ` ${fromID} ${e.style}|"${e.label}"| ${toID}\n`;
116
+ }
117
+ else {
118
+ out += ` ${fromID} ${e.style} ${toID}\n`;
119
+ }
120
+ }
121
+ // Style declarations
122
+ if (sortedServices.length > 0) {
123
+ const ids = sortedServices.map(sanitizeID).join(",");
124
+ out += ` style ${ids} fill:#f9f,stroke:#333\n`;
125
+ }
126
+ if (sortedExchangeNames.length > 0) {
127
+ const ids = sortedExchangeNames
128
+ .map((name) => exchID(exchanges.get(name).transport, name))
129
+ .join(",");
130
+ out += ` style ${ids} fill:#bbf,stroke:#333\n`;
131
+ }
132
+ return out;
133
+ }
134
+ //# sourceMappingURL=visualize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualize.js","sourceRoot":"","sources":["../src/visualize.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@gomessaging/messaging",
3
+ "version": "0.0.1",
4
+ "description": "Messaging specification and shared types for the gomessaging libraries",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://codeberg.org/messaging/messaging.git",
9
+ "directory": "typescript"
10
+ },
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.build.json",
24
+ "test": "bun test",
25
+ "typecheck": "tsc --noEmit"
26
+ },
27
+ "devDependencies": {
28
+ "@types/bun": "latest",
29
+ "typescript": "5.9.3"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ }
34
+ }