@apiboost/omnispec 1.0.0 → 1.1.0-next.2

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 (95) hide show
  1. package/dist/cjs/asyncapi/index.js +5 -5
  2. package/dist/cjs/chunks/AsyncApiSpec-Bj1F8C5K.js +2601 -0
  3. package/dist/cjs/chunks/AsyncApiSpec-Bj1F8C5K.js.map +1 -0
  4. package/dist/cjs/chunks/{Collapsible-BHAHk_Ep.js → Collapsible-BTWyDBkX.js} +429 -209
  5. package/dist/cjs/chunks/Collapsible-BTWyDBkX.js.map +1 -0
  6. package/dist/cjs/chunks/{ErrorBoundary-c1piU8da.js → ErrorBoundary-CezYgQDG.js} +2 -2
  7. package/dist/cjs/chunks/{ErrorBoundary-c1piU8da.js.map → ErrorBoundary-CezYgQDG.js.map} +1 -1
  8. package/dist/cjs/chunks/{OmniSpecRenderer-CE4wxVTL.js → OmniSpecRenderer-CghCPNuw.js} +6 -6
  9. package/dist/cjs/chunks/{OmniSpecRenderer-CE4wxVTL.js.map → OmniSpecRenderer-CghCPNuw.js.map} +1 -1
  10. package/dist/cjs/chunks/{OpenApiSpec-D0JtmOVQ.js → OpenApiSpec-BOlesoUX.js} +12 -12
  11. package/dist/cjs/chunks/OpenApiSpec-BOlesoUX.js.map +1 -0
  12. package/dist/cjs/chunks/{OpenIdConnectManual-oEnN0QJ-.js → OpenIdConnectManual-Bh7tdxoH.js} +7 -227
  13. package/dist/cjs/chunks/OpenIdConnectManual-Bh7tdxoH.js.map +1 -0
  14. package/dist/cjs/chunks/{ref-resolver-DWu6Q6E5.js → ref-resolver-0A8GNRI3.js} +6 -2
  15. package/dist/cjs/chunks/{ref-resolver-DWu6Q6E5.js.map → ref-resolver-0A8GNRI3.js.map} +1 -1
  16. package/dist/cjs/chunks/{useSpecDetector-A4OwYrmY.js → useSpecDetector-BemsWW9u.js} +2 -2
  17. package/dist/cjs/chunks/{useSpecDetector-A4OwYrmY.js.map → useSpecDetector-BemsWW9u.js.map} +1 -1
  18. package/dist/cjs/chunks/{useSpecFetcher-BKz1jHTV.js → useSpecFetcher-BAbHnXax.js} +28 -1
  19. package/dist/{esm/chunks/useSpecFetcher-CZvAnU7Z.js.map → cjs/chunks/useSpecFetcher-BAbHnXax.js.map} +1 -1
  20. package/dist/cjs/core/public.js +5 -5
  21. package/dist/cjs/index.js +9 -9
  22. package/dist/cjs/openapi/index.js +6 -6
  23. package/dist/cjs/wc/index.js +4 -4
  24. package/dist/esm/asyncapi/index.js +5 -5
  25. package/dist/esm/chunks/AsyncApiSpec-BzhfaQ_T.js +2599 -0
  26. package/dist/esm/chunks/AsyncApiSpec-BzhfaQ_T.js.map +1 -0
  27. package/dist/esm/chunks/{Collapsible-DA6-nS46.js → Collapsible-MyJB2agz.js} +428 -211
  28. package/dist/esm/chunks/Collapsible-MyJB2agz.js.map +1 -0
  29. package/dist/esm/chunks/{ErrorBoundary-posRNrbt.js → ErrorBoundary-9pDlZFfM.js} +2 -2
  30. package/dist/esm/chunks/{ErrorBoundary-posRNrbt.js.map → ErrorBoundary-9pDlZFfM.js.map} +1 -1
  31. package/dist/esm/chunks/{OmniSpecRenderer-MqsQFXro.js → OmniSpecRenderer-BUJSl_2I.js} +6 -6
  32. package/dist/esm/chunks/{OmniSpecRenderer-MqsQFXro.js.map → OmniSpecRenderer-BUJSl_2I.js.map} +1 -1
  33. package/dist/esm/chunks/{OpenApiSpec-Cy-oW6jA.js → OpenApiSpec-wm3tH2vF.js} +6 -6
  34. package/dist/esm/chunks/OpenApiSpec-wm3tH2vF.js.map +1 -0
  35. package/dist/esm/chunks/{OpenIdConnectManual-COfITasf.js → OpenIdConnectManual-DPmTIIIy.js} +6 -223
  36. package/dist/esm/chunks/OpenIdConnectManual-DPmTIIIy.js.map +1 -0
  37. package/dist/esm/chunks/{ref-resolver-BIrHJOjz.js → ref-resolver-B0C36NuQ.js} +6 -3
  38. package/dist/esm/chunks/{ref-resolver-BIrHJOjz.js.map → ref-resolver-B0C36NuQ.js.map} +1 -1
  39. package/dist/esm/chunks/{useSpecDetector-5SGcKnJx.js → useSpecDetector-BJBNbfN5.js} +2 -2
  40. package/dist/esm/chunks/{useSpecDetector-5SGcKnJx.js.map → useSpecDetector-BJBNbfN5.js.map} +1 -1
  41. package/dist/esm/chunks/{useSpecFetcher-CZvAnU7Z.js → useSpecFetcher-BvVfMuzf.js} +28 -1
  42. package/dist/{cjs/chunks/useSpecFetcher-BKz1jHTV.js.map → esm/chunks/useSpecFetcher-BvVfMuzf.js.map} +1 -1
  43. package/dist/esm/core/public.js +4 -4
  44. package/dist/esm/index.js +9 -9
  45. package/dist/esm/openapi/index.js +6 -6
  46. package/dist/esm/wc/index.js +4 -4
  47. package/dist/types/asyncapi/AsyncApiSpec.d.ts +1 -1
  48. package/dist/types/asyncapi/AsyncApiSpec.d.ts.map +1 -1
  49. package/dist/types/asyncapi/components/AsyncOverview.d.ts.map +1 -1
  50. package/dist/types/asyncapi/components/BindingsSection.d.ts +26 -0
  51. package/dist/types/asyncapi/components/BindingsSection.d.ts.map +1 -0
  52. package/dist/types/asyncapi/components/ChannelDetail.d.ts +7 -2
  53. package/dist/types/asyncapi/components/ChannelDetail.d.ts.map +1 -1
  54. package/dist/types/asyncapi/components/ChannelReferenceDetail.d.ts +35 -0
  55. package/dist/types/asyncapi/components/ChannelReferenceDetail.d.ts.map +1 -0
  56. package/dist/types/asyncapi/components/ComponentsSection.d.ts +1 -1
  57. package/dist/types/asyncapi/components/ComponentsSection.d.ts.map +1 -1
  58. package/dist/types/asyncapi/components/ExternalDocsLink.d.ts +29 -0
  59. package/dist/types/asyncapi/components/ExternalDocsLink.d.ts.map +1 -0
  60. package/dist/types/asyncapi/components/MessagePayload.d.ts +22 -0
  61. package/dist/types/asyncapi/components/MessagePayload.d.ts.map +1 -0
  62. package/dist/types/asyncapi/components/SecurityRequirementBadges.d.ts +29 -0
  63. package/dist/types/asyncapi/components/SecurityRequirementBadges.d.ts.map +1 -0
  64. package/dist/types/asyncapi/components/SecuritySchemesSection.d.ts +23 -0
  65. package/dist/types/asyncapi/components/SecuritySchemesSection.d.ts.map +1 -0
  66. package/dist/types/asyncapi/components/ServerList.d.ts +1 -1
  67. package/dist/types/asyncapi/components/ServerList.d.ts.map +1 -1
  68. package/dist/types/asyncapi/components/TagGroupHeader.d.ts +18 -0
  69. package/dist/types/asyncapi/components/TagGroupHeader.d.ts.map +1 -0
  70. package/dist/types/asyncapi/components/field-display.d.ts +30 -0
  71. package/dist/types/asyncapi/components/field-display.d.ts.map +1 -0
  72. package/dist/types/asyncapi/parser/asyncapi-parser.d.ts.map +1 -1
  73. package/dist/types/asyncapi/schema-formats.d.ts +26 -0
  74. package/dist/types/asyncapi/schema-formats.d.ts.map +1 -0
  75. package/dist/types/asyncapi/tag-grouping.d.ts +43 -0
  76. package/dist/types/asyncapi/tag-grouping.d.ts.map +1 -0
  77. package/dist/types/asyncapi/types/asyncapi.types.d.ts +72 -8
  78. package/dist/types/asyncapi/types/asyncapi.types.d.ts.map +1 -1
  79. package/dist/types/core/components/Layout/DocLayout.d.ts.map +1 -1
  80. package/dist/types/core/types/auth.types.d.ts +1 -1
  81. package/dist/types/openapi/parser/ref-resolver.d.ts +8 -0
  82. package/dist/types/openapi/parser/ref-resolver.d.ts.map +1 -1
  83. package/dist/wc/standalone.js +1 -1
  84. package/dist/wc/standalone.js.map +1 -1
  85. package/package.json +2 -2
  86. package/dist/cjs/chunks/AsyncApiSpec-TBlyRxTP.js +0 -819
  87. package/dist/cjs/chunks/AsyncApiSpec-TBlyRxTP.js.map +0 -1
  88. package/dist/cjs/chunks/Collapsible-BHAHk_Ep.js.map +0 -1
  89. package/dist/cjs/chunks/OpenApiSpec-D0JtmOVQ.js.map +0 -1
  90. package/dist/cjs/chunks/OpenIdConnectManual-oEnN0QJ-.js.map +0 -1
  91. package/dist/esm/chunks/AsyncApiSpec-C3lsUpZk.js +0 -817
  92. package/dist/esm/chunks/AsyncApiSpec-C3lsUpZk.js.map +0 -1
  93. package/dist/esm/chunks/Collapsible-DA6-nS46.js.map +0 -1
  94. package/dist/esm/chunks/OpenApiSpec-Cy-oW6jA.js.map +0 -1
  95. package/dist/esm/chunks/OpenIdConnectManual-COfITasf.js.map +0 -1
