@grest-ts/asyncapi 0.0.24 → 0.0.25
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/README.md +143 -0
- package/dist/src/GGAsyncApiDocs.d.ts +14 -0
- package/dist/src/GGAsyncApiDocs.d.ts.map +1 -1
- package/dist/src/GGAsyncApiDocs.js +16 -0
- package/dist/src/GGAsyncApiDocs.js.map +1 -1
- package/dist/src/GGAsyncApiDocsGroups.d.ts +70 -0
- package/dist/src/GGAsyncApiDocsGroups.d.ts.map +1 -0
- package/dist/src/GGAsyncApiDocsGroups.js +206 -0
- package/dist/src/GGAsyncApiDocsGroups.js.map +1 -0
- package/dist/src/index-node.d.ts +2 -0
- package/dist/src/index-node.d.ts.map +1 -1
- package/dist/src/index-node.js +1 -0
- package/dist/src/index-node.js.map +1 -1
- package/dist/src/tsconfig.json +1 -1
- package/dist/tsconfig.publish.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/GGAsyncApiDocs.ts +17 -0
- package/src/GGAsyncApiDocsGroups.ts +258 -0
- package/src/index-node.ts +2 -0
- package/src/tsconfig.json +1 -1
package/README.md
CHANGED
|
@@ -3,3 +3,146 @@
|
|
|
3
3
|
> [Documentation](https://github.com/grest-ts/grest-ts#readme) | [All packages](https://github.com/grest-ts/grest-ts#package-reference)
|
|
4
4
|
<!-- GREST-TS-BANNER-END -->
|
|
5
5
|
|
|
6
|
+
# @grest-ts/asyncapi
|
|
7
|
+
|
|
8
|
+
> **Optional package** — generates AsyncAPI 3.0 specs from your grest-ts WebSocket schemas and serves AsyncAPI Studio (the standard interactive viewer).
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **`toAsyncApi()`** — pure function, no side effects; safe in CI/build scripts for static spec export
|
|
13
|
+
- **`GGAsyncApiDocs`** — serves `GET /asyncapi.json` and `GET /asyncapi-docs` (AsyncAPI Studio); schemas auto-collected from the server
|
|
14
|
+
- **All four message patterns covered** — request/response, fire-and-forget, server push, and server-initiated request/response
|
|
15
|
+
- **Bearer / API-key handshake auth** — middleware headers with `format: "bearer"` or `format: "api-key"` become AsyncAPI `securitySchemes` automatically
|
|
16
|
+
- **Named schemas** — every `.docs({title})` schema is extracted to `components/schemas` and reused via `$ref` across messages
|
|
17
|
+
- **Symmetric error reporting** — every `errors:[…]` entry becomes its own typed reply message so the spec lists every possible response shape
|
|
18
|
+
- **Same `.docs()` passthrough as @grest-ts/openapi** — title, description, example, examples, deprecated all flow into the spec
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @grest-ts/asyncapi
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The package depends on `@grest-ts/openapi` for the schema converter, so you do not need to install both manually if you only want AsyncAPI — `npm install @grest-ts/asyncapi` brings everything.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Serve docs alongside your WebSocket APIs
|
|
31
|
+
|
|
32
|
+
`GGAsyncApiDocs.register()` mirrors the `MyApi.register()` pattern — pass `http` explicitly, or omit it to use the default `GGHttpServer` from the locator.
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import {GGAsyncApiDocs} from "@grest-ts/asyncapi";
|
|
36
|
+
import {GGHttpServer} from "@grest-ts/http";
|
|
37
|
+
import {ChatApi, NotificationApi} from "@myapp/api";
|
|
38
|
+
|
|
39
|
+
const server = new GGHttpServer();
|
|
40
|
+
ChatApi.register(chatHandler);
|
|
41
|
+
NotificationApi.register(notificationHandler);
|
|
42
|
+
|
|
43
|
+
GGAsyncApiDocs.register({
|
|
44
|
+
http: server, // optional — falls back to locator default
|
|
45
|
+
title: "My WebSocket APIs",
|
|
46
|
+
version: "1.0.0",
|
|
47
|
+
description: "Chat and notification events",
|
|
48
|
+
specPath: "/asyncapi.json",
|
|
49
|
+
docsPath: "/asyncapi-docs"
|
|
50
|
+
});
|
|
51
|
+
// GET /asyncapi.json → AsyncAPI 3.0 spec
|
|
52
|
+
// GET /asyncapi-docs → AsyncAPI Studio (sidebar deep links via /asyncapi-docs/* are also handled)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Explicit schema list
|
|
56
|
+
|
|
57
|
+
When you want to document schemas that are not registered on this server (e.g. a docs-only build, or sharing a common bundle), pass them in directly:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
GGAsyncApiDocs.register({
|
|
61
|
+
http: server,
|
|
62
|
+
schemas: [ChatApiSchema, NotificationApiSchema],
|
|
63
|
+
title: "WebSocket Showcase",
|
|
64
|
+
specPath: "/asyncapi.json",
|
|
65
|
+
docsPath: "/asyncapi-docs",
|
|
66
|
+
eager: true // build spec at construction time (default: lazy on first request)
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Export spec to a file (CI/scripts)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import {toAsyncApi} from "@grest-ts/asyncapi";
|
|
74
|
+
import {writeFileSync} from "fs";
|
|
75
|
+
|
|
76
|
+
const spec = toAsyncApi([ChatApiSchema, NotificationApiSchema], {
|
|
77
|
+
title: "My WebSocket APIs",
|
|
78
|
+
version: "2.0.0",
|
|
79
|
+
servers: {
|
|
80
|
+
production: {host: "api.example.com", protocol: "wss"}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
writeFileSync("asyncapi.json", JSON.stringify(spec, null, 2));
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Multi-spec switcher (`registerGroups`)
|
|
87
|
+
|
|
88
|
+
When one service exposes WebSocket APIs that consumers want to browse separately, register them as named groups. The studio is rendered with a small custom dropdown above it; switching the dropdown re-renders the studio with the chosen spec.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
GGAsyncApiDocs.registerGroups({
|
|
92
|
+
groups: {
|
|
93
|
+
"Chat": [ChatApiSchema],
|
|
94
|
+
"Notifications": [NotificationApiSchema],
|
|
95
|
+
},
|
|
96
|
+
title: "MyOrg Events",
|
|
97
|
+
specPathPrefix: "/asyncapi",
|
|
98
|
+
docsPath: "/asyncapi-docs",
|
|
99
|
+
primary: "Chat",
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Group names get kebab-cased into URL slugs. Because the AsyncAPI react-component does not have a native multi-spec switcher, the dropdown is rendered inside the page template (no public API around it).
|
|
104
|
+
|
|
105
|
+
For mixed HTTP + WebSocket setups, see [`@grest-ts/api-docs`](@pkg/api-docs) — it builds a unified shell that handles both protocols in one page.
|
|
106
|
+
|
|
107
|
+
## Message patterns
|
|
108
|
+
|
|
109
|
+
`@grest-ts/websocket` contracts can describe four interaction patterns; `toAsyncApi()` emits each one with the right `action` / `reply` shape:
|
|
110
|
+
|
|
111
|
+
| Contract shape | AsyncAPI emission |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `clientToServer` with `success` and/or `errors` | `action: send` + `reply` listing success and each error message |
|
|
114
|
+
| `clientToServer` with no `success` and no `errors` | `action: send` (fire-and-forget; no reply block) |
|
|
115
|
+
| `serverToClient` with `input` only | `action: receive` (server push; no reply block) |
|
|
116
|
+
| `serverToClient` with `success`/`errors` | `action: receive` + `reply` (server-initiated request/response) |
|
|
117
|
+
|
|
118
|
+
Every message gets a stable id (`<ChannelName>_<methodName>[_request|_response|_error_<TYPE>]`) so spec consumers can deep-link to a particular interaction.
|
|
119
|
+
|
|
120
|
+
## Auth
|
|
121
|
+
|
|
122
|
+
When a WebSocket schema uses a middleware whose header schema declares `.docs({format: "bearer"})` (or `"api-key"`), the converter:
|
|
123
|
+
|
|
124
|
+
1. Adds the corresponding entry to `components.securitySchemes` (using the header's `.docs({title})` if you provided one — defaults to `BearerAuth` / `ApiKeyAuth`).
|
|
125
|
+
2. Attaches a security requirement to every operation on that channel.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import {IsBearerToken} from "@grest-ts/schema";
|
|
129
|
+
|
|
130
|
+
export const ChatAuth = {
|
|
131
|
+
headers: {
|
|
132
|
+
"authorization": IsBearerToken.docs({description: "JWT access token for the chat channel"})
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const ChatApiSchema = webSocketSchema(ChatContract)
|
|
137
|
+
.path("ws/chat")
|
|
138
|
+
.use(ChatAuth)
|
|
139
|
+
.done();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Plain (non-security) handshake headers are emitted under the channel's `bindings.ws.headers` schema instead.
|
|
143
|
+
|
|
144
|
+
## Schema → JSON Schema mapping
|
|
145
|
+
|
|
146
|
+
The schema converter is shared with `@grest-ts/openapi` — the same `.docs({title, description, example, examples, deprecated})` annotations and `.default(value)` values flow into both specs. See the [@grest-ts/openapi mapping table](@pkg/openapi#schema-json-schema-mapping) for the full list.
|
|
147
|
+
|
|
148
|
+
A handful of post-processing steps adapt the output to AsyncAPI 3.0 conventions: `discriminator: {propertyName: "x"}` collapses to the plain string `"x"`, and `additionalProperties: false` is stripped from message payloads since it adds noise without value in documentation.
|
|
@@ -2,6 +2,7 @@ import type { GGWebSocketSchema } from "@grest-ts/websocket";
|
|
|
2
2
|
import { GGHttpServer } from "@grest-ts/http";
|
|
3
3
|
import type { AsyncAPIDocument } from "./AsyncApiTypes";
|
|
4
4
|
import { ToAsyncApiOptions } from "./toAsyncApi";
|
|
5
|
+
import { GGAsyncApiDocsGroupsOptions } from "./GGAsyncApiDocsGroups";
|
|
5
6
|
export interface GGAsyncApiDocsOptions extends ToAsyncApiOptions {
|
|
6
7
|
/**
|
|
7
8
|
* Path where the JSON spec is served.
|
|
@@ -65,6 +66,19 @@ export declare class GGAsyncApiDocs {
|
|
|
65
66
|
* - when absent, uses the default GGHttpServer from the locator
|
|
66
67
|
*/
|
|
67
68
|
static register(options: GGAsyncApiDocsOptions): void;
|
|
69
|
+
/**
|
|
70
|
+
* Register a multi-spec AsyncAPI Studio with one spec per group, switched
|
|
71
|
+
* via a small custom dropdown rendered above the studio. Useful when one
|
|
72
|
+
* service exposes WebSocket APIs that consumers want to browse separately.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* GGAsyncApiDocs.registerGroups({
|
|
76
|
+
* groups: { Chat: [ChatApiSchema], Notifications: [NotificationApiSchema] },
|
|
77
|
+
* specPathPrefix: "/asyncapi",
|
|
78
|
+
* docsPath: "/asyncapi-docs",
|
|
79
|
+
* });
|
|
80
|
+
*/
|
|
81
|
+
static registerGroups(options: GGAsyncApiDocsGroupsOptions): void;
|
|
68
82
|
constructor(server: GGHttpServer, options: GGAsyncApiDocsOptions);
|
|
69
83
|
private buildSpec;
|
|
70
84
|
getSpec(): AsyncAPIDocument;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GGAsyncApiDocs.d.ts","sourceRoot":"","sources":["../../src/GGAsyncApiDocs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAiB,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAa,iBAAiB,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"GGAsyncApiDocs.d.ts","sourceRoot":"","sources":["../../src/GGAsyncApiDocs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAiB,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAa,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAuB,2BAA2B,EAAC,MAAM,wBAAwB,CAAC;AAEzF,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC5D;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IAEvD;;;;OAIG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,KAAK,CAA+B;IAE5C;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAMrD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI;gBAIrD,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,qBAAqB;IAShE,OAAO,CAAC,SAAS;IAMV,OAAO,IAAI,gBAAgB;IAI3B,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;CAgClD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GG_HTTP_SERVER } from "@grest-ts/http";
|
|
2
2
|
import { GGLocator } from "@grest-ts/locator";
|
|
3
3
|
import { toAsyncApi } from "./toAsyncApi.js";
|
|
4
|
+
import { GGAsyncApiDocsGroups } from "./GGAsyncApiDocsGroups.js";
|
|
4
5
|
/**
|
|
5
6
|
* Serves GET /asyncapi.json and GET /asyncapi-docs (AsyncAPI Studio UI)
|
|
6
7
|
* for all WebSocket schemas registered on a GGHttpServer.
|
|
@@ -42,6 +43,21 @@ export class GGAsyncApiDocs {
|
|
|
42
43
|
throw new Error("GGAsyncApiDocs.register: no HTTP server found. Pass options.http or create a GGHttpServer first.");
|
|
43
44
|
new GGAsyncApiDocs(server, options);
|
|
44
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Register a multi-spec AsyncAPI Studio with one spec per group, switched
|
|
48
|
+
* via a small custom dropdown rendered above the studio. Useful when one
|
|
49
|
+
* service exposes WebSocket APIs that consumers want to browse separately.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* GGAsyncApiDocs.registerGroups({
|
|
53
|
+
* groups: { Chat: [ChatApiSchema], Notifications: [NotificationApiSchema] },
|
|
54
|
+
* specPathPrefix: "/asyncapi",
|
|
55
|
+
* docsPath: "/asyncapi-docs",
|
|
56
|
+
* });
|
|
57
|
+
*/
|
|
58
|
+
static registerGroups(options) {
|
|
59
|
+
GGAsyncApiDocsGroups.register(options);
|
|
60
|
+
}
|
|
45
61
|
constructor(server, options) {
|
|
46
62
|
this.server = server;
|
|
47
63
|
this.options = options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GGAsyncApiDocs.js","sourceRoot":"","sources":["../../src/GGAsyncApiDocs.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAC,UAAU,EAAoB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"GGAsyncApiDocs.js","sourceRoot":"","sources":["../../src/GGAsyncApiDocs.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAC,UAAU,EAAoB,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAC,oBAAoB,EAA8B,MAAM,wBAAwB,CAAC;AAkCzF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,cAAc;IACN,MAAM,CAAe;IACrB,OAAO,CAAwB;IACxC,KAAK,CAA+B;IAE5C;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,OAA8B;QAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,kGAAkG,CAAC,CAAC;QACjI,IAAI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,cAAc,CAAC,OAAoC;QACtD,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,YAAY,MAAoB,EAAE,OAA8B;QAC5D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAEO,SAAS;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO;eAC5B,IAAI,CAAC,MAAM,CAAC,0BAA2E,CAAC;QAChG,OAAO,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAEM,OAAO;QACV,OAAO,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;IAC3C,CAAC;IAEM,YAAY,CAAC,MAAoB;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;QAEvC,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;gBACf,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;aAC5C,CAAC,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,uEAAuE;QACvE,wEAAwE;QACxE,2DAA2D;QAC3D,MAAM,WAAW,GAAG,KAAK,EAAE,IAAS,EAAE,GAAQ,EAAE,EAAE;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;YAC3C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;gBACf,cAAc,EAAE,0BAA0B;gBAC1C,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;aAC5C,CAAC,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QACnD,sDAAsD;QACtD,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,WAAW,CAAC,CAAC;QAE1D,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AAED;;;;;;;;;GASG;AACH,SAAS,uBAAuB,CAAC,IAAsB;IACnD,qFAAqF;IACrF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO;;;;;;;;;;;;;;eAcI,QAAQ;;;;;QAKf,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { GGWebSocketSchema } from "@grest-ts/websocket";
|
|
2
|
+
import { GGHttpServer } from "@grest-ts/http";
|
|
3
|
+
import type { AsyncAPIDocument } from "./AsyncApiTypes";
|
|
4
|
+
import { ToAsyncApiOptions } from "./toAsyncApi";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration passed to `customUi` so the user can build their own switcher
|
|
7
|
+
* around the same per-group spec endpoints we serve.
|
|
8
|
+
*/
|
|
9
|
+
export interface AsyncApiSwitcherConfig {
|
|
10
|
+
title: string;
|
|
11
|
+
/** Each entry is one spec dropdown choice, in declaration order. */
|
|
12
|
+
urls: Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
url: string;
|
|
15
|
+
}>;
|
|
16
|
+
/** Which `name` opens by default. */
|
|
17
|
+
primaryName: string;
|
|
18
|
+
}
|
|
19
|
+
export interface GGAsyncApiDocsGroupsOptions extends ToAsyncApiOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Map of group label → WebSocket schemas in that group. Each group
|
|
22
|
+
* becomes its own AsyncAPI spec, served at `${specPathPrefix}/${slug}.json`.
|
|
23
|
+
*/
|
|
24
|
+
groups: Record<string, GGWebSocketSchema<any, any, any, any, any>[]>;
|
|
25
|
+
/** Path prefix for spec endpoints. e.g. `/asyncapi` → `/asyncapi/users.json`. */
|
|
26
|
+
specPathPrefix: string;
|
|
27
|
+
/** Path where the AsyncAPI Studio HTML is served. */
|
|
28
|
+
docsPath: string;
|
|
29
|
+
/** Which group opens by default. Must be a key of `groups`. */
|
|
30
|
+
primary?: string;
|
|
31
|
+
/** Build all specs eagerly at construction (default: lazy on first request). */
|
|
32
|
+
eager?: boolean;
|
|
33
|
+
/** Replace the AsyncAPI Studio HTML entirely. */
|
|
34
|
+
customUi?: (config: AsyncApiSwitcherConfig) => string;
|
|
35
|
+
/** Override the HTTP server. Defaults to the locator's GG_HTTP_SERVER. */
|
|
36
|
+
http?: GGHttpServer;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Multi-spec AsyncAPI Studio — one spec per logical group, switched via a
|
|
40
|
+
* small built-in dropdown rendered above the embedded studio.
|
|
41
|
+
*
|
|
42
|
+
* AsyncAPI's react-component does not have a native multi-spec switcher, so
|
|
43
|
+
* this package ships its own minimal one in the HTML template. The switcher
|
|
44
|
+
* is intentionally hidden inside the package (no public API), to keep the
|
|
45
|
+
* surface small.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* GGAsyncApiDocs.registerGroups({
|
|
49
|
+
* groups: {
|
|
50
|
+
* "Chat": [ChatApiSchema],
|
|
51
|
+
* "Notifications": [NotificationApiSchema],
|
|
52
|
+
* },
|
|
53
|
+
* specPathPrefix: "/asyncapi",
|
|
54
|
+
* docsPath: "/asyncapi-docs",
|
|
55
|
+
* });
|
|
56
|
+
*/
|
|
57
|
+
export declare class GGAsyncApiDocsGroups {
|
|
58
|
+
private readonly options;
|
|
59
|
+
private readonly groupKeys;
|
|
60
|
+
private readonly slugByGroup;
|
|
61
|
+
private readonly specCache;
|
|
62
|
+
static register(options: GGAsyncApiDocsGroupsOptions): void;
|
|
63
|
+
constructor(server: GGHttpServer, options: GGAsyncApiDocsGroupsOptions);
|
|
64
|
+
private buildSpec;
|
|
65
|
+
getSpec(group: string): AsyncAPIDocument;
|
|
66
|
+
buildSwitcherConfig(): AsyncApiSwitcherConfig;
|
|
67
|
+
registerWith(server: GGHttpServer): this;
|
|
68
|
+
private buildDocsHtml;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=GGAsyncApiDocsGroups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGAsyncApiDocsGroups.d.ts","sourceRoot":"","sources":["../../src/GGAsyncApiDocsGroups.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAiB,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAa,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAE3D;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACzC,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,2BAA4B,SAAQ,iBAAiB;IAClE;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAErE,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;IAEvB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IAEjB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,MAAM,CAAC;IAEtD,0EAA0E;IAC1E,IAAI,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IAEjE,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI;gBAM/C,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,2BAA2B;IAgBtE,OAAO,CAAC,SAAS;IAMV,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB;IASxC,mBAAmB,IAAI,sBAAsB;IAU7C,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAgC/C,OAAO,CAAC,aAAa;CAKxB"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { GG_HTTP_SERVER } from "@grest-ts/http";
|
|
2
|
+
import { GGLocator } from "@grest-ts/locator";
|
|
3
|
+
import { toAsyncApi } from "./toAsyncApi.js";
|
|
4
|
+
/**
|
|
5
|
+
* Multi-spec AsyncAPI Studio — one spec per logical group, switched via a
|
|
6
|
+
* small built-in dropdown rendered above the embedded studio.
|
|
7
|
+
*
|
|
8
|
+
* AsyncAPI's react-component does not have a native multi-spec switcher, so
|
|
9
|
+
* this package ships its own minimal one in the HTML template. The switcher
|
|
10
|
+
* is intentionally hidden inside the package (no public API), to keep the
|
|
11
|
+
* surface small.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* GGAsyncApiDocs.registerGroups({
|
|
15
|
+
* groups: {
|
|
16
|
+
* "Chat": [ChatApiSchema],
|
|
17
|
+
* "Notifications": [NotificationApiSchema],
|
|
18
|
+
* },
|
|
19
|
+
* specPathPrefix: "/asyncapi",
|
|
20
|
+
* docsPath: "/asyncapi-docs",
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
export class GGAsyncApiDocsGroups {
|
|
24
|
+
options;
|
|
25
|
+
groupKeys;
|
|
26
|
+
slugByGroup;
|
|
27
|
+
specCache = new Map();
|
|
28
|
+
static register(options) {
|
|
29
|
+
const server = options.http ?? GGLocator.getScope().get(GG_HTTP_SERVER);
|
|
30
|
+
if (!server)
|
|
31
|
+
throw new Error("GGAsyncApiDocsGroups.register: no HTTP server found. Pass options.http or create a GGHttpServer first.");
|
|
32
|
+
new GGAsyncApiDocsGroups(server, options);
|
|
33
|
+
}
|
|
34
|
+
constructor(server, options) {
|
|
35
|
+
this.options = options;
|
|
36
|
+
this.groupKeys = Object.keys(options.groups);
|
|
37
|
+
if (this.groupKeys.length === 0) {
|
|
38
|
+
throw new Error("GGAsyncApiDocsGroups: `groups` must contain at least one entry.");
|
|
39
|
+
}
|
|
40
|
+
this.slugByGroup = buildSlugMap(this.groupKeys);
|
|
41
|
+
if (options.primary !== undefined && !this.groupKeys.includes(options.primary)) {
|
|
42
|
+
throw new Error(`GGAsyncApiDocsGroups: \`primary\` must be a key of \`groups\` (got ${options.primary}).`);
|
|
43
|
+
}
|
|
44
|
+
if (options.eager) {
|
|
45
|
+
for (const name of this.groupKeys)
|
|
46
|
+
this.specCache.set(name, this.buildSpec(name));
|
|
47
|
+
}
|
|
48
|
+
this.registerWith(server);
|
|
49
|
+
}
|
|
50
|
+
buildSpec(group) {
|
|
51
|
+
const schemas = this.options.groups[group];
|
|
52
|
+
if (!schemas)
|
|
53
|
+
throw new Error(`GGAsyncApiDocsGroups: unknown group ${group}`);
|
|
54
|
+
return toAsyncApi(schemas, this.options);
|
|
55
|
+
}
|
|
56
|
+
getSpec(group) {
|
|
57
|
+
let spec = this.specCache.get(group);
|
|
58
|
+
if (!spec) {
|
|
59
|
+
spec = this.buildSpec(group);
|
|
60
|
+
this.specCache.set(group, spec);
|
|
61
|
+
}
|
|
62
|
+
return spec;
|
|
63
|
+
}
|
|
64
|
+
buildSwitcherConfig() {
|
|
65
|
+
const prefix = normalizePathPrefix(this.options.specPathPrefix);
|
|
66
|
+
const urls = this.groupKeys.map(name => ({
|
|
67
|
+
name,
|
|
68
|
+
url: `${prefix}/${this.slugByGroup.get(name)}.json`
|
|
69
|
+
}));
|
|
70
|
+
const primaryName = this.options.primary ?? this.groupKeys[0];
|
|
71
|
+
return { title: this.options.title ?? "API", urls, primaryName };
|
|
72
|
+
}
|
|
73
|
+
registerWith(server) {
|
|
74
|
+
const prefix = normalizePathPrefix(this.options.specPathPrefix);
|
|
75
|
+
for (const name of this.groupKeys) {
|
|
76
|
+
const slug = this.slugByGroup.get(name);
|
|
77
|
+
server.registerRoute("GET", `${prefix}/${slug}.json`, async (_req, res) => {
|
|
78
|
+
const spec = this.getSpec(name);
|
|
79
|
+
const body = JSON.stringify(spec, null, 2);
|
|
80
|
+
res.writeHead(200, {
|
|
81
|
+
"Content-Type": "application/json",
|
|
82
|
+
"Content-Length": Buffer.byteLength(body)
|
|
83
|
+
});
|
|
84
|
+
res.end(body);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const docsPath = this.options.docsPath;
|
|
88
|
+
const serveStudio = async (_req, res) => {
|
|
89
|
+
const html = this.buildDocsHtml();
|
|
90
|
+
res.writeHead(200, {
|
|
91
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
92
|
+
"Content-Length": Buffer.byteLength(html)
|
|
93
|
+
});
|
|
94
|
+
res.end(html);
|
|
95
|
+
};
|
|
96
|
+
server.registerRoute("GET", docsPath, serveStudio);
|
|
97
|
+
// Wildcard for sidebar deep-link navigation within the studio
|
|
98
|
+
server.registerRoute("GET", docsPath + "/*", serveStudio);
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
buildDocsHtml() {
|
|
102
|
+
const config = this.buildSwitcherConfig();
|
|
103
|
+
if (this.options.customUi)
|
|
104
|
+
return this.options.customUi(config);
|
|
105
|
+
return buildSwitcherHtml(config);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function normalizePathPrefix(prefix) {
|
|
109
|
+
let p = prefix.trim();
|
|
110
|
+
if (!p.startsWith("/"))
|
|
111
|
+
p = "/" + p;
|
|
112
|
+
return p.replace(/\/+$/, "");
|
|
113
|
+
}
|
|
114
|
+
function toSlug(name) {
|
|
115
|
+
return name
|
|
116
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
117
|
+
.toLowerCase()
|
|
118
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
119
|
+
.replace(/^-+|-+$/g, "")
|
|
120
|
+
|| "group";
|
|
121
|
+
}
|
|
122
|
+
function buildSlugMap(keys) {
|
|
123
|
+
const slugs = new Map();
|
|
124
|
+
const used = new Set();
|
|
125
|
+
for (const key of keys) {
|
|
126
|
+
const slug = toSlug(key);
|
|
127
|
+
if (used.has(slug)) {
|
|
128
|
+
throw new Error(`GGAsyncApiDocsGroups: group names produce duplicate slug "${slug}". Rename one of: ${keys.filter(k => toSlug(k) === slug).join(", ")}`);
|
|
129
|
+
}
|
|
130
|
+
used.add(slug);
|
|
131
|
+
slugs.set(key, slug);
|
|
132
|
+
}
|
|
133
|
+
return slugs;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* AsyncAPI Studio with a small custom switcher above it.
|
|
137
|
+
*
|
|
138
|
+
* The switcher is a plain `<select>` that fetches the chosen spec and
|
|
139
|
+
* re-renders the studio with the new schema. We hide the studio's own
|
|
140
|
+
* sidebar so the page stays uncluttered.
|
|
141
|
+
*/
|
|
142
|
+
function buildSwitcherHtml(config) {
|
|
143
|
+
const optionsHtml = config.urls.map(u => `<option value="${escapeHtml(u.url)}"${u.name === config.primaryName ? " selected" : ""}>${escapeHtml(u.name)}</option>`).join("");
|
|
144
|
+
return `<!DOCTYPE html>
|
|
145
|
+
<html lang="en">
|
|
146
|
+
<head>
|
|
147
|
+
<meta charset="UTF-8" />
|
|
148
|
+
<title>${escapeHtml(config.title)}</title>
|
|
149
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
150
|
+
<link rel="icon" href="https://www.asyncapi.com/favicon.ico" />
|
|
151
|
+
<link rel="stylesheet" href="https://unpkg.com/@asyncapi/react-component@latest/styles/default.min.css">
|
|
152
|
+
<style>
|
|
153
|
+
body { margin: 0; font-family: system-ui, -apple-system, sans-serif; }
|
|
154
|
+
.gg-switcher {
|
|
155
|
+
padding: 12px 20px;
|
|
156
|
+
background: #1a1a2e;
|
|
157
|
+
color: #fff;
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
gap: 16px;
|
|
161
|
+
border-bottom: 1px solid #2a2a3e;
|
|
162
|
+
}
|
|
163
|
+
.gg-switcher-title { font-weight: 600; font-size: 16px; }
|
|
164
|
+
.gg-switcher select {
|
|
165
|
+
padding: 6px 12px;
|
|
166
|
+
font-size: 14px;
|
|
167
|
+
background: #2a2a3e;
|
|
168
|
+
color: #fff;
|
|
169
|
+
border: 1px solid #3a3a4e;
|
|
170
|
+
border-radius: 4px;
|
|
171
|
+
cursor: pointer;
|
|
172
|
+
}
|
|
173
|
+
</style>
|
|
174
|
+
</head>
|
|
175
|
+
<body>
|
|
176
|
+
<div class="gg-switcher">
|
|
177
|
+
<span class="gg-switcher-title">${escapeHtml(config.title)}</span>
|
|
178
|
+
<label>
|
|
179
|
+
<span style="margin-right: 8px;">Spec:</span>
|
|
180
|
+
<select id="gg-spec-switcher">${optionsHtml}</select>
|
|
181
|
+
</label>
|
|
182
|
+
</div>
|
|
183
|
+
<div id="asyncapi"></div>
|
|
184
|
+
<script src="https://unpkg.com/@asyncapi/react-component@latest/browser/standalone/index.js"></script>
|
|
185
|
+
<script>
|
|
186
|
+
const switcher = document.getElementById('gg-spec-switcher');
|
|
187
|
+
const container = document.getElementById('asyncapi');
|
|
188
|
+
async function loadSpec(url) {
|
|
189
|
+
const res = await fetch(url);
|
|
190
|
+
const schema = await res.json();
|
|
191
|
+
container.innerHTML = '';
|
|
192
|
+
AsyncApiStandalone.render(
|
|
193
|
+
{schema: schema, config: {show: {sidebar: true}}},
|
|
194
|
+
container
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
switcher.addEventListener('change', e => loadSpec(e.target.value));
|
|
198
|
+
loadSpec(switcher.value);
|
|
199
|
+
</script>
|
|
200
|
+
</body>
|
|
201
|
+
</html>`;
|
|
202
|
+
}
|
|
203
|
+
function escapeHtml(s) {
|
|
204
|
+
return s.replace(/[&<>"']/g, c => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=GGAsyncApiDocsGroups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGAsyncApiDocsGroups.js","sourceRoot":"","sources":["../../src/GGAsyncApiDocsGroups.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index-node.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export { toAsyncApi } from "./toAsyncApi";
|
|
|
2
2
|
export type { ToAsyncApiOptions } from "./toAsyncApi";
|
|
3
3
|
export { GGAsyncApiDocs } from "./GGAsyncApiDocs";
|
|
4
4
|
export type { GGAsyncApiDocsOptions } from "./GGAsyncApiDocs";
|
|
5
|
+
export { GGAsyncApiDocsGroups } from "./GGAsyncApiDocsGroups";
|
|
6
|
+
export type { GGAsyncApiDocsGroupsOptions, AsyncApiSwitcherConfig } from "./GGAsyncApiDocsGroups";
|
|
5
7
|
export { GGAsyncApiDocs as GGAsyncApiServer } from "./GGAsyncApiDocs";
|
|
6
8
|
export type { GGAsyncApiDocsOptions as GGAsyncApiServerOptions } from "./GGAsyncApiDocs";
|
|
7
9
|
//# sourceMappingURL=index-node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-node.d.ts","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,YAAY,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index-node.d.ts","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,YAAY,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AACpD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAC,2BAA2B,EAAE,sBAAsB,EAAC,MAAM,wBAAwB,CAAC;AAEhG,OAAO,EAAC,cAAc,IAAI,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AACpE,YAAY,EAAC,qBAAqB,IAAI,uBAAuB,EAAC,MAAM,kBAAkB,CAAC"}
|
package/dist/src/index-node.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { toAsyncApi } from "./toAsyncApi.js";
|
|
2
2
|
export { GGAsyncApiDocs } from "./GGAsyncApiDocs.js";
|
|
3
|
+
export { GGAsyncApiDocsGroups } from "./GGAsyncApiDocsGroups.js";
|
|
3
4
|
// Backward-compatible aliases
|
|
4
5
|
export { GGAsyncApiDocs as GGAsyncApiServer } from "./GGAsyncApiDocs.js";
|
|
5
6
|
//# sourceMappingURL=index-node.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-node.js","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AAExC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAEhD,8BAA8B;AAC9B,OAAO,EAAC,cAAc,IAAI,gBAAgB,EAAC,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index-node.js","sourceRoot":"","sources":["../../src/index-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AAExC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAE5D,8BAA8B;AAC9B,OAAO,EAAC,cAAc,IAAI,gBAAgB,EAAC,MAAM,kBAAkB,CAAC"}
|