@@ -0,0 +1,2599 @@
1
+ import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
+ import { useCallback, Fragment, useState, useMemo } from 'react';
3
+ import { cx, css } from '@emotion/css';
4
+ import { a as useSpecFetcher, I as Icon, m as mq, r as resolveSchemaStyle, S as SpecType, T as ThemeProvider, L as LoadingScreen, b as SpecStatusScreen, E as ErrorMessage, N as NavTree, h as buildSidebar, C as ConfigProvider, e as DocLayout } from './useSpecFetcher-BvVfMuzf.js';
5
+ import { M as MarkdownRenderer, C as CodeBlock, T as Tabs, t as SchemaTree, A as schemaToNodes, x as generateExample, J as ExampleSelector, d as ExpandableCard, f as MethodBar, K as buildConstraints, S as SchemaBadge, R as ReferenceLayout, a as Collapsible, D as useHashScroll, y as requestExpand, w as flattenNavItemIds, G as useScrollSpy, u as SearchBar, L as ExpandProvider, v as SpecToolbar, z as resolveDownloadLink } from './Collapsible-MyJB2agz.js';
6
+ import { E as ErrorBoundary } from './ErrorBoundary-9pDlZFfM.js';
7
+ import { r as resolveRefs, p as parse, d as decodeJsonPointerSegment } from './ref-resolver-B0C36NuQ.js';
8
+ import '@emotion/styled';
9
+ import './ssrf-guard-CsZoYdEq.js';
10
+
11
+ function mergeSchema(base, override) {
12
+ if (!base) return override;
13
+ if (!override) return base;
14
+ const result = { ...base, ...override };
15
+ const baseProps = base.properties;
16
+ const overrideProps = override.properties;
17
+ if (baseProps || overrideProps) {
18
+ result.properties = { ...baseProps ?? {}, ...overrideProps ?? {} };
19
+ }
20
+ const required = Array.from(
21
+ /* @__PURE__ */ new Set([...base.required ?? [], ...override.required ?? []])
22
+ );
23
+ if (required.length > 0) result.required = required;
24
+ return result;
25
+ }
26
+ function mergeMessageLayer(base, override) {
27
+ const result = { ...base };
28
+ for (const [key, value] of Object.entries(override)) {
29
+ if (key === "traits" || value === void 0) continue;
30
+ if (key === "headers") {
31
+ result.headers = mergeSchema(base.headers, value);
32
+ } else if (key === "examples") {
33
+ result.examples = [...base.examples ?? [], ...value ?? []];
34
+ } else if (key === "bindings") {
35
+ result.bindings = { ...base.bindings ?? {}, ...value };
36
+ } else {
37
+ result[key] = value;
38
+ }
39
+ }
40
+ return result;
41
+ }
42
+ function applyMessageTraits(msg, isV3) {
43
+ if (!msg.traits || msg.traits.length === 0) return msg;
44
+ if (isV3) {
45
+ let acc2 = {};
46
+ for (const trait of msg.traits) acc2 = mergeMessageLayer(acc2, trait);
47
+ return mergeMessageLayer(acc2, msg);
48
+ }
49
+ let acc = msg;
50
+ for (const trait of msg.traits) acc = mergeMessageLayer(acc, trait);
51
+ return acc;
52
+ }
53
+ function mergeOperationLayer(base, override) {
54
+ const result = { ...base };
55
+ for (const [key, value] of Object.entries(override)) {
56
+ if (key === "traits" || value === void 0) continue;
57
+ if (key === "bindings") {
58
+ result.bindings = { ...base.bindings ?? {}, ...value };
59
+ } else {
60
+ result[key] = value;
61
+ }
62
+ }
63
+ return result;
64
+ }
65
+ function applyOperationTraits(op, isV3) {
66
+ if (!op.traits || op.traits.length === 0) return op;
67
+ if (isV3) {
68
+ let acc2 = {};
69
+ for (const trait of op.traits) acc2 = mergeOperationLayer(acc2, trait);
70
+ return mergeOperationLayer(acc2, op);
71
+ }
72
+ let acc = op;
73
+ for (const trait of op.traits) acc = mergeOperationLayer(acc, trait);
74
+ return acc;
75
+ }
76
+ async function parseAsyncApiSpec(specInput) {
77
+ const raw = typeof specInput === "string" ? parseSpecString(specInput) : specInput;
78
+ const api = await resolveRefs(raw);
79
+ const majorVersion = parseInt(api.asyncapi.split(".")[0], 10);
80
+ const isV3 = majorVersion >= 3;
81
+ const servers = extractServers(api, raw);
82
+ const rawApi = raw;
83
+ const defaultContentType = api.defaultContentType;
84
+ const channels = isV3 ? extractChannelsV3(api, rawApi, defaultContentType) : extractChannelsV2(api, defaultContentType);
85
+ const components = extractComponents(api, isV3, defaultContentType);
86
+ const root = api;
87
+ const tags = api.tags?.map((tag) => {
88
+ const raw2 = tag;
89
+ return {
90
+ name: tag.name,
91
+ description: tag.description,
92
+ displayName: raw2["x-displayName"],
93
+ externalDocs: raw2.externalDocs
94
+ };
95
+ })?.filter((tag) => !tag["x-internal"]);
96
+ return {
97
+ title: api.info.title,
98
+ description: api.info.description,
99
+ version: api.info.version,
100
+ specVersion: api.asyncapi,
101
+ servers,
102
+ channels: channels.filter((ch) => !ch.xInternal),
103
+ components,
104
+ tags,
105
+ tagGroups: root["x-tagGroups"],
106
+ externalDocs: api.externalDocs,
107
+ contact: api.info.contact,
108
+ license: api.info.license,
109
+ termsOfService: api.info.termsOfService,
110
+ logo: api.info["x-logo"],
111
+ defaultContentType
112
+ };
113
+ }
114
+ function extractServers(api, rawApi) {
115
+ if (!api.servers) return [];
116
+ const isV3 = parseInt(api.asyncapi.split(".")[0], 10) >= 3;
117
+ const toServer = (s, name, rawSecurity) => ({
118
+ name,
119
+ url: s.host ? `${s.protocol}://${s.host}${s.pathname ?? ""}` : s.url ?? "",
120
+ protocol: s.protocol,
121
+ protocolVersion: s.protocolVersion,
122
+ description: s.description,
123
+ variables: s.variables,
124
+ security: s.security,
125
+ securityNames: deriveSecurityNames(rawSecurity, s.security),
126
+ securityRequirements: deriveSecurityRequirements(rawSecurity, s.security, isV3),
127
+ bindings: s.bindings
128
+ });
129
+ if (Array.isArray(api.servers)) {
130
+ const rawServers2 = Array.isArray(rawApi.servers) ? rawApi.servers : [];
131
+ return api.servers.map((s, idx) => toServer(s, s.name ?? `server-${idx}`, rawServers2[idx]?.security));
132
+ }
133
+ const rawServers = !Array.isArray(rawApi.servers) && rawApi.servers || {};
134
+ return Object.entries(api.servers).map(([name, s]) => toServer(s, name, rawServers[name]?.security));
135
+ }
136
+ function extractChannelsV2(api, defaultContentType) {
137
+ if (!api.channels) return [];
138
+ return Object.entries(api.channels).map(([channelName, ch]) => {
139
+ const operations = [];
140
+ if (ch.publish) {
141
+ operations.push(convertOperationV2("publish", ch.publish, defaultContentType));
142
+ }
143
+ if (ch.subscribe) {
144
+ operations.push(convertOperationV2("subscribe", ch.subscribe, defaultContentType));
145
+ }
146
+ const raw = ch;
147
+ return {
148
+ name: channelName,
149
+ address: channelName,
150
+ description: ch.description,
151
+ operations: operations.filter((op) => !op.xInternal),
152
+ parameters: ch.parameters,
153
+ bindings: ch.bindings,
154
+ // 2.x channels have no externalDocs or channel-level tags.
155
+ xInternal: raw["x-internal"]
156
+ };
157
+ });
158
+ }
159
+ function convertOperationV2(action, rawOp, defaultContentType) {
160
+ const op = applyOperationTraits(rawOp, false);
161
+ const messages = [];
162
+ if (op.message) {
163
+ if ("oneOf" in op.message) {
164
+ for (const m of op.message.oneOf) {
165
+ messages.push(convertMessage(m, false, defaultContentType));
166
+ }
167
+ } else {
168
+ messages.push(convertMessage(op.message, false, defaultContentType));
169
+ }
170
+ }
171
+ const raw = op;
172
+ return {
173
+ action,
174
+ operationId: op.operationId,
175
+ summary: op.summary,
176
+ description: op.description,
177
+ messages,
178
+ message: messages[0],
179
+ tags: op.tags,
180
+ bindings: op.bindings,
181
+ externalDocs: op.externalDocs,
182
+ securityNames: deriveSecurityNames(void 0, op.security),
183
+ securityRequirements: deriveSecurityRequirements(void 0, op.security, false),
184
+ xBadges: raw["x-badges"],
185
+ xInternal: raw["x-internal"]
186
+ };
187
+ }
188
+ function resolveChannelName(rawChannel, resolvedChannel, addressToName) {
189
+ const refString = rawChannel && typeof rawChannel === "object" && "$ref" in rawChannel && typeof rawChannel.$ref === "string" ? rawChannel.$ref : resolvedChannel && typeof resolvedChannel === "object" && "$ref" in resolvedChannel && typeof resolvedChannel.$ref === "string" ? resolvedChannel.$ref : void 0;
190
+ if (refString) {
191
+ const last = refString.split("/").pop();
192
+ return last !== void 0 ? decodeJsonPointerSegment(last) : void 0;
193
+ }
194
+ const address = resolvedChannel?.address;
195
+ if (address && addressToName.has(address)) {
196
+ return addressToName.get(address);
197
+ }
198
+ return void 0;
199
+ }
200
+ function extractChannelsV3(api, rawApi, defaultContentType) {
201
+ if (!api.channels) return [];
202
+ const channelMap = /* @__PURE__ */ new Map();
203
+ const addressToName = /* @__PURE__ */ new Map();
204
+ for (const [channelName, ch] of Object.entries(api.channels)) {
205
+ const raw = ch;
206
+ const address = ch.address ?? channelName;
207
+ addressToName.set(address, channelName);
208
+ channelMap.set(channelName, {
209
+ name: channelName,
210
+ address,
211
+ description: ch.description,
212
+ operations: [],
213
+ parameters: ch.parameters,
214
+ bindings: ch.bindings,
215
+ externalDocs: ch.externalDocs,
216
+ tags: ch.tags,
217
+ xInternal: raw["x-internal"]
218
+ });
219
+ }
220
+ const orphanOperations = [];
221
+ if (api.operations) {
222
+ for (const [opKey, resolvedOp] of Object.entries(api.operations)) {
223
+ const op = applyOperationTraits(resolvedOp, true);
224
+ const rawOp = rawApi.operations?.[opKey];
225
+ const channelName = resolveChannelName(rawOp?.channel, op.channel, addressToName);
226
+ const collectMessages = (list) => {
227
+ const out = [];
228
+ for (const msg of list ?? []) {
229
+ if (msg && typeof msg === "object" && "$ref" in msg) continue;
230
+ out.push(convertMessage(msg, true, defaultContentType));
231
+ }
232
+ return out;
233
+ };
234
+ let messages = collectMessages(op.messages);
235
+ if (messages.length === 0 && channelName && api.channels?.[channelName]?.messages) {
236
+ messages = collectMessages(
237
+ Object.values(api.channels[channelName].messages)
238
+ );
239
+ }
240
+ const replyMessages = collectMessages(op.reply?.messages);
241
+ const rawReplyChannel = rawOp?.reply?.channel;
242
+ const replyChannelName = resolveChannelName(
243
+ rawReplyChannel,
244
+ op.reply?.channel,
245
+ addressToName
246
+ );
247
+ const raw = op;
248
+ const reply = replyMessages.length > 0 || op.reply?.address || replyChannelName ? {
249
+ messages: replyMessages,
250
+ address: op.reply?.address,
251
+ channelName: replyChannelName
252
+ } : void 0;
253
+ const operation = {
254
+ action: op.action,
255
+ // 3.x has no operationId field; the operations-map key is the id.
256
+ operationId: opKey,
257
+ title: op.title,
258
+ summary: op.summary,
259
+ description: op.description,
260
+ messages,
261
+ message: messages[0],
262
+ tags: op.tags,
263
+ bindings: op.bindings,
264
+ externalDocs: op.externalDocs,
265
+ securityNames: deriveSecurityNames(rawOp?.security, op.security),
266
+ securityRequirements: deriveSecurityRequirements(rawOp?.security, op.security, true),
267
+ reply,
268
+ xBadges: raw["x-badges"],
269
+ xInternal: raw["x-internal"]
270
+ };
271
+ if (operation.xInternal) continue;
272
+ if (channelName && channelMap.has(channelName)) {
273
+ channelMap.get(channelName).operations.push(operation);
274
+ } else {
275
+ orphanOperations.push(operation);
276
+ }
277
+ }
278
+ }
279
+ const channels = Array.from(channelMap.values());
280
+ if (orphanOperations.length > 0) {
281
+ channels.push({
282
+ name: "__unassigned__",
283
+ address: "Unassigned operations",
284
+ description: "These operations reference a channel that is not defined in this document.",
285
+ operations: orphanOperations
286
+ });
287
+ }
288
+ return channels;
289
+ }
290
+ function convertMessage(rawMsg, isV3, defaultContentType) {
291
+ const msg = applyMessageTraits(rawMsg, isV3);
292
+ const hasOwnContentType = typeof msg.contentType === "string" && msg.contentType.length > 0;
293
+ const contentType = hasOwnContentType ? msg.contentType : defaultContentType ?? "application/json";
294
+ return {
295
+ name: msg.name,
296
+ title: msg.title,
297
+ summary: msg.summary,
298
+ description: msg.description,
299
+ contentType,
300
+ contentTypeInherited: hasOwnContentType ? void 0 : true,
301
+ schemaFormat: msg.schemaFormat,
302
+ payload: msg.payload,
303
+ headers: msg.headers,
304
+ correlationId: msg.correlationId,
305
+ tags: msg.tags,
306
+ examples: msg.examples,
307
+ bindings: msg.bindings,
308
+ externalDocs: msg.externalDocs
309
+ };
310
+ }
311
+ function extractComponents(api, isV3, defaultContentType) {
312
+ const components = api.components;
313
+ const rawMessages = api.components?.messages ?? {};
314
+ const messages = {};
315
+ for (const [name, msg] of Object.entries(rawMessages)) {
316
+ messages[name] = convertMessage(msg, isV3, defaultContentType);
317
+ }
318
+ return {
319
+ schemas: api.components?.schemas ?? {},
320
+ messages,
321
+ securitySchemes: components?.securitySchemes ?? {}
322
+ };
323
+ }
324
+ function deriveSecurityNames(raw, resolved) {
325
+ const rawArr = raw ?? [];
326
+ const resArr = resolved ?? [];
327
+ const count = Math.max(rawArr.length, resArr.length);
328
+ if (count === 0) return void 0;
329
+ const names = [];
330
+ for (let i = 0; i < count; i++) {
331
+ const rawEntry = rawArr[i];
332
+ const resEntry = resArr[i];
333
+ if (rawEntry && typeof rawEntry === "object" && typeof rawEntry.$ref === "string") {
334
+ names.push(decodeJsonPointerSegment(rawEntry.$ref.split("/").pop()));
335
+ } else if (resEntry && typeof resEntry === "object") {
336
+ if (typeof resEntry.type === "string") {
337
+ names.push(resEntry.type);
338
+ } else {
339
+ names.push(...Object.keys(resEntry));
340
+ }
341
+ }
342
+ }
343
+ return names.length > 0 ? names : void 0;
344
+ }
345
+ function deriveSecurityRequirements(raw, resolved, isV3) {
346
+ const rawArr = raw ?? [];
347
+ const resArr = resolved ?? [];
348
+ const count = Math.max(rawArr.length, resArr.length);
349
+ if (count === 0) return void 0;
350
+ const out = [];
351
+ for (let i = 0; i < count; i++) {
352
+ const rawEntry = rawArr[i];
353
+ const resEntry = resArr[i];
354
+ if (isV3) {
355
+ let name;
356
+ if (rawEntry && typeof rawEntry === "object" && typeof rawEntry.$ref === "string") {
357
+ name = decodeJsonPointerSegment(rawEntry.$ref.split("/").pop());
358
+ } else if (resEntry && typeof resEntry.type === "string") {
359
+ name = resEntry.type;
360
+ }
361
+ if (name === void 0) continue;
362
+ const rawScopes = rawEntry?.scopes;
363
+ const resScopes = resEntry?.scopes;
364
+ const scopesSource = Array.isArray(rawScopes) ? rawScopes : Array.isArray(resScopes) ? resScopes : [];
365
+ const scopes = scopesSource.map(String);
366
+ out.push([{ name, scopes }]);
367
+ } else {
368
+ const map = rawEntry ?? resEntry;
369
+ if (!map || typeof map !== "object") continue;
370
+ const inner = Object.entries(map).map(([name, scopes]) => ({
371
+ name,
372
+ scopes: Array.isArray(scopes) ? scopes.map(String) : []
373
+ }));
374
+ if (inner.length > 0) out.push(inner);
375
+ }
376
+ }
377
+ return out.length > 0 ? out : void 0;
378
+ }
379
+ function parseSpecString(input) {
380
+ const trimmed = input.trim();
381
+ if (trimmed.startsWith("{")) {
382
+ try {
383
+ return JSON.parse(trimmed);
384
+ } catch {
385
+ }
386
+ }
387
+ return parse(trimmed);
388
+ }
389
+
390
+ function useAsyncApiSpec(spec) {
391
+ const parser = useCallback(async (raw) => {
392
+ return parseAsyncApiSpec(raw);
393
+ }, []);
394
+ return useSpecFetcher(spec, parser);
395
+ }
396
+
397
+ function ExternalDocsLink({ externalDocs, context, className }) {
398
+ const label = externalDocs.description ?? "External docs";
399
+ const ariaLabel = `${context ? `${context} external docs` : "External docs"}, opens in new tab`;
400
+ return /* @__PURE__ */ jsxs(
401
+ "a",
402
+ {
403
+ href: externalDocs.url,
404
+ target: "_blank",
405
+ rel: "noopener noreferrer",
406
+ "aria-label": ariaLabel,
407
+ className: cx(linkStyle$1, className),
408
+ children: [
409
+ label,
410
+ /* @__PURE__ */ jsx(Icon, { name: "external-link", size: "0.875em" })
411
+ ]
412
+ }
413
+ );
414
+ }
415
+ const linkStyle$1 = css({
416
+ display: "inline-flex",
417
+ alignItems: "center",
418
+ gap: "0.25rem",
419
+ fontSize: "var(--omnispec-font-size-xs)",
420
+ color: "var(--omnispec-fg-link)",
421
+ textDecoration: "none",
422
+ minWidth: 0,
423
+ overflowWrap: "anywhere",
424
+ "&:hover": {
425
+ textDecoration: "underline"
426
+ }
427
+ });
428
+
429
+ const containerStyle$4 = css({
430
+ marginBottom: "2rem",
431
+ paddingBottom: "1.5rem",
432
+ borderBottom: "1px solid var(--omnispec-border-color)"
433
+ });
434
+ const titleStyle$5 = css({
435
+ margin: "0 0 0.25rem",
436
+ fontSize: "var(--omnispec-h2-font-size)",
437
+ color: "var(--omnispec-h2-color)",
438
+ fontWeight: 700,
439
+ display: "inline"
440
+ });
441
+ const versionStyle$1 = css({
442
+ fontSize: "var(--omnispec-font-size-sm)",
443
+ color: "var(--omnispec-fg-muted)",
444
+ marginLeft: "0.75rem",
445
+ fontFamily: "var(--omnispec-font-mono)"
446
+ });
447
+ const specBadgeStyle = css({
448
+ fontSize: "var(--omnispec-font-size-xs)",
449
+ color: "var(--omnispec-color-primary)",
450
+ border: "1px solid var(--omnispec-color-primary)",
451
+ borderRadius: "0.25rem",
452
+ padding: "1px 0.375rem",
453
+ marginLeft: "0.5rem",
454
+ fontFamily: "var(--omnispec-font-mono)"
455
+ });
456
+ const metaStyle = css({
457
+ fontSize: "var(--omnispec-font-size-sm)",
458
+ color: "var(--omnispec-fg-secondary)",
459
+ marginTop: "0.25rem"
460
+ });
461
+ const linkStyle = css({
462
+ color: "var(--omnispec-fg-link)",
463
+ textDecoration: "none",
464
+ "&:hover": {
465
+ textDecoration: "underline"
466
+ }
467
+ });
468
+ function AsyncOverview({ spec }) {
469
+ return /* @__PURE__ */ jsxs("div", { className: cx("omnispec-async-overview", containerStyle$4), children: [
470
+ /* @__PURE__ */ jsx("h1", { className: titleStyle$5, children: spec.title }),
471
+ /* @__PURE__ */ jsxs("span", { className: versionStyle$1, children: [
472
+ "v",
473
+ spec.version
474
+ ] }),
475
+ /* @__PURE__ */ jsxs("span", { className: specBadgeStyle, children: [
476
+ "AsyncAPI ",
477
+ spec.specVersion
478
+ ] }),
479
+ spec.description && /* @__PURE__ */ jsx(MarkdownRenderer, { content: spec.description }),
480
+ spec.contact && /* @__PURE__ */ jsxs("div", { className: metaStyle, children: [
481
+ spec.contact.name && /* @__PURE__ */ jsxs("span", { children: [
482
+ "Contact: ",
483
+ spec.contact.name
484
+ ] }),
485
+ spec.contact.email && /* @__PURE__ */ jsxs("span", { children: [
486
+ " <",
487
+ /* @__PURE__ */ jsx("a", { href: `mailto:${spec.contact.email}`, className: linkStyle, children: spec.contact.email }),
488
+ ">"
489
+ ] }),
490
+ spec.contact.url && /* @__PURE__ */ jsxs("span", { children: [
491
+ " \xB7 ",
492
+ /* @__PURE__ */ jsx("a", { href: spec.contact.url, target: "_blank", rel: "noopener noreferrer", className: linkStyle, children: spec.contact.url })
493
+ ] })
494
+ ] }),
495
+ spec.license && /* @__PURE__ */ jsxs("div", { className: metaStyle, children: [
496
+ "License: ",
497
+ spec.license.url ? /* @__PURE__ */ jsx("a", { href: spec.license.url, target: "_blank", rel: "noopener noreferrer", className: linkStyle, children: spec.license.name }) : spec.license.name
498
+ ] }),
499
+ spec.externalDocs && /* @__PURE__ */ jsx("div", { className: metaStyle, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: spec.externalDocs, context: spec.title ?? "API" }) })
500
+ ] });
501
+ }
502
+
503
+ const protocolColors = {
504
+ kafka: "#231F20",
505
+ "kafka-secure": "#231F20",
506
+ mqtt: "#660066",
507
+ "mqtt5": "#660066",
508
+ amqp: "#FF6600",
509
+ "amqp1": "#FF6600",
510
+ ws: "#4A90D9",
511
+ wss: "#4A90D9",
512
+ http: "var(--omnispec-color-get)",
513
+ https: "var(--omnispec-color-get)",
514
+ nats: "#27AAE1",
515
+ redis: "#DC382D",
516
+ sns: "#FF9900",
517
+ sqs: "#FF9900",
518
+ stomp: "#6DB33F",
519
+ mercure: "#1D1D1D"
520
+ };
521
+ const badgeBase = css({
522
+ display: "inline-block",
523
+ padding: "0.125rem 0.5rem",
524
+ borderRadius: "0.25rem",
525
+ fontSize: "0.625rem",
526
+ fontWeight: 700,
527
+ fontFamily: "var(--omnispec-font-mono)",
528
+ color: "#ffffff",
529
+ letterSpacing: "0.0313rem"
530
+ });
531
+ const versionStyle = css({
532
+ fontWeight: 400,
533
+ opacity: 0.8
534
+ });
535
+ function ProtocolBadge({ protocol, version }) {
536
+ const color = protocolColors[protocol.toLowerCase()] ?? "var(--omnispec-fg-muted)";
537
+ return /* @__PURE__ */ jsxs("span", { className: cx(badgeBase, css({ backgroundColor: color })), children: [
538
+ protocol.toUpperCase(),
539
+ version && /* @__PURE__ */ jsxs("span", { className: versionStyle, children: [
540
+ " ",
541
+ version
542
+ ] })
543
+ ] });
544
+ }
545
+
546
+ function humanizeField(field) {
547
+ if (/^x-/i.test(field)) return field;
548
+ const spaced = field.replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim();
549
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
550
+ }
551
+ function isPlainObject(value) {
552
+ return typeof value === "object" && value !== null && !Array.isArray(value);
553
+ }
554
+ const JSON_SCHEMA_TYPES = /* @__PURE__ */ new Set([
555
+ "string",
556
+ "number",
557
+ "integer",
558
+ "boolean",
559
+ "object",
560
+ "array",
561
+ "null"
562
+ ]);
563
+ function hasSchemaType(value) {
564
+ const t = value.type;
565
+ if (typeof t === "string") return JSON_SCHEMA_TYPES.has(t);
566
+ if (Array.isArray(t)) return t.every((x) => typeof x === "string" && JSON_SCHEMA_TYPES.has(x));
567
+ return false;
568
+ }
569
+ function isJsonSchema(value) {
570
+ return "properties" in value || "enum" in value || "items" in value || hasSchemaType(value);
571
+ }
572
+ function isScalarArray(value) {
573
+ return value.every(
574
+ (item) => item === null || typeof item !== "object"
575
+ );
576
+ }
577
+ function renderValue(value) {
578
+ if (value === null) return /* @__PURE__ */ jsx("span", { className: mutedStyle, children: "null" });
579
+ if (typeof value === "boolean") return /* @__PURE__ */ jsx("code", { className: codeStyle, children: value ? "true" : "false" });
580
+ if (typeof value === "number") return /* @__PURE__ */ jsx("code", { className: codeStyle, children: String(value) });
581
+ if (typeof value === "string") return /* @__PURE__ */ jsx("span", { children: value });
582
+ if (Array.isArray(value)) {
583
+ if (value.length === 0) return /* @__PURE__ */ jsx("span", { className: mutedStyle, children: "none" });
584
+ if (isScalarArray(value)) {
585
+ return /* @__PURE__ */ jsx("span", { children: value.map((item) => String(item)).join(", ") });
586
+ }
587
+ return /* @__PURE__ */ jsx("code", { className: jsonStyle, children: JSON.stringify(value, null, 2) });
588
+ }
589
+ if (isPlainObject(value)) {
590
+ if (isJsonSchema(value)) {
591
+ return /* @__PURE__ */ jsx(SchemaValue, { schema: value });
592
+ }
593
+ const nested = Object.entries(value).filter(([, v]) => v !== void 0);
594
+ if (nested.length === 0) return /* @__PURE__ */ jsx("span", { className: mutedStyle, children: "none" });
595
+ return /* @__PURE__ */ jsx("div", { className: nestedStyle, children: /* @__PURE__ */ jsx(FieldRows, { fields: nested }) });
596
+ }
597
+ return /* @__PURE__ */ jsx("code", { className: jsonStyle, children: JSON.stringify(value) });
598
+ }
599
+ function SchemaValue({ schema }) {
600
+ const properties = isPlainObject(schema.properties) ? schema.properties : void 0;
601
+ if (properties && Object.keys(properties).length > 0) {
602
+ return /* @__PURE__ */ jsx("div", { className: schemaTableStyle, children: Object.entries(properties).map(([name, propSchema]) => /* @__PURE__ */ jsx(
603
+ SchemaRow,
604
+ {
605
+ name,
606
+ schema: isPlainObject(propSchema) ? propSchema : {}
607
+ },
608
+ name
609
+ )) });
610
+ }
611
+ return /* @__PURE__ */ jsx("div", { className: schemaTableStyle, children: /* @__PURE__ */ jsx(SchemaLeaf, { schema }) });
612
+ }
613
+ function SchemaRow({ name, schema }) {
614
+ return /* @__PURE__ */ jsxs("div", { className: schemaRowStyle, children: [
615
+ /* @__PURE__ */ jsx("code", { className: schemaNameStyle$1, children: name }),
616
+ /* @__PURE__ */ jsx(SchemaLeaf, { schema })
617
+ ] });
618
+ }
619
+ function SchemaLeaf({ schema }) {
620
+ const type = typeof schema.type === "string" ? schema.type : void 0;
621
+ const description = typeof schema.description === "string" ? schema.description : void 0;
622
+ const enumValues = Array.isArray(schema.enum) ? schema.enum : void 0;
623
+ return /* @__PURE__ */ jsxs("div", { className: schemaLeafStyle, children: [
624
+ type && /* @__PURE__ */ jsx("span", { className: schemaTypeStyle, children: type }),
625
+ description && /* @__PURE__ */ jsx("span", { className: schemaDescStyle, children: description }),
626
+ enumValues && enumValues.length > 0 && /* @__PURE__ */ jsxs("span", { className: enumWrapStyle, children: [
627
+ /* @__PURE__ */ jsx("span", { className: enumLabelStyle, children: "Allowed:" }),
628
+ enumValues.map((v, i) => /* @__PURE__ */ jsx("code", { className: enumItemStyle, children: String(v) }, i))
629
+ ] })
630
+ ] });
631
+ }
632
+ function FieldRows({ fields }) {
633
+ if (fields.length === 0) return null;
634
+ return /* @__PURE__ */ jsx("dl", { className: listStyle$1, children: fields.map(([field, value]) => /* @__PURE__ */ jsxs("div", { className: rowStyle$1, children: [
635
+ /* @__PURE__ */ jsx("dt", { className: nameStyle$1, children: humanizeField(field) }),
636
+ /* @__PURE__ */ jsx("dd", { className: valueStyle, children: renderValue(value) })
637
+ ] }, field)) });
638
+ }
639
+ const listStyle$1 = css({
640
+ display: "grid",
641
+ gridTemplateColumns: "max-content 1fr",
642
+ gap: "0.25rem 1rem",
643
+ margin: "0.25rem 0 0",
644
+ minWidth: 0
645
+ });
646
+ const rowStyle$1 = css({ display: "contents" });
647
+ const nameStyle$1 = css({
648
+ fontSize: "var(--omnispec-font-size-xs)",
649
+ fontWeight: 600,
650
+ color: "var(--omnispec-fg-secondary)"
651
+ });
652
+ const valueStyle = css({
653
+ fontSize: "var(--omnispec-font-size-xs)",
654
+ color: "var(--omnispec-fg-primary)",
655
+ margin: 0,
656
+ minWidth: 0,
657
+ overflowWrap: "anywhere",
658
+ wordBreak: "break-word"
659
+ });
660
+ const codeStyle = css({
661
+ fontFamily: "var(--omnispec-font-mono)",
662
+ fontSize: "var(--omnispec-font-size-xs)"
663
+ });
664
+ const jsonStyle = css({
665
+ display: "block",
666
+ fontFamily: "var(--omnispec-font-mono)",
667
+ fontSize: "var(--omnispec-font-size-xs)",
668
+ color: "var(--omnispec-fg-code)",
669
+ margin: 0,
670
+ whiteSpace: "pre",
671
+ overflowX: "auto",
672
+ maxWidth: "100%",
673
+ overflowWrap: "anywhere"
674
+ });
675
+ const mutedStyle = css({
676
+ color: "var(--omnispec-fg-muted)"
677
+ });
678
+ const nestedStyle = css({
679
+ minWidth: 0,
680
+ paddingLeft: "0.5rem",
681
+ marginTop: "0.125rem",
682
+ boxShadow: "inset 2px 0 0 0 var(--omnispec-border-color)"
683
+ });
684
+ const schemaTableStyle = css({
685
+ display: "flex",
686
+ flexDirection: "column",
687
+ gap: "0.25rem",
688
+ minWidth: 0
689
+ });
690
+ const schemaRowStyle = css({
691
+ display: "flex",
692
+ flexDirection: "column",
693
+ gap: "0.125rem",
694
+ minWidth: 0
695
+ });
696
+ const schemaNameStyle$1 = css({
697
+ fontFamily: "var(--omnispec-font-mono)",
698
+ fontSize: "var(--omnispec-font-size-xs)",
699
+ fontWeight: 600,
700
+ color: "var(--omnispec-fg-primary)",
701
+ overflowWrap: "anywhere"
702
+ });
703
+ const schemaLeafStyle = css({
704
+ display: "flex",
705
+ flexWrap: "wrap",
706
+ alignItems: "baseline",
707
+ gap: "0.375rem",
708
+ minWidth: 0
709
+ });
710
+ const schemaTypeStyle = css({
711
+ fontFamily: "var(--omnispec-font-mono)",
712
+ fontSize: "var(--omnispec-font-size-xs)",
713
+ color: "var(--omnispec-fg-code)"
714
+ });
715
+ const schemaDescStyle = css({
716
+ fontSize: "var(--omnispec-font-size-xs)",
717
+ color: "var(--omnispec-fg-secondary)",
718
+ overflowWrap: "anywhere",
719
+ wordBreak: "break-word"
720
+ });
721
+ const enumWrapStyle = css({
722
+ display: "flex",
723
+ flexWrap: "wrap",
724
+ alignItems: "baseline",
725
+ gap: "0.25rem",
726
+ minWidth: 0
727
+ });
728
+ const enumLabelStyle = css({
729
+ fontSize: "var(--omnispec-font-size-xs)",
730
+ color: "var(--omnispec-fg-muted)"
731
+ });
732
+ const enumItemStyle = css({
733
+ fontFamily: "var(--omnispec-font-mono)",
734
+ fontSize: "var(--omnispec-font-size-xs)",
735
+ color: "var(--omnispec-fg-code)",
736
+ backgroundColor: "var(--omnispec-bg-tertiary)",
737
+ borderRadius: "var(--omnispec-border-radius)",
738
+ padding: "0.02rem 0.3rem",
739
+ overflowWrap: "anywhere"
740
+ });
741
+
742
+ const HIDDEN_KEYS = /* @__PURE__ */ new Set(["bindingVersion"]);
743
+ function BindingsSection({ bindings, title = "Bindings" }) {
744
+ if (!bindings || Object.keys(bindings).length === 0) return null;
745
+ const protocols = Object.entries(bindings).filter(
746
+ ([, cfg]) => cfg && typeof cfg === "object"
747
+ );
748
+ if (protocols.length === 0) return null;
749
+ return /* @__PURE__ */ jsxs("div", { className: containerStyle$3, children: [
750
+ /* @__PURE__ */ jsx("h4", { className: titleStyle$4, children: title }),
751
+ /* @__PURE__ */ jsx("div", { className: protocolListStyle, children: protocols.map(([protocol, cfg]) => {
752
+ const rows = Object.entries(cfg).filter(
753
+ ([key, value]) => !HIDDEN_KEYS.has(key) && value !== void 0
754
+ );
755
+ return /* @__PURE__ */ jsxs("div", { className: protocolCardStyle, children: [
756
+ /* @__PURE__ */ jsx("div", { className: protocolHeaderStyle, children: /* @__PURE__ */ jsx(ProtocolBadge, { protocol }) }),
757
+ rows.length > 0 ? /* @__PURE__ */ jsx(FieldRows, { fields: rows }) : /* @__PURE__ */ jsx("p", { className: emptyStyle, children: "No binding fields." })
758
+ ] }, protocol);
759
+ }) })
760
+ ] });
761
+ }
762
+ const containerStyle$3 = css({
763
+ marginTop: "1rem"
764
+ });
765
+ const titleStyle$4 = css({
766
+ margin: "0 0 0.75rem",
767
+ fontSize: "var(--omnispec-font-size-md)",
768
+ fontWeight: 700,
769
+ color: "var(--omnispec-fg-primary)",
770
+ letterSpacing: "0.02em"
771
+ });
772
+ const protocolListStyle = css({
773
+ display: "flex",
774
+ flexDirection: "column",
775
+ gap: "0.5rem"
776
+ });
777
+ const protocolCardStyle = css({
778
+ padding: "0.625rem 0.75rem",
779
+ borderRadius: "var(--omnispec-border-radius)",
780
+ backgroundColor: "var(--omnispec-bg-secondary)"
781
+ });
782
+ const protocolHeaderStyle = css({
783
+ marginBottom: "0.5rem"
784
+ });
785
+ const emptyStyle = css({
786
+ margin: 0,
787
+ fontSize: "var(--omnispec-font-size-xs)",
788
+ color: "var(--omnispec-fg-muted)"
789
+ });
790
+
791
+ function SecurityRequirementBadges({ requirements, label = "Security" }) {
792
+ if (!requirements || requirements.length === 0) return null;
793
+ return /* @__PURE__ */ jsxs("div", { className: rowStyle, children: [
794
+ /* @__PURE__ */ jsx("span", { className: labelStyle, children: label }),
795
+ requirements.map((alternative, altIndex) => /* @__PURE__ */ jsxs(Fragment, { children: [
796
+ altIndex > 0 && /* @__PURE__ */ jsx("span", { className: orStyle, children: "OR" }),
797
+ alternative.map((scheme) => /* @__PURE__ */ jsxs("a", { href: `#security-${scheme.name}`, className: badgeStyle, children: [
798
+ /* @__PURE__ */ jsx(Icon, { name: "lock", size: "0.625rem", strokeWidth: 2.5 }),
799
+ scheme.name,
800
+ scheme.scopes.length > 0 && /* @__PURE__ */ jsxs("span", { className: scopesStyle$1, children: [
801
+ /* @__PURE__ */ jsx("span", { className: scopeSepStyle, children: "\xB7" }),
802
+ scheme.scopes.join(", ")
803
+ ] })
804
+ ] }, scheme.name))
805
+ ] }, altIndex))
806
+ ] });
807
+ }
808
+ const rowStyle = css({
809
+ display: "flex",
810
+ alignItems: "center",
811
+ gap: "0.375rem",
812
+ flexWrap: "wrap",
813
+ marginTop: "0.5rem"
814
+ });
815
+ const labelStyle = css({
816
+ fontSize: "var(--omnispec-font-size-xxs)",
817
+ lineHeight: 1.5,
818
+ fontWeight: 600,
819
+ textTransform: "uppercase",
820
+ letterSpacing: "0.05em",
821
+ color: "var(--omnispec-fg-muted)"
822
+ });
823
+ const orStyle = css({
824
+ fontSize: "var(--omnispec-font-size-xxs)",
825
+ lineHeight: 1.5,
826
+ fontWeight: 700,
827
+ textTransform: "uppercase",
828
+ letterSpacing: "0.05em",
829
+ color: "var(--omnispec-fg-muted)"
830
+ });
831
+ const badgeStyle = css({
832
+ display: "inline-flex",
833
+ alignItems: "center",
834
+ gap: "0.3125rem",
835
+ fontSize: "var(--omnispec-font-size-xs)",
836
+ fontFamily: "var(--omnispec-font-mono)",
837
+ color: "var(--omnispec-fg-primary)",
838
+ backgroundColor: "var(--omnispec-bg-tertiary)",
839
+ padding: "0.1875rem 0.625rem",
840
+ borderRadius: "var(--omnispec-border-radius)",
841
+ fontWeight: 500,
842
+ textDecoration: "none",
843
+ "&:hover": {
844
+ textDecoration: "underline"
845
+ }
846
+ });
847
+ const scopesStyle$1 = css({
848
+ display: "inline-flex",
849
+ alignItems: "center",
850
+ gap: "0.3125rem",
851
+ color: "var(--omnispec-fg-secondary)"
852
+ });
853
+ const scopeSepStyle = css({
854
+ color: "var(--omnispec-fg-muted)"
855
+ });
856
+
857
+ const containerStyle$2 = css({
858
+ marginBottom: "1.5rem"
859
+ });
860
+ const titleStyle$3 = css({
861
+ margin: "0 0 0.75rem",
862
+ fontSize: "var(--omnispec-h3-font-size)",
863
+ color: "var(--omnispec-h3-color)",
864
+ fontWeight: 600
865
+ });
866
+ const tabStripStyle = css({
867
+ display: "flex",
868
+ flexWrap: "wrap",
869
+ gap: "0.25rem",
870
+ marginBottom: "0.5rem"
871
+ });
872
+ const tabStyle = css({
873
+ padding: "0.25rem 0.75rem",
874
+ border: "none",
875
+ borderRadius: "var(--omnispec-border-radius)",
876
+ backgroundColor: "var(--omnispec-bg-tertiary)",
877
+ color: "var(--omnispec-fg-secondary)",
878
+ fontSize: "var(--omnispec-font-size-sm)",
879
+ fontFamily: "var(--omnispec-font-mono)",
880
+ cursor: "pointer",
881
+ "&:hover": {
882
+ color: "var(--omnispec-fg-primary)"
883
+ }
884
+ });
885
+ const tabActiveStyle = css({
886
+ backgroundColor: "var(--omnispec-color-primary)",
887
+ color: "#ffffff",
888
+ "&:hover": {
889
+ color: "#ffffff"
890
+ }
891
+ });
892
+ const cardStyle$1 = css({
893
+ padding: "0.75rem",
894
+ border: "1px solid var(--omnispec-border-color)",
895
+ borderRadius: "var(--omnispec-border-radius)",
896
+ backgroundColor: "var(--omnispec-bg-secondary)",
897
+ "&:hover": {
898
+ borderColor: "var(--omnispec-color-primary)"
899
+ }
900
+ });
901
+ const cardHeaderStyle = css({
902
+ display: "flex",
903
+ alignItems: "center",
904
+ gap: "0.5rem",
905
+ marginBottom: "0.375rem"
906
+ });
907
+ const serverNameStyle = css({
908
+ fontWeight: 600,
909
+ fontSize: "var(--omnispec-font-size-sm)",
910
+ color: "var(--omnispec-fg-primary)"
911
+ });
912
+ const urlStyle = css({
913
+ fontFamily: "var(--omnispec-font-mono)",
914
+ fontSize: "var(--omnispec-font-size-sm)",
915
+ color: "var(--omnispec-fg-code)",
916
+ display: "block",
917
+ marginBottom: "0.25rem"
918
+ });
919
+ const descriptionStyle = css({
920
+ margin: "0.25rem 0 0",
921
+ fontSize: "var(--omnispec-font-size-xs)",
922
+ color: "var(--omnispec-fg-secondary)"
923
+ });
924
+ const variablesStyle = css({
925
+ marginTop: "0.5rem",
926
+ fontSize: "var(--omnispec-font-size-xs)"
927
+ });
928
+ const varRowStyle = css({
929
+ display: "flex",
930
+ gap: "0.375rem",
931
+ marginBottom: "0.125rem"
932
+ });
933
+ const varNameStyle = css({
934
+ fontFamily: "var(--omnispec-font-mono)",
935
+ color: "var(--omnispec-fg-primary)",
936
+ fontWeight: 600
937
+ });
938
+ const varDefaultStyle = css({
939
+ fontFamily: "var(--omnispec-font-mono)",
940
+ color: "var(--omnispec-fg-muted)"
941
+ });
942
+ const varDescStyle = css({
943
+ color: "var(--omnispec-fg-secondary)"
944
+ });
945
+ const varEnumStyle = css({
946
+ fontFamily: "var(--omnispec-font-mono)",
947
+ color: "var(--omnispec-color-info)"
948
+ });
949
+ const varTokenStyle = css({
950
+ color: "var(--omnispec-color-primary)",
951
+ backgroundColor: "color-mix(in srgb, var(--omnispec-color-primary) 12%, transparent)",
952
+ borderRadius: "var(--omnispec-border-radius)",
953
+ padding: "0 0.125rem",
954
+ "&::before": { content: '"{"' },
955
+ "&::after": { content: '"}"' }
956
+ });
957
+ function highlightVariables(url) {
958
+ const parts = url.split(/(\{[^}]+\})/g);
959
+ return parts.map(
960
+ (part, i) => /^\{[^}]+\}$/.test(part) ? /* @__PURE__ */ jsx("span", { className: varTokenStyle, children: part.slice(1, -1) }, i) : /* @__PURE__ */ jsx("span", { children: part }, i)
961
+ );
962
+ }
963
+ function ServerCard({ server }) {
964
+ return /* @__PURE__ */ jsxs("div", { className: cardStyle$1, children: [
965
+ /* @__PURE__ */ jsxs("div", { className: cardHeaderStyle, children: [
966
+ /* @__PURE__ */ jsx("span", { className: serverNameStyle, children: server.name }),
967
+ /* @__PURE__ */ jsx(ProtocolBadge, { protocol: server.protocol, version: server.protocolVersion })
968
+ ] }),
969
+ /* @__PURE__ */ jsx("code", { className: urlStyle, children: highlightVariables(server.url) }),
970
+ server.description && /* @__PURE__ */ jsx("p", { className: descriptionStyle, children: server.description }),
971
+ server.variables && Object.entries(server.variables).length > 0 && /* @__PURE__ */ jsx("div", { className: variablesStyle, children: Object.entries(server.variables).map(([name, variable]) => /* @__PURE__ */ jsxs("div", { className: varRowStyle, children: [
972
+ /* @__PURE__ */ jsx("code", { className: varNameStyle, children: name }),
973
+ variable.default && /* @__PURE__ */ jsxs("span", { className: varDefaultStyle, children: [
974
+ "= ",
975
+ variable.default
976
+ ] }),
977
+ variable.enum && variable.enum.length > 0 && /* @__PURE__ */ jsxs("span", { className: varEnumStyle, children: [
978
+ "enum: ",
979
+ variable.enum.join(" | ")
980
+ ] }),
981
+ variable.description && /* @__PURE__ */ jsx("span", { className: varDescStyle, children: variable.description })
982
+ ] }, name)) }),
983
+ /* @__PURE__ */ jsx(SecurityRequirementBadges, { requirements: server.securityRequirements ?? [] }),
984
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: server.bindings, title: "Server Bindings" })
985
+ ] });
986
+ }
987
+ function ServerList({ servers }) {
988
+ const [selected, setSelected] = useState(0);
989
+ if (servers.length === 0) return null;
990
+ const activeIndex = Math.min(selected, servers.length - 1);
991
+ return /* @__PURE__ */ jsxs("div", { className: cx("omnispec-async-servers", containerStyle$2), children: [
992
+ /* @__PURE__ */ jsx("h3", { className: titleStyle$3, children: "Servers" }),
993
+ servers.length > 1 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
994
+ /* @__PURE__ */ jsx("div", { className: tabStripStyle, role: "tablist", "aria-label": "Servers", children: servers.map((server, idx) => /* @__PURE__ */ jsx(
995
+ "button",
996
+ {
997
+ type: "button",
998
+ role: "tab",
999
+ "aria-selected": idx === activeIndex,
1000
+ className: cx(tabStyle, idx === activeIndex && tabActiveStyle),
1001
+ onClick: () => setSelected(idx),
1002
+ children: server.name
1003
+ },
1004
+ server.name
1005
+ )) }),
1006
+ /* @__PURE__ */ jsx(ServerCard, { server: servers[activeIndex] })
1007
+ ] }) : /* @__PURE__ */ jsx(ServerCard, { server: servers[0] })
1008
+ ] });
1009
+ }
1010
+
1011
+ function detectSchemaFormat(schemaFormat) {
1012
+ if (!schemaFormat) return "json";
1013
+ const f = schemaFormat.toLowerCase();
1014
+ if (f.includes("avro")) return "avro";
1015
+ if (f.includes("protobuf") || f.includes("proto")) return "protobuf";
1016
+ return "json";
1017
+ }
1018
+ function avroToJsonSchema(avro) {
1019
+ return convert(avro);
1020
+ }
1021
+ function convert(node) {
1022
+ if (typeof node === "string") return primitive(node);
1023
+ if (Array.isArray(node)) {
1024
+ const nonNull = node.filter((n) => n !== "null");
1025
+ const nullable = node.length !== nonNull.length;
1026
+ if (nonNull.length === 1) {
1027
+ return { ...convert(nonNull[0]), nullable };
1028
+ }
1029
+ return { oneOf: nonNull.map(convert), nullable };
1030
+ }
1031
+ if (node && typeof node === "object") {
1032
+ const obj = node;
1033
+ const type = obj.type;
1034
+ if (type === "record") {
1035
+ const fields = obj.fields ?? [];
1036
+ const properties = {};
1037
+ const required = [];
1038
+ for (const field of fields) {
1039
+ const name = field.name;
1040
+ const schema = convert(field.type);
1041
+ if (field.doc) schema.description = field.doc;
1042
+ if (field.default !== void 0) schema.default = field.default;
1043
+ properties[name] = schema;
1044
+ if (field.default === void 0 && !schema.nullable) required.push(name);
1045
+ }
1046
+ const result = { type: "object", properties };
1047
+ if (obj.doc) result.description = obj.doc;
1048
+ if (required.length > 0) result.required = required;
1049
+ return result;
1050
+ }
1051
+ if (type === "enum") {
1052
+ return { type: "string", enum: obj.symbols ?? [] };
1053
+ }
1054
+ if (type === "array") {
1055
+ return { type: "array", items: convert(obj.items) };
1056
+ }
1057
+ if (type === "map") {
1058
+ return { type: "object", additionalProperties: convert(obj.values) };
1059
+ }
1060
+ if (type === "fixed") {
1061
+ return { type: "string", format: `fixed(${obj.size ?? "?"})` };
1062
+ }
1063
+ if (typeof type === "string") {
1064
+ const base = primitive(type);
1065
+ if (obj.logicalType) base.format = String(obj.logicalType);
1066
+ return base;
1067
+ }
1068
+ if (type && typeof type === "object") return convert(type);
1069
+ }
1070
+ return { type: "object" };
1071
+ }
1072
+ const AVRO_PRIMITIVES = {
1073
+ null: { type: "null" },
1074
+ boolean: { type: "boolean" },
1075
+ int: { type: "integer", format: "int32" },
1076
+ long: { type: "integer", format: "int64" },
1077
+ float: { type: "number", format: "float" },
1078
+ double: { type: "number", format: "double" },
1079
+ bytes: { type: "string", format: "byte" },
1080
+ string: { type: "string" }
1081
+ };
1082
+ function primitive(name) {
1083
+ return { ...AVRO_PRIMITIVES[name] ?? { type: name } };
1084
+ }
1085
+
1086
+ function MessagePayload({ message, idx }) {
1087
+ const rawPayload = message.payload;
1088
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1089
+ message.tags && message.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle$2, children: message.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: tagChipStyle$2, title: tag.description, children: tag.name }, tag.name)) }),
1090
+ message.externalDocs && /* @__PURE__ */ jsx("div", { className: externalDocsStyle, children: /* @__PURE__ */ jsx(
1091
+ ExternalDocsLink,
1092
+ {
1093
+ externalDocs: message.externalDocs,
1094
+ context: message.name ?? message.title ?? "message"
1095
+ }
1096
+ ) }),
1097
+ message.schemaFormat && /* @__PURE__ */ jsx("span", { className: schemaFormatBadgeStyle, children: message.schemaFormat }),
1098
+ rawPayload && /* @__PURE__ */ jsx(PayloadBody, { rawPayload, schemaFormat: message.schemaFormat, message, idx })
1099
+ ] });
1100
+ }
1101
+ function PayloadBody({
1102
+ rawPayload,
1103
+ schemaFormat,
1104
+ message,
1105
+ idx
1106
+ }) {
1107
+ if (typeof rawPayload.$ref === "string") {
1108
+ return /* @__PURE__ */ jsxs("div", { className: unresolvedRefStyle, role: "alert", children: [
1109
+ /* @__PURE__ */ jsx(Icon, { name: "warning", size: "0.875rem" }),
1110
+ /* @__PURE__ */ jsxs("span", { children: [
1111
+ "Unresolved reference: ",
1112
+ /* @__PURE__ */ jsx("code", { className: unresolvedRefCodeStyle, children: rawPayload.$ref })
1113
+ ] })
1114
+ ] });
1115
+ }
1116
+ const format = detectSchemaFormat(schemaFormat);
1117
+ if (format === "protobuf") {
1118
+ return /* @__PURE__ */ jsxs("div", { children: [
1119
+ /* @__PURE__ */ jsx(CodeBlock, { code: JSON.stringify(rawPayload, null, 2), language: "json" }),
1120
+ /* @__PURE__ */ jsx("p", { className: proNoteStyle, children: "Full Protobuf schema rendering is available in Pro." })
1121
+ ] });
1122
+ }
1123
+ const schema = format === "avro" ? avroToJsonSchema(rawPayload) : rawPayload;
1124
+ return /* @__PURE__ */ jsx(
1125
+ Tabs,
1126
+ {
1127
+ tabs: [
1128
+ {
1129
+ id: `schema-${idx}`,
1130
+ label: "Payload Schema",
1131
+ content: /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(schema) })
1132
+ },
1133
+ {
1134
+ id: `example-${idx}`,
1135
+ label: "Example",
1136
+ content: /* @__PURE__ */ jsx(MessageExample, { message, schema })
1137
+ }
1138
+ ]
1139
+ }
1140
+ );
1141
+ }
1142
+ function MessageExample({ message, schema }) {
1143
+ const named = (message.examples ?? []).filter((ex) => ex.payload !== void 0).map((ex, i) => ({
1144
+ name: ex.name ?? `example ${i + 1}`,
1145
+ summary: ex.summary,
1146
+ value: ex.payload
1147
+ }));
1148
+ const [selectedName, setSelectedName] = useState(named[0]?.name ?? "");
1149
+ const active = named.find((ex) => ex.name === selectedName) ?? named[0];
1150
+ const exampleSchema = schema ?? message.payload;
1151
+ const code = active?.value !== void 0 ? JSON.stringify(active.value, null, 2) : exampleSchema ? JSON.stringify(generateExample(exampleSchema), null, 2) : "{}";
1152
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1153
+ /* @__PURE__ */ jsx(ExampleSelector, { examples: named, selectedName: selectedName || (named[0]?.name ?? ""), onSelect: setSelectedName }),
1154
+ /* @__PURE__ */ jsx(CodeBlock, { code, language: "json" })
1155
+ ] });
1156
+ }
1157
+ const tagChipsStyle$2 = css({
1158
+ display: "flex",
1159
+ flexWrap: "wrap",
1160
+ gap: "0.25rem",
1161
+ marginBottom: "0.5rem"
1162
+ });
1163
+ const tagChipStyle$2 = css({
1164
+ fontSize: "var(--omnispec-font-size-xxs)",
1165
+ fontFamily: "var(--omnispec-font-mono)",
1166
+ color: "var(--omnispec-fg-secondary)",
1167
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1168
+ padding: "1px 0.5rem",
1169
+ borderRadius: "0.625rem"
1170
+ });
1171
+ const externalDocsStyle = css({
1172
+ marginBottom: "0.5rem"
1173
+ });
1174
+ const schemaFormatBadgeStyle = css({
1175
+ display: "inline-block",
1176
+ fontFamily: "var(--omnispec-font-mono)",
1177
+ fontSize: "var(--omnispec-font-size-xxs)",
1178
+ color: "var(--omnispec-fg-secondary)",
1179
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1180
+ padding: "0.0625rem 0.375rem",
1181
+ borderRadius: "var(--omnispec-border-radius)",
1182
+ marginBottom: "0.5rem"
1183
+ });
1184
+ const proNoteStyle = css({
1185
+ margin: "0.375rem 0 0",
1186
+ fontSize: "var(--omnispec-font-size-xxs)",
1187
+ color: "var(--omnispec-fg-muted)",
1188
+ fontStyle: "italic"
1189
+ });
1190
+ const unresolvedRefStyle = css({
1191
+ display: "flex",
1192
+ alignItems: "center",
1193
+ gap: "0.5rem",
1194
+ padding: "0.5rem 0.75rem",
1195
+ borderRadius: "var(--omnispec-border-radius)",
1196
+ backgroundColor: "color-mix(in srgb, var(--omnispec-color-warning) 12%, transparent)",
1197
+ color: "var(--omnispec-color-warning)",
1198
+ fontSize: "var(--omnispec-font-size-sm)"
1199
+ });
1200
+ const unresolvedRefCodeStyle = css({
1201
+ fontFamily: "var(--omnispec-font-mono)",
1202
+ fontSize: "var(--omnispec-font-size-xs)"
1203
+ });
1204
+
1205
+ const actionLabels$1 = {
1206
+ publish: "PUB",
1207
+ subscribe: "SUB",
1208
+ send: "SEND",
1209
+ receive: "RECV"
1210
+ };
1211
+ const actionColors$1 = {
1212
+ publish: "var(--omnispec-color-publish)",
1213
+ subscribe: "var(--omnispec-color-subscribe)",
1214
+ send: "var(--omnispec-color-publish)",
1215
+ receive: "var(--omnispec-color-subscribe)"
1216
+ };
1217
+ function ChannelDetail({ channel, id, expandAll, expandGeneration, onTagClick }) {
1218
+ const primaryAction = channel.operations[0]?.action;
1219
+ const primaryLabel = actionLabels$1[primaryAction] ?? primaryAction?.toUpperCase() ?? "";
1220
+ const primaryColor = actionColors$1[primaryAction] ?? "var(--omnispec-fg-muted)";
1221
+ return /* @__PURE__ */ jsxs(
1222
+ ExpandableCard,
1223
+ {
1224
+ id,
1225
+ title: channel.address,
1226
+ rightLabel: `${channel.operations.length} ${channel.operations.length === 1 ? "operation" : "operations"}`,
1227
+ expandAll,
1228
+ expandGeneration,
1229
+ children: [
1230
+ /* @__PURE__ */ jsx(MethodBar, { label: primaryLabel, path: channel.address, color: primaryColor }),
1231
+ /* @__PURE__ */ jsxs("div", { className: bodyStyle, children: [
1232
+ channel.description && /* @__PURE__ */ jsx("div", { className: sectionStyle$1, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: channel.description }) }),
1233
+ channel.externalDocs && /* @__PURE__ */ jsx("div", { className: sectionStyle$1, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: channel.externalDocs, context: channel.address }) }),
1234
+ channel.parameters && Object.keys(channel.parameters).length > 0 && /* @__PURE__ */ jsxs("div", { className: sectionStyle$1, children: [
1235
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle$1, children: "Parameters" }),
1236
+ /* @__PURE__ */ jsx("div", { className: paramListStyle$1, children: Object.entries(channel.parameters).map(([name, param]) => {
1237
+ const schema = param.schema ?? {};
1238
+ const paramType = schema.type;
1239
+ const paramFormat = schema.format;
1240
+ const paramEnum = schema.enum;
1241
+ const constraintBadges = buildConstraints(schema);
1242
+ return /* @__PURE__ */ jsxs("div", { className: paramRowStyle$1, children: [
1243
+ /* @__PURE__ */ jsxs("div", { className: paramHeaderStyle$1, children: [
1244
+ /* @__PURE__ */ jsx("span", { className: paramNameStyle$1, children: name }),
1245
+ paramType && /* @__PURE__ */ jsx("pre", { className: typeBadgeStyle$2, children: paramType })
1246
+ ] }),
1247
+ (paramFormat || constraintBadges.length > 0 || paramEnum && paramEnum.length > 0) && /* @__PURE__ */ jsxs("div", { className: paramConstraintsStyle$1, children: [
1248
+ paramFormat && /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: paramFormat }),
1249
+ constraintBadges.map((c) => /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: c }, c)),
1250
+ paramEnum && paramEnum.length > 0 && /* @__PURE__ */ jsxs(SchemaBadge, { variant: "enum", children: [
1251
+ "enum: ",
1252
+ paramEnum.map(String).join(" | ")
1253
+ ] })
1254
+ ] }),
1255
+ param.description && /* @__PURE__ */ jsx("p", { className: paramDescStyle$1, children: param.description })
1256
+ ] }, name);
1257
+ }) })
1258
+ ] }),
1259
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: channel.bindings, title: "Channel Bindings" }),
1260
+ channel.operations.map((op, idx) => /* @__PURE__ */ jsxs("div", { id: id ? `${id}-op-${idx}` : void 0, className: operationStyle, children: [
1261
+ /* @__PURE__ */ jsxs("div", { className: opHeaderStyle$1, children: [
1262
+ /* @__PURE__ */ jsx(
1263
+ "span",
1264
+ {
1265
+ className: cx(actionBadgeBase$1, css({
1266
+ backgroundColor: actionColors$1[op.action] ?? "var(--omnispec-fg-muted)"
1267
+ })),
1268
+ children: actionLabels$1[op.action] ?? op.action.toUpperCase()
1269
+ }
1270
+ ),
1271
+ op.operationId && /* @__PURE__ */ jsx("span", { className: opIdStyle$1, children: op.operationId }),
1272
+ op.title && /* @__PURE__ */ jsx("span", { className: opTitleStyle$1, children: op.title }),
1273
+ op.summary && /* @__PURE__ */ jsx("span", { className: opSummaryStyle$1, children: op.summary })
1274
+ ] }),
1275
+ op.tags && op.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle$1, children: op.tags.map(
1276
+ (tag) => onTagClick ? /* @__PURE__ */ jsx(
1277
+ "button",
1278
+ {
1279
+ type: "button",
1280
+ className: tagChipButtonStyle$1,
1281
+ title: tag.description,
1282
+ onClick: () => onTagClick(tag.name),
1283
+ children: tag.name
1284
+ },
1285
+ tag.name
1286
+ ) : /* @__PURE__ */ jsx("span", { className: tagChipStyle$1, title: tag.description, children: tag.name }, tag.name)
1287
+ ) }),
1288
+ op.description && /* @__PURE__ */ jsx("div", { className: sectionStyle$1, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: op.description }) }),
1289
+ op.externalDocs && /* @__PURE__ */ jsx("div", { className: opExternalDocsStyle, children: /* @__PURE__ */ jsx(
1290
+ ExternalDocsLink,
1291
+ {
1292
+ externalDocs: op.externalDocs,
1293
+ context: op.operationId ?? op.summary ?? "operation"
1294
+ }
1295
+ ) }),
1296
+ /* @__PURE__ */ jsx(SecurityRequirementBadges, { requirements: op.securityRequirements ?? [] }),
1297
+ /* @__PURE__ */ jsx(OperationMessages, { operation: op, idx }),
1298
+ op.reply && (op.reply.messages.length > 0 || op.reply.address || op.reply.channelName) && /* @__PURE__ */ jsxs("div", { className: replyStyle$1, children: [
1299
+ /* @__PURE__ */ jsx("h4", { className: replyTitleStyle, children: "Reply" }),
1300
+ op.reply.channelName && /* @__PURE__ */ jsxs("div", { className: replyMetaRowStyle, children: [
1301
+ /* @__PURE__ */ jsx("span", { className: replyMetaLabelStyle, children: "channel" }),
1302
+ /* @__PURE__ */ jsx("code", { className: replyMetaValueStyle, children: op.reply.channelName })
1303
+ ] }),
1304
+ op.reply.address && (op.reply.address.location || op.reply.address.description) && /* @__PURE__ */ jsxs("div", { className: replyMetaRowStyle, children: [
1305
+ /* @__PURE__ */ jsx("span", { className: replyMetaLabelStyle, children: "address" }),
1306
+ op.reply.address.location && /* @__PURE__ */ jsx("code", { className: replyMetaValueStyle, children: op.reply.address.location }),
1307
+ op.reply.address.description && /* @__PURE__ */ jsx("span", { className: replyMetaDescStyle, children: op.reply.address.description })
1308
+ ] }),
1309
+ op.reply.messages.map((replyMsg, i) => /* @__PURE__ */ jsx(MessageView, { message: replyMsg, idx: `${idx}-reply-${i}` }, i))
1310
+ ] }),
1311
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: op.bindings, title: "Operation Bindings" })
1312
+ ] }, idx))
1313
+ ] })
1314
+ ]
1315
+ }
1316
+ );
1317
+ }
1318
+ function messageLabel(message, index) {
1319
+ return message.title ?? message.name ?? `Message ${index + 1}`;
1320
+ }
1321
+ function OperationMessages({ operation, idx }) {
1322
+ const messages = operation.messages ?? [];
1323
+ const [selectedIndex, setSelectedIndex] = useState(0);
1324
+ if (messages.length === 0) return null;
1325
+ const active = messages[Math.min(selectedIndex, messages.length - 1)];
1326
+ return /* @__PURE__ */ jsxs("div", { className: sectionStyle$1, children: [
1327
+ messages.length > 1 && /* @__PURE__ */ jsxs("div", { className: messageSelectorStyle, children: [
1328
+ /* @__PURE__ */ jsx("label", { htmlFor: `msg-select-${idx}`, className: messageSelectorLabelStyle, children: "Message" }),
1329
+ /* @__PURE__ */ jsx(
1330
+ "select",
1331
+ {
1332
+ id: `msg-select-${idx}`,
1333
+ className: messageSelectStyle,
1334
+ value: selectedIndex,
1335
+ onChange: (e) => setSelectedIndex(Number(e.target.value)),
1336
+ children: messages.map((m, i) => /* @__PURE__ */ jsx("option", { value: i, children: messageLabel(m, i) }, i))
1337
+ }
1338
+ ),
1339
+ /* @__PURE__ */ jsxs("span", { className: messageCountStyle, children: [
1340
+ messages.length,
1341
+ " messages"
1342
+ ] })
1343
+ ] }),
1344
+ /* @__PURE__ */ jsx(MessageView, { message: active, idx })
1345
+ ] });
1346
+ }
1347
+ function MessageView({ message, idx }) {
1348
+ return /* @__PURE__ */ jsxs("div", { children: [
1349
+ /* @__PURE__ */ jsxs("h4", { className: sectionTitleStyle$1, children: [
1350
+ "Message",
1351
+ (message.title ?? message.name) && /* @__PURE__ */ jsxs("span", { className: messageTitleStyle$1, children: [
1352
+ " \u2014 ",
1353
+ message.title ?? message.name
1354
+ ] })
1355
+ ] }),
1356
+ message.summary && /* @__PURE__ */ jsx("p", { className: messageSummaryStyle$1, children: message.summary }),
1357
+ message.contentType && /* @__PURE__ */ jsx("code", { className: contentTypeStyle$2, children: message.contentType }),
1358
+ /* @__PURE__ */ jsx(MessagePayload, { message, idx }),
1359
+ message.correlationId && /* @__PURE__ */ jsxs("div", { className: correlationIdStyle, children: [
1360
+ /* @__PURE__ */ jsx("span", { className: correlationIdLabelStyle, children: "correlationId" }),
1361
+ /* @__PURE__ */ jsx("code", { className: correlationIdLocationStyle, children: message.correlationId.location }),
1362
+ message.correlationId.description && /* @__PURE__ */ jsx("span", { className: correlationIdDescStyle, children: message.correlationId.description })
1363
+ ] }),
1364
+ message.headers && /* @__PURE__ */ jsxs("div", { className: headersWrapStyle$1, children: [
1365
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle$1, children: "Headers" }),
1366
+ /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(message.headers) })
1367
+ ] }),
1368
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: message.bindings, title: "Message Bindings" })
1369
+ ] });
1370
+ }
1371
+ const bodyStyle = css({
1372
+ padding: "0.75rem 1rem",
1373
+ [mq.desktop]: {
1374
+ padding: "1rem 1.25rem"
1375
+ }
1376
+ });
1377
+ const sectionStyle$1 = css({
1378
+ marginBottom: "1.5rem"
1379
+ });
1380
+ const sectionTitleStyle$1 = css({
1381
+ margin: "0 0 0.75rem",
1382
+ fontSize: "var(--omnispec-font-size-md)",
1383
+ fontWeight: 700,
1384
+ color: "var(--omnispec-fg-primary)",
1385
+ letterSpacing: "0.02em"
1386
+ });
1387
+ const paramListStyle$1 = css({
1388
+ display: "flex",
1389
+ flexDirection: "column"
1390
+ });
1391
+ const paramRowStyle$1 = css({
1392
+ padding: "0.75rem 0"
1393
+ });
1394
+ const paramHeaderStyle$1 = css({
1395
+ display: "flex",
1396
+ alignItems: "center",
1397
+ gap: "0.5rem",
1398
+ flexWrap: "wrap"
1399
+ });
1400
+ const paramNameStyle$1 = css({
1401
+ fontSize: "var(--omnispec-font-size-sm)",
1402
+ fontWeight: 700,
1403
+ backgroundColor: "transparent",
1404
+ padding: 0
1405
+ });
1406
+ const typeBadgeStyle$2 = css({
1407
+ fontSize: "var(--omnispec-font-size-xs)",
1408
+ fontWeight: 400
1409
+ });
1410
+ const paramDescStyle$1 = css({
1411
+ margin: "0.25rem 0 0",
1412
+ fontSize: "var(--omnispec-font-size-base)",
1413
+ color: "var(--omnispec-fg-secondary)",
1414
+ lineHeight: 1.5
1415
+ });
1416
+ const paramConstraintsStyle$1 = css({
1417
+ display: "flex",
1418
+ flexWrap: "wrap",
1419
+ gap: "0.375rem",
1420
+ marginTop: "0.375rem"
1421
+ });
1422
+ const operationStyle = css({
1423
+ padding: "0.75rem 0",
1424
+ borderTop: "1px solid var(--omnispec-border-color)"
1425
+ });
1426
+ const opHeaderStyle$1 = css({
1427
+ display: "flex",
1428
+ alignItems: "center",
1429
+ gap: "0.5rem",
1430
+ marginBottom: "0.5rem"
1431
+ });
1432
+ const actionBadgeBase$1 = css({
1433
+ display: "inline-block",
1434
+ padding: "0.125rem 0.375rem",
1435
+ borderRadius: "0.1875rem",
1436
+ fontSize: "0.5625rem",
1437
+ fontWeight: 700,
1438
+ fontFamily: "var(--omnispec-font-mono)",
1439
+ color: "#ffffff",
1440
+ letterSpacing: "0.0313rem"
1441
+ });
1442
+ const opIdStyle$1 = css({
1443
+ fontSize: "var(--omnispec-font-size-sm)",
1444
+ fontWeight: 700,
1445
+ backgroundColor: "transparent",
1446
+ padding: 0
1447
+ });
1448
+ const opTitleStyle$1 = css({
1449
+ fontSize: "var(--omnispec-font-size-sm)",
1450
+ fontWeight: 600,
1451
+ color: "var(--omnispec-fg-primary)"
1452
+ });
1453
+ const opSummaryStyle$1 = css({
1454
+ fontSize: "var(--omnispec-font-size-sm)",
1455
+ color: "var(--omnispec-fg-secondary)"
1456
+ });
1457
+ const opExternalDocsStyle = css({
1458
+ marginBottom: "0.75rem"
1459
+ });
1460
+ const messageTitleStyle$1 = css({
1461
+ fontWeight: 400,
1462
+ color: "var(--omnispec-fg-primary)"
1463
+ });
1464
+ const messageSummaryStyle$1 = css({
1465
+ margin: "0 0 0.5rem",
1466
+ fontSize: "var(--omnispec-font-size-base)",
1467
+ color: "var(--omnispec-fg-secondary)"
1468
+ });
1469
+ const contentTypeStyle$2 = css({
1470
+ fontFamily: "var(--omnispec-font-mono)",
1471
+ fontSize: "var(--omnispec-font-size-xs)",
1472
+ color: "var(--omnispec-fg-muted)",
1473
+ display: "block",
1474
+ marginBottom: "0.5rem",
1475
+ backgroundColor: "transparent",
1476
+ padding: 0
1477
+ });
1478
+ const headersWrapStyle$1 = css({
1479
+ marginTop: "1rem"
1480
+ });
1481
+ const messageSelectorStyle = css({
1482
+ display: "flex",
1483
+ alignItems: "center",
1484
+ gap: "0.5rem",
1485
+ flexWrap: "wrap",
1486
+ marginBottom: "0.75rem"
1487
+ });
1488
+ const messageSelectorLabelStyle = css({
1489
+ fontSize: "var(--omnispec-font-size-xs)",
1490
+ fontWeight: 600,
1491
+ color: "var(--omnispec-fg-muted)",
1492
+ textTransform: "uppercase",
1493
+ letterSpacing: "0.0313rem",
1494
+ whiteSpace: "nowrap"
1495
+ });
1496
+ const messageSelectStyle = css({
1497
+ padding: "0.375rem 0.625rem",
1498
+ border: "1px solid var(--omnispec-input-border)",
1499
+ borderRadius: "var(--omnispec-border-radius)",
1500
+ backgroundColor: "var(--omnispec-input-bg)",
1501
+ color: "var(--omnispec-fg-primary)",
1502
+ fontSize: "var(--omnispec-font-size-sm)",
1503
+ fontFamily: "var(--omnispec-font-mono)"
1504
+ });
1505
+ const messageCountStyle = css({
1506
+ fontSize: "var(--omnispec-font-size-xs)",
1507
+ color: "var(--omnispec-fg-muted)"
1508
+ });
1509
+ const correlationIdStyle = css({
1510
+ display: "flex",
1511
+ alignItems: "center",
1512
+ gap: "0.5rem",
1513
+ flexWrap: "wrap",
1514
+ marginTop: "0.75rem"
1515
+ });
1516
+ const correlationIdLabelStyle = css({
1517
+ fontSize: "var(--omnispec-font-size-xs)",
1518
+ fontWeight: 700,
1519
+ color: "var(--omnispec-fg-primary)",
1520
+ fontFamily: "var(--omnispec-font-mono)"
1521
+ });
1522
+ const correlationIdLocationStyle = css({
1523
+ fontFamily: "var(--omnispec-font-mono)",
1524
+ fontSize: "var(--omnispec-font-size-xs)",
1525
+ color: "var(--omnispec-fg-code)",
1526
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1527
+ padding: "1px 0.375rem",
1528
+ borderRadius: "0.1875rem"
1529
+ });
1530
+ const correlationIdDescStyle = css({
1531
+ fontSize: "var(--omnispec-font-size-xs)",
1532
+ color: "var(--omnispec-fg-secondary)"
1533
+ });
1534
+ const replyStyle$1 = css({
1535
+ marginTop: "1rem",
1536
+ paddingLeft: "0.75rem",
1537
+ borderLeft: "0.125rem solid var(--omnispec-border-color)"
1538
+ });
1539
+ const replyTitleStyle = css({
1540
+ margin: "0 0 0.5rem",
1541
+ fontSize: "var(--omnispec-font-size-md)",
1542
+ fontWeight: 700,
1543
+ color: "var(--omnispec-fg-primary)",
1544
+ letterSpacing: "0.02em"
1545
+ });
1546
+ const replyMetaRowStyle = css({
1547
+ display: "flex",
1548
+ alignItems: "center",
1549
+ gap: "0.5rem",
1550
+ flexWrap: "wrap",
1551
+ marginBottom: "0.5rem"
1552
+ });
1553
+ const replyMetaLabelStyle = css({
1554
+ fontSize: "var(--omnispec-font-size-xs)",
1555
+ fontWeight: 700,
1556
+ color: "var(--omnispec-fg-primary)",
1557
+ fontFamily: "var(--omnispec-font-mono)"
1558
+ });
1559
+ const replyMetaValueStyle = css({
1560
+ fontFamily: "var(--omnispec-font-mono)",
1561
+ fontSize: "var(--omnispec-font-size-xs)",
1562
+ color: "var(--omnispec-fg-code)",
1563
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1564
+ padding: "1px 0.375rem",
1565
+ borderRadius: "0.1875rem"
1566
+ });
1567
+ const replyMetaDescStyle = css({
1568
+ fontSize: "var(--omnispec-font-size-xs)",
1569
+ color: "var(--omnispec-fg-secondary)"
1570
+ });
1571
+ const tagChipsStyle$1 = css({
1572
+ display: "flex",
1573
+ flexWrap: "wrap",
1574
+ gap: "0.25rem",
1575
+ marginBottom: "0.5rem"
1576
+ });
1577
+ const tagChipStyle$1 = css({
1578
+ fontSize: "var(--omnispec-font-size-xxs)",
1579
+ fontFamily: "var(--omnispec-font-mono)",
1580
+ color: "var(--omnispec-fg-secondary)",
1581
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1582
+ padding: "1px 0.5rem",
1583
+ borderRadius: "0.625rem"
1584
+ });
1585
+ const tagChipButtonStyle$1 = css({
1586
+ fontSize: "var(--omnispec-font-size-xxs)",
1587
+ fontFamily: "var(--omnispec-font-mono)",
1588
+ color: "var(--omnispec-fg-secondary)",
1589
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1590
+ padding: "1px 0.5rem",
1591
+ borderRadius: "0.625rem",
1592
+ border: "none",
1593
+ cursor: "pointer",
1594
+ "&:hover": {
1595
+ color: "var(--omnispec-fg-primary)"
1596
+ }
1597
+ });
1598
+
1599
+ const actionLabels = {
1600
+ publish: "PUB",
1601
+ subscribe: "SUB",
1602
+ send: "SEND",
1603
+ receive: "RECV"
1604
+ };
1605
+ const actionColors = {
1606
+ publish: "var(--omnispec-color-publish)",
1607
+ subscribe: "var(--omnispec-color-subscribe)",
1608
+ send: "var(--omnispec-color-publish)",
1609
+ receive: "var(--omnispec-color-subscribe)"
1610
+ };
1611
+ function ChannelReferenceDetail({ channel, id, expandAll, expandGeneration, onTagClick }) {
1612
+ const primaryAction = channel.operations[0]?.action;
1613
+ const primaryLabel = actionLabels[primaryAction] ?? primaryAction?.toUpperCase() ?? "";
1614
+ const primaryColor = actionColors[primaryAction] ?? "var(--omnispec-fg-muted)";
1615
+ return /* @__PURE__ */ jsxs(
1616
+ ExpandableCard,
1617
+ {
1618
+ id,
1619
+ title: channel.address,
1620
+ rightLabel: `${channel.operations.length} ${channel.operations.length === 1 ? "operation" : "operations"}`,
1621
+ expandAll,
1622
+ expandGeneration,
1623
+ children: [
1624
+ /* @__PURE__ */ jsx(MethodBar, { label: primaryLabel, path: channel.address, color: primaryColor }),
1625
+ channel.description && /* @__PURE__ */ jsx("div", { className: channelMetaStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: channel.description }) }),
1626
+ channel.externalDocs && /* @__PURE__ */ jsx("div", { className: channelMetaStyle, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: channel.externalDocs, context: channel.address }) }),
1627
+ channel.operations.map((op, idx) => /* @__PURE__ */ jsx("div", { id: id ? `${id}-op-${idx}` : void 0, className: operationWrapStyle, children: /* @__PURE__ */ jsx(
1628
+ ReferenceLayout,
1629
+ {
1630
+ operationId: op.operationId ?? `${channel.name}-op-${idx}`,
1631
+ schema: /* @__PURE__ */ jsx(
1632
+ OperationSchemaColumn,
1633
+ {
1634
+ channel,
1635
+ operation: op,
1636
+ onTagClick
1637
+ }
1638
+ ),
1639
+ samples: /* @__PURE__ */ jsx(OperationSamplesColumn, { operation: op, idx }),
1640
+ tryIt: /* @__PURE__ */ jsx("div", { className: tryItNaStyle, children: "Interactive testing is not available for AsyncAPI protocols." })
1641
+ }
1642
+ ) }, idx))
1643
+ ]
1644
+ }
1645
+ );
1646
+ }
1647
+ function OperationSchemaColumn({
1648
+ channel,
1649
+ operation,
1650
+ onTagClick
1651
+ }) {
1652
+ return /* @__PURE__ */ jsxs("div", { children: [
1653
+ /* @__PURE__ */ jsxs("div", { className: opHeaderStyle, children: [
1654
+ /* @__PURE__ */ jsx(
1655
+ "span",
1656
+ {
1657
+ className: cx(actionBadgeBase, css({
1658
+ backgroundColor: actionColors[operation.action] ?? "var(--omnispec-fg-muted)"
1659
+ })),
1660
+ children: actionLabels[operation.action] ?? operation.action.toUpperCase()
1661
+ }
1662
+ ),
1663
+ operation.operationId && /* @__PURE__ */ jsx("span", { className: opIdStyle, children: operation.operationId }),
1664
+ operation.title && /* @__PURE__ */ jsx("span", { className: opTitleStyle, children: operation.title }),
1665
+ operation.summary && /* @__PURE__ */ jsx("span", { className: opSummaryStyle, children: operation.summary })
1666
+ ] }),
1667
+ operation.tags && operation.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: tagChipsStyle, children: operation.tags.map(
1668
+ (tag) => onTagClick ? /* @__PURE__ */ jsx(
1669
+ "button",
1670
+ {
1671
+ type: "button",
1672
+ className: tagChipButtonStyle,
1673
+ title: tag.description,
1674
+ onClick: () => onTagClick(tag.name),
1675
+ children: tag.name
1676
+ },
1677
+ tag.name
1678
+ ) : /* @__PURE__ */ jsx("span", { className: tagChipStyle, title: tag.description, children: tag.name }, tag.name)
1679
+ ) }),
1680
+ operation.description && /* @__PURE__ */ jsx("div", { className: sectionStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: operation.description }) }),
1681
+ operation.externalDocs && /* @__PURE__ */ jsx("div", { className: sectionStyle, children: /* @__PURE__ */ jsx(
1682
+ ExternalDocsLink,
1683
+ {
1684
+ externalDocs: operation.externalDocs,
1685
+ context: operation.operationId ?? operation.summary ?? "operation"
1686
+ }
1687
+ ) }),
1688
+ channel.parameters && Object.keys(channel.parameters).length > 0 && /* @__PURE__ */ jsxs("div", { className: sectionStyle, children: [
1689
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle, children: "Parameters" }),
1690
+ /* @__PURE__ */ jsx("div", { className: paramListStyle, children: Object.entries(channel.parameters).map(([name, param]) => {
1691
+ const schema = param.schema ?? {};
1692
+ const paramType = schema.type;
1693
+ const paramFormat = schema.format;
1694
+ const paramEnum = schema.enum;
1695
+ const constraintBadges = buildConstraints(schema);
1696
+ return /* @__PURE__ */ jsxs("div", { className: paramRowStyle, children: [
1697
+ /* @__PURE__ */ jsxs("div", { className: paramHeaderStyle, children: [
1698
+ /* @__PURE__ */ jsx("span", { className: paramNameStyle, children: name }),
1699
+ paramType && /* @__PURE__ */ jsx("pre", { className: typeBadgeStyle$1, children: paramType })
1700
+ ] }),
1701
+ (paramFormat || constraintBadges.length > 0 || paramEnum && paramEnum.length > 0) && /* @__PURE__ */ jsxs("div", { className: paramConstraintsStyle, children: [
1702
+ paramFormat && /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: paramFormat }),
1703
+ constraintBadges.map((c) => /* @__PURE__ */ jsx(SchemaBadge, { variant: "constraint", children: c }, c)),
1704
+ paramEnum && paramEnum.length > 0 && /* @__PURE__ */ jsxs(SchemaBadge, { variant: "enum", children: [
1705
+ "enum: ",
1706
+ paramEnum.map(String).join(" | ")
1707
+ ] })
1708
+ ] }),
1709
+ param.description && /* @__PURE__ */ jsx("p", { className: paramDescStyle, children: param.description })
1710
+ ] }, name);
1711
+ }) })
1712
+ ] }),
1713
+ /* @__PURE__ */ jsx(SecurityRequirementBadges, { requirements: operation.securityRequirements ?? [] }),
1714
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: operation.bindings, title: "Operation Bindings" }),
1715
+ /* @__PURE__ */ jsx(BindingsSection, { bindings: channel.bindings, title: "Channel Bindings" })
1716
+ ] });
1717
+ }
1718
+ function OperationSamplesColumn({ operation, idx }) {
1719
+ const messages = operation.messages ?? [];
1720
+ const replyMessages = operation.reply?.messages ?? [];
1721
+ if (messages.length === 0 && replyMessages.length === 0) {
1722
+ return /* @__PURE__ */ jsx("div", { className: emptySamplesStyle, children: "No message payload is defined for this operation." });
1723
+ }
1724
+ return /* @__PURE__ */ jsxs("div", { className: samplesColumnStyle, children: [
1725
+ messages.map((message, i) => /* @__PURE__ */ jsxs("div", { children: [
1726
+ /* @__PURE__ */ jsxs("h4", { className: sectionTitleStyle, children: [
1727
+ "Message",
1728
+ (message.title ?? message.name) && /* @__PURE__ */ jsxs("span", { className: messageTitleStyle, children: [
1729
+ " \u2014 ",
1730
+ message.title ?? message.name
1731
+ ] })
1732
+ ] }),
1733
+ message.contentType && /* @__PURE__ */ jsx("code", { className: contentTypeStyle$1, children: message.contentType }),
1734
+ /* @__PURE__ */ jsx(MessagePayload, { message, idx: `${idx}-msg-${i}` })
1735
+ ] }, i)),
1736
+ replyMessages.length > 0 && /* @__PURE__ */ jsxs("div", { className: replyStyle, children: [
1737
+ /* @__PURE__ */ jsx("h4", { className: sectionTitleStyle, children: "Reply" }),
1738
+ replyMessages.map((message, i) => /* @__PURE__ */ jsx(MessagePayload, { message, idx: `${idx}-reply-${i}` }, i))
1739
+ ] })
1740
+ ] });
1741
+ }
1742
+ const channelMetaStyle = css({
1743
+ padding: "0.75rem 1rem 0",
1744
+ [mq.desktop]: {
1745
+ padding: "1rem 1.25rem 0"
1746
+ }
1747
+ });
1748
+ const operationWrapStyle = css({
1749
+ borderTop: "1px solid var(--omnispec-border-color)"
1750
+ });
1751
+ const tryItNaStyle = css({
1752
+ fontSize: "var(--omnispec-font-size-sm)",
1753
+ color: "var(--omnispec-fg-muted)",
1754
+ fontStyle: "italic",
1755
+ padding: "0.5rem 0"
1756
+ });
1757
+ const samplesColumnStyle = css({
1758
+ display: "flex",
1759
+ flexDirection: "column",
1760
+ gap: "1.5rem"
1761
+ });
1762
+ const emptySamplesStyle = css({
1763
+ fontSize: "var(--omnispec-font-size-sm)",
1764
+ color: "var(--omnispec-fg-muted)",
1765
+ fontStyle: "italic"
1766
+ });
1767
+ const sectionStyle = css({
1768
+ marginBottom: "1.5rem"
1769
+ });
1770
+ const sectionTitleStyle = css({
1771
+ margin: "0 0 0.75rem",
1772
+ fontSize: "var(--omnispec-font-size-md)",
1773
+ fontWeight: 700,
1774
+ color: "var(--omnispec-fg-primary)",
1775
+ letterSpacing: "0.02em"
1776
+ });
1777
+ const paramListStyle = css({
1778
+ display: "flex",
1779
+ flexDirection: "column"
1780
+ });
1781
+ const paramRowStyle = css({
1782
+ padding: "0.75rem 0"
1783
+ });
1784
+ const paramHeaderStyle = css({
1785
+ display: "flex",
1786
+ alignItems: "center",
1787
+ gap: "0.5rem",
1788
+ flexWrap: "wrap"
1789
+ });
1790
+ const paramNameStyle = css({
1791
+ fontSize: "var(--omnispec-font-size-sm)",
1792
+ fontWeight: 700,
1793
+ backgroundColor: "transparent",
1794
+ padding: 0
1795
+ });
1796
+ const typeBadgeStyle$1 = css({
1797
+ fontSize: "var(--omnispec-font-size-xs)",
1798
+ fontWeight: 400
1799
+ });
1800
+ const paramDescStyle = css({
1801
+ margin: "0.25rem 0 0",
1802
+ fontSize: "var(--omnispec-font-size-base)",
1803
+ color: "var(--omnispec-fg-secondary)",
1804
+ lineHeight: 1.5
1805
+ });
1806
+ const paramConstraintsStyle = css({
1807
+ display: "flex",
1808
+ flexWrap: "wrap",
1809
+ gap: "0.375rem",
1810
+ marginTop: "0.375rem"
1811
+ });
1812
+ const opHeaderStyle = css({
1813
+ display: "flex",
1814
+ alignItems: "center",
1815
+ gap: "0.5rem",
1816
+ marginBottom: "0.5rem"
1817
+ });
1818
+ const actionBadgeBase = css({
1819
+ display: "inline-block",
1820
+ padding: "0.125rem 0.375rem",
1821
+ borderRadius: "0.1875rem",
1822
+ fontSize: "0.5625rem",
1823
+ fontWeight: 700,
1824
+ fontFamily: "var(--omnispec-font-mono)",
1825
+ color: "#ffffff",
1826
+ letterSpacing: "0.0313rem"
1827
+ });
1828
+ const opIdStyle = css({
1829
+ fontSize: "var(--omnispec-font-size-sm)",
1830
+ fontWeight: 700,
1831
+ backgroundColor: "transparent",
1832
+ padding: 0
1833
+ });
1834
+ const opTitleStyle = css({
1835
+ fontSize: "var(--omnispec-font-size-sm)",
1836
+ fontWeight: 600,
1837
+ color: "var(--omnispec-fg-primary)"
1838
+ });
1839
+ const opSummaryStyle = css({
1840
+ fontSize: "var(--omnispec-font-size-sm)",
1841
+ color: "var(--omnispec-fg-secondary)"
1842
+ });
1843
+ const messageTitleStyle = css({
1844
+ fontWeight: 400,
1845
+ color: "var(--omnispec-fg-primary)"
1846
+ });
1847
+ const contentTypeStyle$1 = css({
1848
+ fontFamily: "var(--omnispec-font-mono)",
1849
+ fontSize: "var(--omnispec-font-size-xs)",
1850
+ color: "var(--omnispec-fg-muted)",
1851
+ display: "block",
1852
+ marginBottom: "0.5rem",
1853
+ backgroundColor: "transparent",
1854
+ padding: 0
1855
+ });
1856
+ const replyStyle = css({
1857
+ paddingLeft: "0.75rem",
1858
+ borderLeft: "0.125rem solid var(--omnispec-border-color)"
1859
+ });
1860
+ const tagChipsStyle = css({
1861
+ display: "flex",
1862
+ flexWrap: "wrap",
1863
+ gap: "0.25rem",
1864
+ marginBottom: "0.5rem"
1865
+ });
1866
+ const tagChipStyle = css({
1867
+ fontSize: "var(--omnispec-font-size-xxs)",
1868
+ fontFamily: "var(--omnispec-font-mono)",
1869
+ color: "var(--omnispec-fg-secondary)",
1870
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1871
+ padding: "1px 0.5rem",
1872
+ borderRadius: "0.625rem"
1873
+ });
1874
+ const tagChipButtonStyle = css({
1875
+ fontSize: "var(--omnispec-font-size-xxs)",
1876
+ fontFamily: "var(--omnispec-font-mono)",
1877
+ color: "var(--omnispec-fg-secondary)",
1878
+ backgroundColor: "var(--omnispec-bg-tertiary)",
1879
+ padding: "1px 0.5rem",
1880
+ borderRadius: "0.625rem",
1881
+ border: "none",
1882
+ cursor: "pointer",
1883
+ "&:hover": {
1884
+ color: "var(--omnispec-fg-primary)"
1885
+ }
1886
+ });
1887
+
1888
+ function ComponentsSection({ components }) {
1889
+ const schemas = Object.entries(components.schemas);
1890
+ const messages = Object.entries(components.messages ?? {});
1891
+ if (schemas.length === 0 && messages.length === 0) return null;
1892
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1893
+ messages.length > 0 && /* @__PURE__ */ jsxs("div", { className: `omnispec-async-messages ${containerStyle$1}`, id: "messages", children: [
1894
+ /* @__PURE__ */ jsx("h2", { className: titleStyle$2, children: "Messages" }),
1895
+ /* @__PURE__ */ jsx("div", { className: schemaWrapperStyle, children: messages.map(([name, message]) => /* @__PURE__ */ jsx("div", { className: schemaStyle, id: `message-${name}`, children: /* @__PURE__ */ jsxs(
1896
+ Collapsible,
1897
+ {
1898
+ title: /* @__PURE__ */ jsx("code", { className: schemaNameStyle, children: name }),
1899
+ defaultOpen: false,
1900
+ children: [
1901
+ message.title && /* @__PURE__ */ jsx("p", { className: messageSummaryStyle, children: message.title }),
1902
+ message.summary && /* @__PURE__ */ jsx("p", { className: messageSummaryStyle, children: message.summary }),
1903
+ message.contentType && /* @__PURE__ */ jsxs("code", { className: contentTypeStyle, children: [
1904
+ message.contentType,
1905
+ message.contentTypeInherited && /* @__PURE__ */ jsx("span", { className: contentTypeHintStyle, children: " (default)" })
1906
+ ] }),
1907
+ /* @__PURE__ */ jsx(MessagePayload, { message, idx: `message-${name}` }),
1908
+ message.headers && /* @__PURE__ */ jsxs("div", { className: headersWrapStyle, children: [
1909
+ /* @__PURE__ */ jsx("h4", { className: headersTitleStyle, children: "Headers" }),
1910
+ /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(message.headers) })
1911
+ ] })
1912
+ ]
1913
+ }
1914
+ ) }, name)) })
1915
+ ] }),
1916
+ schemas.length > 0 && /* @__PURE__ */ jsxs("div", { className: `omnispec-async-components ${containerStyle$1}`, id: "schemas", children: [
1917
+ /* @__PURE__ */ jsx("h2", { className: titleStyle$2, children: "Schemas" }),
1918
+ /* @__PURE__ */ jsx("div", { className: schemaWrapperStyle, children: schemas.map(([name, schema]) => /* @__PURE__ */ jsx("div", { className: schemaStyle, id: `schema-${name}`, children: /* @__PURE__ */ jsx(
1919
+ Collapsible,
1920
+ {
1921
+ title: /* @__PURE__ */ jsx("code", { className: schemaNameStyle, children: name }),
1922
+ defaultOpen: false,
1923
+ children: /* @__PURE__ */ jsx(SchemaTree, { nodes: schemaToNodes(schema) })
1924
+ }
1925
+ ) }, name)) })
1926
+ ] })
1927
+ ] });
1928
+ }
1929
+ const containerStyle$1 = css({
1930
+ marginTop: "2rem",
1931
+ paddingTop: "1.5rem",
1932
+ borderTop: "1px solid var(--omnispec-border-color)",
1933
+ [mq.mobile]: {
1934
+ borderTop: "none",
1935
+ marginTop: "1.5rem",
1936
+ paddingTop: "1rem"
1937
+ }
1938
+ });
1939
+ const titleStyle$2 = css({
1940
+ margin: "0 0 1rem",
1941
+ fontSize: "var(--omnispec-h2-font-size)",
1942
+ color: "var(--omnispec-h2-color)",
1943
+ fontWeight: 700
1944
+ });
1945
+ const schemaWrapperStyle = css({
1946
+ border: "1px solid var(--omnispec-border-color)",
1947
+ borderRadius: "0.5rem",
1948
+ padding: "1.5rem 1rem"
1949
+ });
1950
+ const schemaStyle = css({
1951
+ marginBottom: "0.5rem"
1952
+ });
1953
+ const schemaNameStyle = css({
1954
+ fontFamily: "var(--omnispec-font-mono)",
1955
+ fontSize: "var(--omnispec-font-size-base)",
1956
+ fontWeight: 600,
1957
+ color: "var(--omnispec-color-primary)",
1958
+ backgroundColor: "transparent",
1959
+ padding: 0,
1960
+ "&:hover": {
1961
+ textDecoration: "underline"
1962
+ }
1963
+ });
1964
+ const messageSummaryStyle = css({
1965
+ margin: "0 0 0.5rem",
1966
+ fontSize: "var(--omnispec-font-size-sm)",
1967
+ color: "var(--omnispec-fg-secondary)"
1968
+ });
1969
+ const contentTypeStyle = css({
1970
+ display: "block",
1971
+ fontFamily: "var(--omnispec-font-mono)",
1972
+ fontSize: "var(--omnispec-font-size-xs)",
1973
+ color: "var(--omnispec-fg-muted)",
1974
+ marginBottom: "0.5rem"
1975
+ });
1976
+ const contentTypeHintStyle = css({
1977
+ fontStyle: "italic",
1978
+ color: "var(--omnispec-fg-muted)"
1979
+ });
1980
+ const headersWrapStyle = css({
1981
+ marginTop: "1rem"
1982
+ });
1983
+ const headersTitleStyle = css({
1984
+ margin: "0 0 0.75rem",
1985
+ fontSize: "var(--omnispec-font-size-md)",
1986
+ fontWeight: 700,
1987
+ color: "var(--omnispec-fg-primary)",
1988
+ letterSpacing: "0.02em"
1989
+ });
1990
+
1991
+ const SPECIAL_KEYS = /* @__PURE__ */ new Set(["type", "description", "flows"]);
1992
+ function SecuritySchemesSection({ securitySchemes }) {
1993
+ const entries = Object.entries(securitySchemes ?? {});
1994
+ if (entries.length === 0) return null;
1995
+ return /* @__PURE__ */ jsxs("div", { className: `omnispec-async-security ${containerStyle}`, id: "security", children: [
1996
+ /* @__PURE__ */ jsx("h2", { className: titleStyle$1, children: "Security Schemes" }),
1997
+ /* @__PURE__ */ jsx("div", { className: listStyle, children: entries.map(([name, scheme]) => /* @__PURE__ */ jsxs("div", { className: cardStyle, id: `security-${name}`, children: [
1998
+ /* @__PURE__ */ jsxs("div", { className: headerStyle$1, children: [
1999
+ /* @__PURE__ */ jsx(Icon, { name: "lock", size: "0.875rem" }),
2000
+ /* @__PURE__ */ jsx("code", { className: nameStyle, children: name }),
2001
+ /* @__PURE__ */ jsx("span", { className: typeBadgeStyle, children: scheme.type })
2002
+ ] }),
2003
+ scheme.description && /* @__PURE__ */ jsx("p", { className: descStyle$1, children: scheme.description }),
2004
+ /* @__PURE__ */ jsx(
2005
+ FieldRows,
2006
+ {
2007
+ fields: Object.entries(scheme).filter(
2008
+ ([key, value]) => !SPECIAL_KEYS.has(key) && value !== void 0 && typeof value !== "object"
2009
+ )
2010
+ }
2011
+ ),
2012
+ scheme.flows && Object.keys(scheme.flows).length > 0 && /* @__PURE__ */ jsx("div", { className: flowsStyle, children: Object.entries(scheme.flows).map(([flowName, flow]) => /* @__PURE__ */ jsx(OAuthFlow, { name: flowName, flow }, flowName)) })
2013
+ ] }, name)) })
2014
+ ] });
2015
+ }
2016
+ function OAuthFlow({ name, flow }) {
2017
+ const scopes = flow.availableScopes ?? flow.scopes ?? {};
2018
+ const urls = Object.entries(flow).filter(
2019
+ ([key, value]) => key !== "availableScopes" && key !== "scopes" && typeof value === "string"
2020
+ );
2021
+ return /* @__PURE__ */ jsxs("div", { className: flowCardStyle, children: [
2022
+ /* @__PURE__ */ jsx("div", { className: flowNameStyle, children: name }),
2023
+ /* @__PURE__ */ jsx(FieldRows, { fields: urls }),
2024
+ Object.keys(scopes).length > 0 && /* @__PURE__ */ jsxs("div", { className: scopesStyle, children: [
2025
+ /* @__PURE__ */ jsx("span", { className: scopesLabelStyle, children: "Scopes" }),
2026
+ /* @__PURE__ */ jsx("ul", { className: scopeListStyle, children: Object.entries(scopes).map(([scope, desc]) => /* @__PURE__ */ jsxs("li", { className: scopeRowStyle, children: [
2027
+ /* @__PURE__ */ jsx("code", { className: scopeNameStyle, children: scope }),
2028
+ desc && /* @__PURE__ */ jsx("span", { className: scopeDescStyle, children: desc })
2029
+ ] }, scope)) })
2030
+ ] })
2031
+ ] });
2032
+ }
2033
+ const containerStyle = css({
2034
+ marginTop: "1.5rem",
2035
+ paddingTop: "1rem",
2036
+ [mq.desktop]: {
2037
+ marginTop: "2rem",
2038
+ paddingTop: "1.5rem",
2039
+ borderTop: "1px solid var(--omnispec-border-color)"
2040
+ }
2041
+ });
2042
+ const titleStyle$1 = css({
2043
+ margin: "0 0 1rem",
2044
+ fontSize: "var(--omnispec-h2-font-size)",
2045
+ color: "var(--omnispec-h2-color)",
2046
+ fontWeight: 700
2047
+ });
2048
+ const listStyle = css({
2049
+ display: "flex",
2050
+ flexDirection: "column",
2051
+ gap: "0.75rem"
2052
+ });
2053
+ const cardStyle = css({
2054
+ padding: "0.75rem 0.875rem",
2055
+ borderRadius: "var(--omnispec-border-radius)",
2056
+ backgroundColor: "var(--omnispec-bg-secondary)"
2057
+ });
2058
+ const headerStyle$1 = css({
2059
+ display: "flex",
2060
+ alignItems: "center",
2061
+ gap: "0.5rem",
2062
+ marginBottom: "0.375rem"
2063
+ });
2064
+ const nameStyle = css({
2065
+ fontFamily: "var(--omnispec-font-mono)",
2066
+ fontSize: "var(--omnispec-font-size-sm)",
2067
+ fontWeight: 700,
2068
+ color: "var(--omnispec-color-primary)",
2069
+ backgroundColor: "transparent",
2070
+ padding: 0
2071
+ });
2072
+ const typeBadgeStyle = css({
2073
+ fontSize: "var(--omnispec-font-size-xxs)",
2074
+ fontFamily: "var(--omnispec-font-mono)",
2075
+ color: "var(--omnispec-fg-secondary)",
2076
+ backgroundColor: "var(--omnispec-bg-tertiary)",
2077
+ padding: "0.0625rem 0.375rem",
2078
+ borderRadius: "var(--omnispec-border-radius)"
2079
+ });
2080
+ const descStyle$1 = css({
2081
+ margin: "0 0 0.5rem",
2082
+ fontSize: "var(--omnispec-font-size-sm)",
2083
+ color: "var(--omnispec-fg-secondary)"
2084
+ });
2085
+ const flowsStyle = css({
2086
+ marginTop: "0.625rem",
2087
+ display: "flex",
2088
+ flexDirection: "column",
2089
+ gap: "0.5rem"
2090
+ });
2091
+ const flowCardStyle = css({
2092
+ padding: "0.5rem 0.625rem",
2093
+ borderRadius: "var(--omnispec-border-radius)",
2094
+ backgroundColor: "var(--omnispec-bg-tertiary)"
2095
+ });
2096
+ const flowNameStyle = css({
2097
+ fontFamily: "var(--omnispec-font-mono)",
2098
+ fontSize: "var(--omnispec-font-size-xs)",
2099
+ fontWeight: 700,
2100
+ color: "var(--omnispec-fg-primary)"
2101
+ });
2102
+ const scopesStyle = css({
2103
+ marginTop: "0.375rem"
2104
+ });
2105
+ const scopesLabelStyle = css({
2106
+ fontSize: "var(--omnispec-font-size-xxs)",
2107
+ fontWeight: 600,
2108
+ textTransform: "uppercase",
2109
+ letterSpacing: "0.05em",
2110
+ color: "var(--omnispec-fg-muted)"
2111
+ });
2112
+ const scopeListStyle = css({
2113
+ listStyle: "none",
2114
+ margin: "0.25rem 0 0",
2115
+ padding: 0,
2116
+ display: "flex",
2117
+ flexDirection: "column",
2118
+ gap: "0.125rem"
2119
+ });
2120
+ const scopeRowStyle = css({
2121
+ display: "flex",
2122
+ gap: "0.5rem",
2123
+ alignItems: "baseline",
2124
+ flexWrap: "wrap"
2125
+ });
2126
+ const scopeNameStyle = css({
2127
+ fontFamily: "var(--omnispec-font-mono)",
2128
+ fontSize: "var(--omnispec-font-size-xs)",
2129
+ color: "var(--omnispec-color-primary)"
2130
+ });
2131
+ const scopeDescStyle = css({
2132
+ fontSize: "var(--omnispec-font-size-xs)",
2133
+ color: "var(--omnispec-fg-secondary)"
2134
+ });
2135
+
2136
+ const UNTAGGED_LABEL = "Untagged";
2137
+ function slugify(value) {
2138
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "tag";
2139
+ }
2140
+ function channelTagNames(channel) {
2141
+ const names = /* @__PURE__ */ new Set();
2142
+ for (const tag of channel.tags ?? []) names.add(tag.name);
2143
+ for (const op of channel.operations) {
2144
+ for (const tag of op.tags ?? []) names.add(tag.name);
2145
+ }
2146
+ return Array.from(names);
2147
+ }
2148
+ function hasAnyTags(channels) {
2149
+ return channels.some((ch) => channelTagNames(ch).length > 0);
2150
+ }
2151
+ function groupChannelsByTag(channels, specTags) {
2152
+ const byName = /* @__PURE__ */ new Map();
2153
+ const untagged = [];
2154
+ for (const channel of channels) {
2155
+ const names = channelTagNames(channel);
2156
+ if (names.length === 0) {
2157
+ untagged.push(channel);
2158
+ continue;
2159
+ }
2160
+ for (const name of names) {
2161
+ const list = byName.get(name) ?? [];
2162
+ list.push(channel);
2163
+ byName.set(name, list);
2164
+ }
2165
+ }
2166
+ const declared = (specTags ?? []).map((t) => t.name);
2167
+ const operationOnly = Array.from(byName.keys()).filter((name) => !declared.includes(name)).sort();
2168
+ const orderedNames = [...declared.filter((name) => byName.has(name)), ...operationOnly];
2169
+ const tagMetaByName = new Map((specTags ?? []).map((t) => [t.name, t]));
2170
+ const usedIds = /* @__PURE__ */ new Set();
2171
+ const uniqueId = (base) => {
2172
+ let id = base;
2173
+ let n = 2;
2174
+ while (usedIds.has(id)) id = `${base}-${n++}`;
2175
+ usedIds.add(id);
2176
+ return id;
2177
+ };
2178
+ const groups = orderedNames.map((name) => ({
2179
+ tag: tagMetaByName.get(name) ?? { name },
2180
+ id: uniqueId(slugify(name)),
2181
+ label: tagMetaByName.get(name)?.displayName ?? name,
2182
+ channels: byName.get(name) ?? []
2183
+ }));
2184
+ if (untagged.length > 0) {
2185
+ groups.push({ tag: void 0, id: uniqueId("untagged"), label: UNTAGGED_LABEL, channels: untagged });
2186
+ }
2187
+ return groups;
2188
+ }
2189
+
2190
+ function TagGroupHeader({ group }) {
2191
+ return /* @__PURE__ */ jsxs("div", { className: headerStyle, children: [
2192
+ /* @__PURE__ */ jsxs("h3", { className: titleStyle, children: [
2193
+ group.label,
2194
+ /* @__PURE__ */ jsx("span", { className: countStyle, children: group.channels.length })
2195
+ ] }),
2196
+ group.tag?.description && /* @__PURE__ */ jsx("div", { className: descStyle, children: /* @__PURE__ */ jsx(MarkdownRenderer, { content: group.tag.description }) }),
2197
+ group.tag?.externalDocs && /* @__PURE__ */ jsx("div", { className: docsStyle, children: /* @__PURE__ */ jsx(ExternalDocsLink, { externalDocs: group.tag.externalDocs, context: group.label }) })
2198
+ ] });
2199
+ }
2200
+ const headerStyle = css({
2201
+ marginBottom: "0.75rem",
2202
+ paddingBottom: "0.5rem",
2203
+ borderBottom: "0.125rem solid var(--omnispec-border-color)"
2204
+ });
2205
+ const titleStyle = css({
2206
+ display: "flex",
2207
+ alignItems: "center",
2208
+ gap: "0.625rem",
2209
+ margin: 0,
2210
+ fontSize: "var(--omnispec-h3-font-size)",
2211
+ fontWeight: 800,
2212
+ color: "var(--omnispec-h3-color)"
2213
+ });
2214
+ const countStyle = css({
2215
+ fontSize: "var(--omnispec-font-size-xs)",
2216
+ fontWeight: 500,
2217
+ color: "var(--omnispec-fg-muted)",
2218
+ backgroundColor: "var(--omnispec-bg-tertiary)",
2219
+ padding: "0.125rem 0.5rem",
2220
+ borderRadius: "0.625rem",
2221
+ fontFamily: "var(--omnispec-font-mono)"
2222
+ });
2223
+ const descStyle = css({
2224
+ marginTop: "0.5rem",
2225
+ fontSize: "var(--omnispec-font-size-sm)",
2226
+ color: "var(--omnispec-fg-secondary)",
2227
+ lineHeight: 1.6
2228
+ });
2229
+ const docsStyle = css({
2230
+ marginTop: "0.5rem"
2231
+ });
2232
+
2233
+ function AsyncApiSpec({
2234
+ spec,
2235
+ theme,
2236
+ layout = "sidebar",
2237
+ sidebarPosition = "left",
2238
+ defaultExpandOperations = false,
2239
+ displayMode,
2240
+ downloadLink,
2241
+ sidebarNav,
2242
+ slots = {},
2243
+ schemaStyle,
2244
+ pro,
2245
+ onSpecLoaded,
2246
+ className
2247
+ }) {
2248
+ const resolvedSchemaStyle = resolveSchemaStyle(schemaStyle, pro?.advancedSchemaStyles ?? false);
2249
+ const resolvedDisplayMode = displayMode ?? "compact";
2250
+ const { data: parsedSpec, state } = useAsyncApiSpec(spec);
2251
+ const [searchQuery, setSearchQuery] = useState("");
2252
+ const [allExpanded, setAllExpanded] = useState(defaultExpandOperations);
2253
+ const [expandGeneration, setExpandGeneration] = useState(0);
2254
+ const [navGrouping, setNavGrouping] = useState("channel");
2255
+ const handleToggleExpand = useCallback(() => {
2256
+ setAllExpanded((prev) => !prev);
2257
+ setExpandGeneration((prev) => prev + 1);
2258
+ }, []);
2259
+ useMemo(() => {
2260
+ if (parsedSpec && onSpecLoaded) {
2261
+ const major = parseInt(parsedSpec.specVersion.split(".")[0], 10);
2262
+ onSpecLoaded({
2263
+ title: parsedSpec.title,
2264
+ version: parsedSpec.version,
2265
+ type: major >= 3 ? SpecType.ASYNCAPI_3 : SpecType.ASYNCAPI_2
2266
+ });
2267
+ }
2268
+ }, [parsedSpec, onSpecLoaded]);
2269
+ const filteredChannels = useMemo(() => {
2270
+ if (!parsedSpec || !searchQuery.trim()) return parsedSpec?.channels ?? [];
2271
+ const q = searchQuery.toLowerCase();
2272
+ return parsedSpec.channels.filter(
2273
+ (ch) => ch.address.toLowerCase().includes(q) || ch.description?.toLowerCase().includes(q) || ch.operations.some(
2274
+ (op) => op.operationId?.toLowerCase().includes(q) || op.summary?.toLowerCase().includes(q) || (op.tags ?? []).some((t) => t.name.toLowerCase().includes(q))
2275
+ )
2276
+ );
2277
+ }, [parsedSpec, searchQuery]);
2278
+ const grouped = useMemo(() => hasAnyTags(filteredChannels), [filteredChannels]);
2279
+ const tagGroups = useMemo(
2280
+ () => grouped ? groupChannelsByTag(filteredChannels, parsedSpec?.tags) : [],
2281
+ [grouped, filteredChannels, parsedSpec]
2282
+ );
2283
+ const channelDomId = useMemo(() => {
2284
+ const map = /* @__PURE__ */ new Map();
2285
+ if (grouped) {
2286
+ for (const group of tagGroups) {
2287
+ for (const ch of group.channels) {
2288
+ if (!map.has(ch.name)) map.set(ch.name, `${group.id}-channel-${ch.name}`);
2289
+ }
2290
+ }
2291
+ } else {
2292
+ for (const ch of filteredChannels) map.set(ch.name, `channel-${ch.name}`);
2293
+ }
2294
+ return map;
2295
+ }, [grouped, tagGroups, filteredChannels]);
2296
+ const operationDomId = useCallback(
2297
+ (channelName, idx) => `${channelDomId.get(channelName) ?? `channel-${channelName}`}-op-${idx}`,
2298
+ [channelDomId]
2299
+ );
2300
+ const opToCard = useMemo(() => {
2301
+ const map = /* @__PURE__ */ new Map();
2302
+ for (const ch of filteredChannels) {
2303
+ const card = channelDomId.get(ch.name) ?? `channel-${ch.name}`;
2304
+ ch.operations.forEach((_, idx) => map.set(`${card}-op-${idx}`, card));
2305
+ }
2306
+ return map;
2307
+ }, [filteredChannels, channelDomId]);
2308
+ const hasOperations = useMemo(
2309
+ () => filteredChannels.some((ch) => ch.operations.length > 0),
2310
+ [filteredChannels]
2311
+ );
2312
+ const navItems = useMemo(() => {
2313
+ if (!parsedSpec) return [];
2314
+ const actionLabel = (action) => action.toUpperCase();
2315
+ const actionColor = (action) => action === "subscribe" || action === "receive" ? "var(--omnispec-color-subscribe)" : "var(--omnispec-color-publish)";
2316
+ const channelNavItem = (ch, idPrefix) => {
2317
+ const uniqueActions = [...new Set(ch.operations.map((op) => actionLabel(op.action)))];
2318
+ return {
2319
+ id: `${idPrefix}channel-${ch.name}`,
2320
+ label: ch.address,
2321
+ badge: uniqueActions.join("/") || void 0,
2322
+ badgeColor: actionColor(ch.operations[0]?.action ?? "")
2323
+ };
2324
+ };
2325
+ const operationNavItems = () => filteredChannels.flatMap(
2326
+ (ch) => ch.operations.map((op, idx) => ({
2327
+ id: operationDomId(ch.name, idx),
2328
+ label: op.operationId ?? op.summary ?? `${actionLabel(op.action)} ${ch.address}`,
2329
+ badge: actionLabel(op.action),
2330
+ badgeColor: actionColor(op.action)
2331
+ }))
2332
+ );
2333
+ const tagGroupNavItem = (group) => ({
2334
+ id: `taggroup-${group.id}`,
2335
+ label: group.label,
2336
+ badge: String(group.channels.length),
2337
+ children: group.channels.map((ch) => channelNavItem(ch, `${group.id}-`))
2338
+ });
2339
+ const channelChildren = navGrouping === "operation" ? operationNavItems() : grouped ? nestByTagGroups(tagGroups, parsedSpec.tagGroups, tagGroupNavItem) : filteredChannels.map((ch) => channelNavItem(ch, ""));
2340
+ const items = [];
2341
+ if (parsedSpec.servers.length > 0) {
2342
+ items.push({ id: "servers", label: "Servers" });
2343
+ }
2344
+ const searchedToEmpty = channelChildren.length === 0 && searchQuery.trim().length > 0;
2345
+ const channelsChildren = searchedToEmpty ? [{ id: "channels-no-results", label: "No results", className: noResultsNavStyle }] : channelChildren;
2346
+ if (channelsChildren.length > 0) {
2347
+ items.push({
2348
+ id: "channels",
2349
+ label: navGrouping === "operation" ? "Operations" : "Channels",
2350
+ children: channelsChildren
2351
+ });
2352
+ }
2353
+ if (Object.keys(parsedSpec.components.messages ?? {}).length > 0) {
2354
+ items.push({
2355
+ id: "messages",
2356
+ label: "Messages",
2357
+ children: Object.keys(parsedSpec.components.messages).map((name) => ({
2358
+ id: `message-${name}`,
2359
+ label: name
2360
+ }))
2361
+ });
2362
+ }
2363
+ if (Object.keys(parsedSpec.components.schemas).length > 0) {
2364
+ items.push({
2365
+ id: "schemas",
2366
+ label: "Schemas",
2367
+ children: Object.keys(parsedSpec.components.schemas).map((name) => ({
2368
+ id: `schema-${name}`,
2369
+ label: name
2370
+ }))
2371
+ });
2372
+ }
2373
+ if (Object.keys(parsedSpec.components.securitySchemes).length > 0) {
2374
+ items.push({ id: "security", label: "Security Schemes" });
2375
+ }
2376
+ return items;
2377
+ }, [parsedSpec, grouped, tagGroups, filteredChannels, navGrouping, operationDomId, searchQuery]);
2378
+ const { navigateTo } = useHashScroll(filteredChannels.length);
2379
+ const handleNavSelect = useCallback((id) => {
2380
+ const cardId = opToCard.get(id);
2381
+ if (cardId) {
2382
+ requestExpand(cardId);
2383
+ navigateTo(id);
2384
+ return;
2385
+ }
2386
+ navigateTo(id);
2387
+ }, [navigateTo, opToCard]);
2388
+ const navSectionIds = useMemo(() => flattenNavItemIds(navItems), [navItems]);
2389
+ const activeSection = useScrollSpy(navSectionIds);
2390
+ if (state.status === "loading") {
2391
+ return /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx("div", { className: `omnispec-asyncapi ${className ?? ""}`, children: /* @__PURE__ */ jsx(LoadingScreen, {}) }) });
2392
+ }
2393
+ if (state.status === "error") {
2394
+ return /* @__PURE__ */ jsx(
2395
+ SpecStatusScreen,
2396
+ {
2397
+ theme,
2398
+ layout,
2399
+ sidebarPosition,
2400
+ slots,
2401
+ sidebarNav,
2402
+ premiumThemingEnabled: pro?.premiumThemingEnabled ?? false,
2403
+ className: `omnispec-asyncapi ${className ?? ""}`,
2404
+ children: /* @__PURE__ */ jsx(ErrorMessage, { title: "Failed to load specification", message: state.error })
2405
+ }
2406
+ );
2407
+ }
2408
+ if (!parsedSpec) return null;
2409
+ const specNav = /* @__PURE__ */ jsxs(Fragment$1, { children: [
2410
+ /* @__PURE__ */ jsx(
2411
+ SearchBar,
2412
+ {
2413
+ placeholder: "Filter channels...",
2414
+ onSearch: setSearchQuery
2415
+ }
2416
+ ),
2417
+ hasOperations && /* @__PURE__ */ jsxs("div", { className: groupToggleStyle, role: "group", "aria-label": "Sidebar grouping", children: [
2418
+ /* @__PURE__ */ jsx("span", { className: groupToggleLabelStyle, children: "Group by" }),
2419
+ /* @__PURE__ */ jsxs("div", { className: groupToggleButtonsStyle, children: [
2420
+ /* @__PURE__ */ jsx(
2421
+ "button",
2422
+ {
2423
+ type: "button",
2424
+ className: cx(groupToggleButtonStyle, navGrouping === "channel" && groupToggleActiveStyle),
2425
+ "aria-pressed": navGrouping === "channel",
2426
+ "aria-label": "Group by channel",
2427
+ onClick: () => setNavGrouping("channel"),
2428
+ children: "Channel"
2429
+ }
2430
+ ),
2431
+ /* @__PURE__ */ jsx(
2432
+ "button",
2433
+ {
2434
+ type: "button",
2435
+ className: cx(groupToggleButtonStyle, navGrouping === "operation" && groupToggleActiveStyle),
2436
+ "aria-pressed": navGrouping === "operation",
2437
+ "aria-label": "Group by operation",
2438
+ onClick: () => setNavGrouping("operation"),
2439
+ children: "Operation"
2440
+ }
2441
+ )
2442
+ ] })
2443
+ ] }),
2444
+ /* @__PURE__ */ jsx(
2445
+ NavTree,
2446
+ {
2447
+ items: navItems,
2448
+ activeId: activeSection,
2449
+ onSelect: handleNavSelect
2450
+ }
2451
+ )
2452
+ ] });
2453
+ const sidebar = buildSidebar(sidebarNav, specNav);
2454
+ const resolvedDownloadLink = resolveDownloadLink(downloadLink, spec);
2455
+ return /* @__PURE__ */ jsx(ConfigProvider, { config: { allowTryIt: false, layout, sidebarPosition, defaultExpandOperations, displayMode: resolvedDisplayMode, schemaStyle: resolvedSchemaStyle, slots, proRenderers: pro?.renderers ?? /* @__PURE__ */ new Map(), premiumThemingEnabled: pro?.premiumThemingEnabled ?? false }, children: /* @__PURE__ */ jsx(ExpandProvider, { expandAll: allExpanded, expandGeneration, children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx("div", { className: `omnispec-asyncapi ${className ?? ""}`, children: /* @__PURE__ */ jsx(ErrorBoundary, { title: "Failed to render this API reference", children: /* @__PURE__ */ jsxs(
2456
+ DocLayout,
2457
+ {
2458
+ layout,
2459
+ sidebarPosition,
2460
+ sidebar,
2461
+ sidebarHeader: slots.sidebarHeader,
2462
+ sidebarFooter: slots.sidebarFooter,
2463
+ header: slots.header,
2464
+ footer: slots.footer,
2465
+ children: [
2466
+ /* @__PURE__ */ jsx(
2467
+ SpecToolbar,
2468
+ {
2469
+ overview: /* @__PURE__ */ jsx(AsyncOverview, { spec: parsedSpec }),
2470
+ expandLabel: "channels",
2471
+ allExpanded,
2472
+ onToggleExpand: handleToggleExpand,
2473
+ downloadLink: resolvedDownloadLink
2474
+ }
2475
+ ),
2476
+ /* @__PURE__ */ jsx("div", { id: "servers", children: /* @__PURE__ */ jsx(ServerList, { servers: parsedSpec.servers }) }),
2477
+ /* @__PURE__ */ jsxs("div", { id: "channels", children: [
2478
+ /* @__PURE__ */ jsx("h2", { className: css({ margin: "0 0 1rem", fontSize: "var(--omnispec-h2-font-size)", fontWeight: "var(--omnispec-h2-font-weight)", color: "var(--omnispec-h2-color)" }), children: "Channels" }),
2479
+ filteredChannels.length === 0 ? /* @__PURE__ */ jsx("p", { className: emptyStateStyle, children: parsedSpec.channels.length === 0 ? "No channels are defined for this API." : "No channels match your filter." }) : grouped ? tagGroups.map((group) => /* @__PURE__ */ jsxs("section", { id: `taggroup-${group.id}`, className: tagSectionStyle, children: [
2480
+ /* @__PURE__ */ jsx(TagGroupHeader, { group }),
2481
+ group.channels.map((channel) => /* @__PURE__ */ jsx(
2482
+ ChannelCard,
2483
+ {
2484
+ id: `${group.id}-channel-${channel.name}`,
2485
+ channel,
2486
+ displayMode: resolvedDisplayMode,
2487
+ expandAll: allExpanded,
2488
+ expandGeneration,
2489
+ onTagClick: setSearchQuery
2490
+ },
2491
+ `${group.id}-${channel.name}`
2492
+ ))
2493
+ ] }, group.id)) : filteredChannels.map((channel) => /* @__PURE__ */ jsx(
2494
+ ChannelCard,
2495
+ {
2496
+ id: `channel-${channel.name}`,
2497
+ channel,
2498
+ displayMode: resolvedDisplayMode,
2499
+ expandAll: allExpanded,
2500
+ expandGeneration,
2501
+ onTagClick: setSearchQuery
2502
+ },
2503
+ channel.name
2504
+ ))
2505
+ ] }),
2506
+ /* @__PURE__ */ jsx(ComponentsSection, { components: parsedSpec.components }),
2507
+ /* @__PURE__ */ jsx(SecuritySchemesSection, { securitySchemes: parsedSpec.components.securitySchemes })
2508
+ ]
2509
+ }
2510
+ ) }) }) }) }) });
2511
+ }
2512
+ function ChannelCard({
2513
+ channel,
2514
+ id,
2515
+ displayMode,
2516
+ expandAll,
2517
+ expandGeneration,
2518
+ onTagClick
2519
+ }) {
2520
+ const Renderer = displayMode === "reference" ? ChannelReferenceDetail : ChannelDetail;
2521
+ return /* @__PURE__ */ jsx(
2522
+ Renderer,
2523
+ {
2524
+ id,
2525
+ channel,
2526
+ expandAll,
2527
+ expandGeneration,
2528
+ onTagClick
2529
+ }
2530
+ );
2531
+ }
2532
+ function nestByTagGroups(groups, xTagGroups, toNav) {
2533
+ if (!xTagGroups?.length) return groups.map(toNav);
2534
+ const byTagName = /* @__PURE__ */ new Map();
2535
+ for (const g of groups) if (g.tag?.name) byTagName.set(g.tag.name, g);
2536
+ const used = /* @__PURE__ */ new Set();
2537
+ const grouped = xTagGroups.map((xg) => {
2538
+ const children = xg.tags.map((t) => byTagName.get(t)).filter((g) => !!g);
2539
+ children.forEach((g) => used.add(g));
2540
+ return {
2541
+ id: `xtaggroup-${xg.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "group"}`,
2542
+ label: xg.name,
2543
+ children: children.map(toNav)
2544
+ };
2545
+ }).filter((item) => (item.children?.length ?? 0) > 0);
2546
+ const leftover = groups.filter((g) => !used.has(g)).map(toNav);
2547
+ return [...grouped, ...leftover];
2548
+ }
2549
+ const emptyStateStyle = css({
2550
+ fontSize: "var(--omnispec-font-size-sm)",
2551
+ color: "var(--omnispec-fg-muted)",
2552
+ fontStyle: "italic"
2553
+ });
2554
+ const noResultsNavStyle = css({
2555
+ fontStyle: "italic",
2556
+ color: "var(--omnispec-fg-muted)",
2557
+ cursor: "default"
2558
+ });
2559
+ const groupToggleStyle = css({
2560
+ display: "flex",
2561
+ alignItems: "center",
2562
+ gap: "0.5rem",
2563
+ padding: "0.5rem 0.75rem 0.25rem",
2564
+ flexWrap: "wrap"
2565
+ });
2566
+ const groupToggleLabelStyle = css({
2567
+ fontSize: "var(--omnispec-font-size-xxs)",
2568
+ fontWeight: 600,
2569
+ textTransform: "uppercase",
2570
+ letterSpacing: "0.05em",
2571
+ color: "var(--omnispec-fg-muted)"
2572
+ });
2573
+ const groupToggleButtonsStyle = css({
2574
+ display: "inline-flex",
2575
+ borderRadius: "var(--omnispec-border-radius)",
2576
+ backgroundColor: "var(--omnispec-bg-tertiary)",
2577
+ padding: "0.125rem"
2578
+ });
2579
+ const groupToggleButtonStyle = css({
2580
+ border: "none",
2581
+ background: "transparent",
2582
+ color: "var(--omnispec-fg-secondary)",
2583
+ fontSize: "var(--omnispec-font-size-xs)",
2584
+ padding: "0.125rem 0.625rem",
2585
+ borderRadius: "calc(var(--omnispec-border-radius) - 1px)",
2586
+ cursor: "pointer"
2587
+ });
2588
+ const groupToggleActiveStyle = css({
2589
+ backgroundColor: "var(--omnispec-bg-primary)",
2590
+ color: "var(--omnispec-fg-primary)",
2591
+ fontWeight: 600,
2592
+ boxShadow: "var(--omnispec-shadow-sm, 0 1px 0.125rem rgba(0,0,0,0.1))"
2593
+ });
2594
+ const tagSectionStyle = css({
2595
+ marginBottom: "2rem"
2596
+ });
2597
+
2598
+ export { AsyncApiSpec };
2599
+ //# sourceMappingURL=AsyncApiSpec-BzhfaQ_T.js.map