@redocly/cli 2.62.2 → 2.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/THIRD_PARTY_NOTICES +1 -1
  2. package/lib/chunks/{37WWN4MA.js → 2DKR4Z25.js} +1 -1
  3. package/lib/chunks/{S6NFOZ34.js → 2MCPXKB6.js} +1 -1
  4. package/lib/chunks/2ZIICV4T.js +7 -0
  5. package/lib/chunks/3CSDNX6S.js +20 -0
  6. package/lib/chunks/{KOR5TUJG.js → 4EAF6XUQ.js} +1 -1
  7. package/lib/chunks/5PR7FNUB.js +59 -0
  8. package/lib/chunks/{5X35UU2C.js → 654FMWX6.js} +1 -1
  9. package/lib/chunks/{4AM55DEH.js → 6FADWAOY.js} +1 -1
  10. package/lib/chunks/{3FXYWWTJ.js → 6MP4DHWK.js} +1 -1
  11. package/lib/chunks/{SLQPKXO2.js → 7APJVQSB.js} +1 -1
  12. package/lib/chunks/{KRCCY64H.js → AC62H63B.js} +1 -1
  13. package/lib/chunks/{ZCVUIIPU.js → ALBI5SPY.js} +1 -1
  14. package/lib/chunks/{SXBAAS4M.js → B5ZOH4BB.js} +1 -1
  15. package/lib/chunks/{V2YF33JL.js → BGGUKU7E.js} +1 -1
  16. package/lib/chunks/{6EGJEFXO.js → BWXAXULF.js} +1 -1
  17. package/lib/chunks/{3JYQOGV3.js → CEASD5U3.js} +1 -1
  18. package/lib/chunks/{TBZEEKTV.js → CVPT656W.js} +1 -1
  19. package/lib/chunks/{5PG3ST2N.js → DL4VP2Z4.js} +2 -2
  20. package/lib/chunks/DPNI74SB.js +69 -0
  21. package/lib/chunks/{GWXT3QO6.js → ENIPOAVJ.js} +2 -2
  22. package/lib/chunks/{22EANOP2.js → EQTXHL74.js} +101 -101
  23. package/lib/chunks/{3WHXM4DJ.js → FU7GBMUU.js} +1 -1
  24. package/lib/chunks/{JLVGRO3I.js → FVGFKJ67.js} +7 -7
  25. package/lib/chunks/{73RBZL53.js → FXKIC5R3.js} +1 -1
  26. package/lib/chunks/{2OBVZIAW.js → GKCVQWOQ.js} +3 -3
  27. package/lib/chunks/{MNH2K4WM.js → GKSUZULD.js} +1 -1
  28. package/lib/chunks/GOTKYHFM.js +20 -0
  29. package/lib/chunks/{2XK7ML3U.js → GRTUPOKN.js} +1 -1
  30. package/lib/chunks/{XJE2OFDN.js → HAOBCQWB.js} +358 -19
  31. package/lib/chunks/{IUSSBOYO.js → HIII45WJ.js} +1 -1
  32. package/lib/chunks/{2OVI7BIW.js → HYMULX2S.js} +1 -1
  33. package/lib/chunks/{FDMXHRDK.js → I6NMWBVI.js} +1 -1
  34. package/lib/chunks/{SHZZKTDE.js → IH3N62Q4.js} +1 -1
  35. package/lib/chunks/{V3ILUN2S.js → J665DSDI.js} +1 -1
  36. package/lib/chunks/JQJ5TDVP.js +11 -0
  37. package/lib/chunks/{HWTYAU4Y.js → L5X7LBV6.js} +1 -1
  38. package/lib/chunks/{VXONEXYX.js → LCAJ35J6.js} +1 -1
  39. package/lib/chunks/{US7X4XPD.js → LG3SUXEW.js} +1 -1
  40. package/lib/chunks/{YDVWNFMS.js → LMO5V2XF.js} +1 -1
  41. package/lib/chunks/{XFBJHVYU.js → M4NCSK7Q.js} +1 -1
  42. package/lib/chunks/{RPHIT72T.js → M74SGAZK.js} +1 -1
  43. package/lib/chunks/{M3XPS7UF.js → MVCGBDOY.js} +1 -1
  44. package/lib/chunks/{HYE4U6V5.js → N4R4236N.js} +1 -1
  45. package/lib/chunks/{6NB3FKVN.js → NRWIPPEV.js} +1 -1
  46. package/lib/chunks/{3C6UUCEW.js → OGNRVBTI.js} +1 -1
  47. package/lib/chunks/{6MH5ZWLD.js → ONBORCDJ.js} +1 -1
  48. package/lib/chunks/{ENSYM7KY.js → OS52EARM.js} +1 -1
  49. package/lib/chunks/{6DO6IN4A.js → QCOPS234.js} +1 -1
  50. package/lib/chunks/{CQKQB4PJ.js → QWTSCCNH.js} +1 -1
  51. package/lib/chunks/{4OEXH5EV.js → RRQJCLNO.js} +1 -1
  52. package/lib/chunks/{HBENVUR4.js → RWDQI2KD.js} +1 -1
  53. package/lib/chunks/{I5CGSLGR.js → S3W5GQGC.js} +1 -1
  54. package/lib/chunks/{HUWKDZPP.js → SRRHJLPL.js} +1 -1
  55. package/lib/chunks/{7WM6VLB3.js → TTE4EAVV.js} +3 -2
  56. package/lib/chunks/{LRLGVYCG.js → TWFZE4OF.js} +1 -1
  57. package/lib/chunks/{OP7NIAI7.js → U4RAHOFK.js} +1 -1
  58. package/lib/chunks/{36IHQANV.js → UC5EDLXL.js} +1 -1
  59. package/lib/chunks/{TKLMYBPI.js → ULQK2S4O.js} +1 -1
  60. package/lib/chunks/{FDGP3ZYZ.js → UNOXQ62I.js} +363 -156
  61. package/lib/chunks/{6WZUCZGV.js → UQW6CW3M.js} +1 -1
  62. package/lib/chunks/{DS4SCWID.js → VKTRI5YG.js} +1 -1
  63. package/lib/chunks/{PTNNX4IU.js → VMIHLA3H.js} +1 -1
  64. package/lib/chunks/{WX24BERR.js → VWF52WKH.js} +1 -1
  65. package/lib/chunks/WKQJPOYW.js +7 -0
  66. package/lib/chunks/{SYWAPWW7.js → WQBSNQXL.js} +1 -1
  67. package/lib/chunks/{CIDSJFJO.js → X6TQQHRM.js} +1 -1
  68. package/lib/chunks/{XJTGJYVS.js → XDBFHG7X.js} +1 -1
  69. package/lib/chunks/{LVGVWPDB.js → XYU2LTWU.js} +1 -1
  70. package/lib/chunks/{2OQM5ARW.js → Z4X6WES7.js} +1 -1
  71. package/lib/chunks/{3JYY42DL.js → ZFXOCOU6.js} +1 -1
  72. package/lib/chunks/{3DEJQSYG.js → ZM3M44Q3.js} +1 -1
  73. package/lib/eject-assets/generators/cli/docs.ts +1 -1
  74. package/lib/eject-assets/generators/cli/engine-source.ts +1 -1
  75. package/lib/eject-assets/generators/cli/index.ts +2 -2
  76. package/lib/eject-assets/generators/cli/render.ts +1 -1
  77. package/lib/eject-assets/generators/go/client.ts +1 -1
  78. package/lib/eject-assets/generators/go/descriptor.ts +2 -1
  79. package/lib/eject-assets/generators/go/index.ts +2 -2
  80. package/lib/eject-assets/generators/go/models.ts +1 -1
  81. package/lib/eject-assets/generators/go/naming.ts +1 -1
  82. package/lib/eject-assets/generators/go/operations.ts +1 -1
  83. package/lib/eject-assets/generators/go/pagination.ts +1 -1
  84. package/lib/eject-assets/generators/go/types.ts +1 -1
  85. package/lib/eject-assets/generators/mock/faker.ts +1 -1
  86. package/lib/eject-assets/generators/mock/index.ts +2 -2
  87. package/lib/eject-assets/generators/mock/render.ts +1 -1
  88. package/lib/eject-assets/generators/mock/sample.ts +1 -1
  89. package/lib/eject-assets/generators/mock/values.ts +1 -1
  90. package/lib/eject-assets/generators/php/client.ts +1 -1
  91. package/lib/eject-assets/generators/php/descriptor.ts +2 -1
  92. package/lib/eject-assets/generators/php/index.ts +2 -2
  93. package/lib/eject-assets/generators/php/models.ts +1 -1
  94. package/lib/eject-assets/generators/php/naming.ts +1 -1
  95. package/lib/eject-assets/generators/php/operations.ts +1 -1
  96. package/lib/eject-assets/generators/php/pagination.ts +1 -1
  97. package/lib/eject-assets/generators/php/types.ts +1 -1
  98. package/lib/eject-assets/generators/python/client.ts +1 -1
  99. package/lib/eject-assets/generators/python/descriptor.ts +2 -1
  100. package/lib/eject-assets/generators/python/index.ts +2 -2
  101. package/lib/eject-assets/generators/python/models.ts +1 -1
  102. package/lib/eject-assets/generators/python/naming.ts +1 -1
  103. package/lib/eject-assets/generators/python/operations.ts +1 -1
  104. package/lib/eject-assets/generators/python/pagination.ts +1 -1
  105. package/lib/eject-assets/generators/python/types.ts +1 -1
  106. package/lib/eject-assets/generators/swr/index.ts +2 -2
  107. package/lib/eject-assets/generators/swr/render.ts +1 -1
  108. package/lib/eject-assets/generators/tanstack-query/index.ts +2 -2
  109. package/lib/eject-assets/generators/tanstack-query/render.ts +56 -9
  110. package/lib/eject-assets/generators/transformers/index.ts +2 -2
  111. package/lib/eject-assets/generators/transformers/render.ts +1 -1
  112. package/lib/eject-assets/generators/typescript/banner.ts +1 -1
  113. package/lib/eject-assets/generators/typescript/client.ts +1 -1
  114. package/lib/eject-assets/generators/typescript/descriptor.ts +1 -1
  115. package/lib/eject-assets/generators/typescript/index.ts +29 -3
  116. package/lib/eject-assets/generators/typescript/inline-runtime.ts +1 -1
  117. package/lib/eject-assets/generators/typescript/operation-signature.ts +1 -1
  118. package/lib/eject-assets/generators/typescript/operation-types.ts +1 -1
  119. package/lib/eject-assets/generators/typescript/operations.ts +1 -1
  120. package/lib/eject-assets/generators/typescript/response-headers.ts +1 -1
  121. package/lib/eject-assets/generators/typescript/type-guards.ts +1 -1
  122. package/lib/eject-assets/generators/typescript/types.ts +1 -1
  123. package/lib/eject-assets/generators/zod/index.ts +2 -2
  124. package/lib/eject-assets/generators/zod/schemas.ts +1 -1
  125. package/lib/eject-assets/skills/tanstack-query-generator/SKILL.md +5 -2
  126. package/lib/eject-assets/skills/typescript-generator/SKILL.md +24 -0
  127. package/lib/index.js +5 -5
  128. package/package.json +1 -1
  129. package/lib/chunks/5SIJI5LC.js +0 -42
  130. package/lib/chunks/7WTV5KH3.js +0 -67
  131. package/lib/chunks/EDQ6QRIB.js +0 -20
  132. package/lib/chunks/LCFG5N4V.js +0 -7
  133. package/lib/chunks/PWGFZ5ZK.js +0 -7
  134. package/lib/chunks/RU7T4CKG.js +0 -11
  135. package/lib/chunks/Z6GHMX6Z.js +0 -20
@@ -487,6 +487,7 @@ type PaginationSpec struct {
487
487
  Param string
488
488
  NextCursor string
489
489
  HasMore string
490
+ NextLink string
490
491
  LimitParam string
491
492
  Items string
492
493
  }
@@ -577,7 +578,7 @@ func iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield f
577
578
  }
578
579
  cursor = next
579
580
  }
580
- case "link":
581
+ case "link", "body-link":
581
582
  params := cloneValues(base)
582
583
  previous := ""
583
584
  for {
@@ -589,7 +590,18 @@ func iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield f
589
590
  if !yield(page, nil) {
590
591
  return
591
592
  }
592
- target := linkNext(resp.Header.Get("Link"))
593
+ var target string
594
+ if spec.Style == "link" {
595
+ target = linkNext(resp.Header.Get("Link"))
596
+ } else {
597
+ value := resolvePointer(page, spec.NextLink)
598
+ link, isString := value.(string)
599
+ if value != nil && !isString {
600
+ yield(nil, fmt.Errorf("pagination link at %s is not a string", spec.NextLink))
601
+ return
602
+ }
603
+ target = link
604
+ }
593
605
  if target == "" {
594
606
  return
595
607
  }
@@ -614,9 +626,7 @@ func iterPages(call pageCall, spec PaginationSpec, base url.Values) func(yield f
614
626
  previous = next
615
627
  params = cloneValues(base)
616
628
  for key, values := range targetURL.Query() {
617
- for _, value := range values {
618
- params.Add(key, value)
619
- }
629
+ params[key] = values
620
630
  }
621
631
  }
622
632
  default: // offset / page
@@ -1262,8 +1272,8 @@ function linkNext(?string $header): ?string
1262
1272
 
1263
1273
  /**
1264
1274
  * Auto-pagination: \`$call(array $params): [mixed rawPage, array $response]\`, \`$spec\` is the
1265
- * normalized rule (\`style\`, \`param\`, \`nextCursor\`, \`hasMore\`, \`items\`), \`$base\` the caller's
1266
- * query params. Yields raw decoded pages; generated wrappers hydrate them into models.
1275
+ * normalized rule (\`style\`, \`param\`, \`nextCursor\`, \`hasMore\`, \`nextLink\`, \`items\`), \`$base\`
1276
+ * the caller's query params. Yields raw decoded pages; generated wrappers hydrate them into models.
1267
1277
  */
1268
1278
  function iterPages(callable $call, array $spec, array $base): \\Generator
1269
1279
  {
@@ -1286,9 +1296,11 @@ function iterPages(callable $call, array $spec, array $base): \\Generator
1286
1296
  }
1287
1297
  $seenCursors[$next] = true;
1288
1298
  $params[$spec['param']] = $next;
1289
- } elseif ($style === 'link') {
1290
- $target = linkNext($response['headers']['link'] ?? null);
1291
- if ($target === null || isset($seenLinks[$target])) {
1299
+ } elseif ($style === 'link' || $style === 'body-link') {
1300
+ $target = $style === 'body-link'
1301
+ ? resolvePointer($raw, $spec['nextLink'])
1302
+ : linkNext($response['headers']['link'] ?? null);
1303
+ if (!is_string($target) || $target === '' || isset($seenLinks[$target])) {
1292
1304
  return;
1293
1305
  }
1294
1306
  $seenLinks[$target] = true;
@@ -1959,8 +1971,9 @@ async def send_async(
1959
1971
  `,"_paginate.py":`# Auto-pagination iterators for generated Python clients \u2014 the TypeScript
1960
1972
  # runtime's paginate.ts semantics ported: cursor (next-cursor pointer, optional
1961
1973
  # has-more flag, repeated-cursor guard), offset/page (advance by count/one,
1962
- # repeated-page guard, null start treated as absent), and link (RFC 8288
1963
- # \`Link: rel="next"\` following with relative resolution and a loop guard).
1974
+ # repeated-page guard, null start treated as absent), link (RFC 8288
1975
+ # \`Link: rel="next"\` following) and body-link (the next-link pointer's URL), both
1976
+ # with relative resolution and a loop guard.
1964
1977
  from __future__ import annotations
1965
1978
 
1966
1979
  import re
@@ -2015,8 +2028,8 @@ def iter_pages(call: PageCall, spec: Dict[str, Any], params: Optional[Dict[str,
2015
2028
  if nxt == cursor:
2016
2029
  raise ValueError("Pagination did not advance: the operation returned the same cursor twice")
2017
2030
  cursor = nxt
2018
- elif style == "link":
2019
- yield from _iter_pages_by_link(call, base)
2031
+ elif style in ("link", "body-link"):
2032
+ yield from _iter_pages_by_link(call, spec, base)
2020
2033
  else: # offset / page
2021
2034
  start = base.get(spec["param"])
2022
2035
  fallback = 1 if style == "page" else 0
@@ -2051,13 +2064,27 @@ def _link_next(header: Optional[str]) -> Optional[str]:
2051
2064
  return None
2052
2065
 
2053
2066
 
2054
- def _iter_pages_by_link(call: PageCall, base: Dict[str, Any]) -> Iterator[Any]:
2067
+ def _next_link(spec: Dict[str, Any], page: Any, response: Any) -> Optional[str]:
2068
+ """The next page's URL: the \`Link\` header's rel="next" target for \`link\`, the value at
2069
+ the \`next_link\` pointer for \`body-link\`; None when absent, null, or empty."""
2070
+ if spec["style"] == "link":
2071
+ return _link_next(response.headers.get("link"))
2072
+ pointer = spec["next_link"]
2073
+ target = resolve_pointer(page, pointer)
2074
+ if target is None or target == "":
2075
+ return None
2076
+ if not isinstance(target, str):
2077
+ raise ValueError(f"Pagination link at {pointer} is not a string")
2078
+ return target
2079
+
2080
+
2081
+ def _iter_pages_by_link(call: PageCall, spec: Dict[str, Any], base: Dict[str, Any]) -> Iterator[Any]:
2055
2082
  params = dict(base)
2056
2083
  previous = None
2057
2084
  while True:
2058
2085
  page, response = call(params)
2059
2086
  yield page
2060
- target = _link_next(response.headers.get("link"))
2087
+ target = _next_link(spec, page, response)
2061
2088
  if target is None:
2062
2089
  return
2063
2090
  page_url = str(response.request.url) if response.request is not None else ""
@@ -2111,13 +2138,13 @@ async def aiter_pages(
2111
2138
  if nxt == cursor:
2112
2139
  raise ValueError("Pagination did not advance: the operation returned the same cursor twice")
2113
2140
  cursor = nxt
2114
- elif style == "link":
2141
+ elif style in ("link", "body-link"):
2115
2142
  previous = None
2116
2143
  link_params: Dict[str, Any] = dict(base)
2117
2144
  while True:
2118
2145
  page, response = await call(link_params)
2119
2146
  yield page
2120
- target = _link_next(response.headers.get("link"))
2147
+ target = _next_link(spec, page, response)
2121
2148
  if target is None:
2122
2149
  return
2123
2150
  page_url = str(response.request.url) if response.request is not None else ""
@@ -2365,4 +2392,316 @@ def multipart_arguments(body: Any) -> Dict[str, Any]:
2365
2392
  return {"content": body}
2366
2393
  data, files = to_multipart(body)
2367
2394
  return {"data": data, "files": files}
2368
- `};export{e as a,t as b,n as c};
2395
+ `};var r=`import type { Middleware, SettledCall } from '../../../runtime-contract.js';
2396
+
2397
+ const GENERATOR_VERSION: string = 'dev';
2398
+ const DEFAULT_ENDPOINT = 'https://otel.cloud.redocly.com/v1/traces';
2399
+ const EVENT_TYPE = 'com.redocly.sdkUsage.aggregated';
2400
+ const SEND_TIMEOUT_MS = 3000;
2401
+ const SERVICE_NAME = 'redocly-sdk';
2402
+
2403
+ type StatusClass = '2xx' | '3xx' | '4xx' | '5xx' | 'network_error' | 'timeout' | 'aborted';
2404
+ type LatencyBucket = 'lt_100ms' | 'lt_300ms' | 'lt_1s' | 'lt_3s' | 'lt_10s' | 'gte_10s';
2405
+
2406
+ const STATUS_CLASSES: StatusClass[] = [
2407
+ '2xx',
2408
+ '3xx',
2409
+ '4xx',
2410
+ '5xx',
2411
+ 'network_error',
2412
+ 'timeout',
2413
+ 'aborted',
2414
+ ];
2415
+ const LATENCY_BUCKETS: Array<{ bucket: LatencyBucket; belowMs: number }> = [
2416
+ { bucket: 'lt_100ms', belowMs: 100 },
2417
+ { bucket: 'lt_300ms', belowMs: 300 },
2418
+ { bucket: 'lt_1s', belowMs: 1000 },
2419
+ { bucket: 'lt_3s', belowMs: 3000 },
2420
+ { bucket: 'lt_10s', belowMs: 10000 },
2421
+ { bucket: 'gte_10s', belowMs: Infinity },
2422
+ ];
2423
+
2424
+ export type SdkUsageEvent = {
2425
+ id: string;
2426
+ type: typeof EVENT_TYPE;
2427
+ source: string;
2428
+ time: string;
2429
+ data: {
2430
+ usage: Record<string, string | number>;
2431
+ sdk: Record<string, string>;
2432
+ };
2433
+ };
2434
+
2435
+ export type TelemetryOptions = {
2436
+ sdkName: string;
2437
+ sdkVersion: string;
2438
+ client: string;
2439
+ sink?: (events: SdkUsageEvent[]) => void | Promise<void>;
2440
+ endpoint?: string;
2441
+ flushIntervalMs?: number;
2442
+ };
2443
+
2444
+ type OperationCounts = {
2445
+ calls: number;
2446
+ attempts: number;
2447
+ durationSumMs: number;
2448
+ status: Record<StatusClass, number>;
2449
+ latency: Record<LatencyBucket, number>;
2450
+ };
2451
+
2452
+ type ProcessLike = {
2453
+ env?: Record<string, string | undefined>;
2454
+ versions?: { node?: string; bun?: string; deno?: string };
2455
+ on?: (event: 'beforeExit', listener: () => void) => void;
2456
+ };
2457
+
2458
+ const activeWindows = new Set<() => Promise<void>>();
2459
+ const pendingSends = new Set<Promise<void>>();
2460
+ let exitHookInstalled = false;
2461
+
2462
+ function nodeProcess(): ProcessLike | undefined {
2463
+ return (globalThis as { process?: ProcessLike }).process;
2464
+ }
2465
+
2466
+ function telemetryDisabled(): boolean {
2467
+ const runtimeProcess = nodeProcess();
2468
+ if (runtimeProcess === undefined) return true;
2469
+ // A browser bundle can add a \`process\` shim, so also check for \`document\`.
2470
+ if (typeof document !== 'undefined') return true;
2471
+ const env = runtimeProcess.env ?? {};
2472
+ if (env.REDOCLY_SDK_TELEMETRY === 'off') return true;
2473
+ if (env.DO_NOT_TRACK === '1') return true;
2474
+ return false;
2475
+ }
2476
+
2477
+ export async function flush(): Promise<void> {
2478
+ for (const flushWindow of activeWindows) void flushWindow();
2479
+ await Promise.all(pendingSends);
2480
+ }
2481
+
2482
+ export function telemetry(options: TelemetryOptions): Middleware {
2483
+ if (telemetryDisabled()) return {};
2484
+ const intervalMs = options.flushIntervalMs ?? 60_000;
2485
+ const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;
2486
+ const sink = options.sink ?? ((events: SdkUsageEvent[]) => sendOtlp(endpoint, events));
2487
+ const versions = nodeProcess()?.versions ?? {};
2488
+ let runtime = 'node';
2489
+ let runtimeVersion = versions.node ?? '';
2490
+ if (versions.bun !== undefined) {
2491
+ runtime = 'bun';
2492
+ runtimeVersion = versions.bun;
2493
+ } else if (versions.deno !== undefined) {
2494
+ runtime = 'deno';
2495
+ runtimeVersion = versions.deno;
2496
+ }
2497
+ const sdk: Record<string, string> = {
2498
+ name: options.sdkName,
2499
+ version: options.sdkVersion,
2500
+ generator_version: GENERATOR_VERSION,
2501
+ language: 'typescript',
2502
+ runtime,
2503
+ runtime_version: runtimeVersion,
2504
+ client: options.client,
2505
+ };
2506
+ let counts = new Map<string, OperationCounts>();
2507
+ let windowStart = 0;
2508
+ let timer: ReturnType<typeof setTimeout> | undefined;
2509
+
2510
+ async function flushWindow(): Promise<void> {
2511
+ if (counts.size === 0) return;
2512
+ if (timer !== undefined) clearTimeout(timer);
2513
+ timer = undefined;
2514
+ activeWindows.delete(flushWindow);
2515
+ const events = toEvents(counts, windowStart, Date.now() - windowStart, options.sdkName, sdk);
2516
+ counts = new Map();
2517
+ if (telemetryDisabled()) return;
2518
+ const send = Promise.resolve()
2519
+ .then(() => sink(events))
2520
+ .catch(() => undefined);
2521
+ pendingSends.add(send);
2522
+ await send;
2523
+ pendingSends.delete(send);
2524
+ }
2525
+
2526
+ installExitHook();
2527
+
2528
+ return {
2529
+ onSettled: (ctx, call) => {
2530
+ if (counts.size === 0) {
2531
+ windowStart = Date.now();
2532
+ timer = setTimeout(() => void flushWindow(), intervalMs);
2533
+ unrefTimer(timer);
2534
+ activeWindows.add(flushWindow);
2535
+ }
2536
+ let operation = counts.get(ctx.operation.id);
2537
+ if (operation === undefined) {
2538
+ operation = emptyCounts();
2539
+ counts.set(ctx.operation.id, operation);
2540
+ }
2541
+ record(operation, call);
2542
+ },
2543
+ };
2544
+ }
2545
+
2546
+ function installExitHook(): void {
2547
+ if (exitHookInstalled) return;
2548
+ exitHookInstalled = true;
2549
+ nodeProcess()?.on?.('beforeExit', () => void flush());
2550
+ }
2551
+
2552
+ function unrefTimer(timer: unknown): void {
2553
+ if (timer instanceof Object && 'unref' in timer && typeof timer.unref === 'function') {
2554
+ timer.unref();
2555
+ }
2556
+ }
2557
+
2558
+ function emptyCounts(): OperationCounts {
2559
+ return {
2560
+ calls: 0,
2561
+ attempts: 0,
2562
+ durationSumMs: 0,
2563
+ status: { '2xx': 0, '3xx': 0, '4xx': 0, '5xx': 0, network_error: 0, timeout: 0, aborted: 0 },
2564
+ latency: { lt_100ms: 0, lt_300ms: 0, lt_1s: 0, lt_3s: 0, lt_10s: 0, gte_10s: 0 },
2565
+ };
2566
+ }
2567
+
2568
+ function record(operation: OperationCounts, call: SettledCall): void {
2569
+ operation.calls += 1;
2570
+ operation.attempts += call.attempts;
2571
+ operation.durationSumMs += call.durationMs;
2572
+ operation.status[statusClass(call)] += 1;
2573
+ for (const { bucket, belowMs } of LATENCY_BUCKETS) {
2574
+ if (call.durationMs < belowMs) {
2575
+ operation.latency[bucket] += 1;
2576
+ break;
2577
+ }
2578
+ }
2579
+ }
2580
+
2581
+ function statusClass(call: SettledCall): StatusClass {
2582
+ if (call.response === undefined) {
2583
+ if (call.error instanceof Error && call.error.name === 'TimeoutError') return 'timeout';
2584
+ if (call.error instanceof Error && call.error.name === 'AbortError') return 'aborted';
2585
+ return 'network_error';
2586
+ }
2587
+ const status = call.response.status;
2588
+ if (status >= 500) return '5xx';
2589
+ if (status >= 400) return '4xx';
2590
+ if (status >= 300) return '3xx';
2591
+ return '2xx';
2592
+ }
2593
+
2594
+ function toEvents(
2595
+ counts: Map<string, OperationCounts>,
2596
+ windowStart: number,
2597
+ windowMs: number,
2598
+ source: string,
2599
+ sdk: Record<string, string>
2600
+ ): SdkUsageEvent[] {
2601
+ const events: SdkUsageEvent[] = [];
2602
+ for (const [operationId, operation] of counts) {
2603
+ const usage: Record<string, string | number> = {
2604
+ operation_id: operationId,
2605
+ window_ms: windowMs,
2606
+ calls: operation.calls,
2607
+ attempts: operation.attempts,
2608
+ duration_sum_ms: operation.durationSumMs,
2609
+ };
2610
+ for (const statusClass of STATUS_CLASSES) {
2611
+ const count = operation.status[statusClass];
2612
+ if (count > 0) {
2613
+ usage[\`status_\${statusClass}\`] = count;
2614
+ }
2615
+ }
2616
+ for (const { bucket } of LATENCY_BUCKETS) {
2617
+ const count = operation.latency[bucket];
2618
+ if (count > 0) {
2619
+ usage[\`latency_\${bucket}\`] = count;
2620
+ }
2621
+ }
2622
+ events.push({
2623
+ id: \`evt_\${randomHex(16)}\`,
2624
+ type: EVENT_TYPE,
2625
+ source,
2626
+ time: new Date(windowStart).toISOString(),
2627
+ data: { usage, sdk },
2628
+ });
2629
+ }
2630
+ return events;
2631
+ }
2632
+
2633
+ async function sendOtlp(endpoint: string, events: SdkUsageEvent[]): Promise<void> {
2634
+ const response = await fetch(endpoint, {
2635
+ method: 'POST',
2636
+ // One send per window, so the socket is never reused: close it instead of keeping it idle.
2637
+ headers: { 'Content-Type': 'application/json', Connection: 'close' },
2638
+ body: JSON.stringify(toOtlpRequest(events)),
2639
+ signal: AbortSignal.timeout(SEND_TIMEOUT_MS),
2640
+ });
2641
+ await response.body?.cancel();
2642
+ }
2643
+
2644
+ type OtlpValue = { stringValue: string } | { intValue: number } | { doubleValue: number };
2645
+ type OtlpAttribute = { key: string; value: OtlpValue };
2646
+
2647
+ function toOtlpRequest(events: SdkUsageEvent[]) {
2648
+ const spans = [];
2649
+ for (const event of events) {
2650
+ const timeUnixNano = \`\${Date.parse(event.time)}000000\`;
2651
+ const attributes: OtlpAttribute[] = [
2652
+ attribute('cloudevents.event_id', event.id),
2653
+ attribute('cloudevents.event_type', event.type),
2654
+ attribute('cloudevents.event_source', event.source),
2655
+ attribute('cloudevents.event_spec_version', '1.0'),
2656
+ attribute('cloudevents.event_data_content_type', 'application/json; charset=utf-8'),
2657
+ attribute('cloudevents.event_time', event.time),
2658
+ attribute('cloudevents.event_subject', ''),
2659
+ attribute('cloudevents.event_origin', SERVICE_NAME),
2660
+ attribute('cloudevents.event_object', 'event'),
2661
+ attribute('cloudevents.event_category', 'product'),
2662
+ attribute('cloudevents.event_signal', 'metric'),
2663
+ ];
2664
+ for (const [key, value] of Object.entries(event.data.usage)) {
2665
+ attributes.push(attribute(\`cloudevents.event_data.usage.\${key}\`, value));
2666
+ }
2667
+ for (const [key, value] of Object.entries(event.data.sdk)) {
2668
+ attributes.push(attribute(\`cloudevents.event_data.sdk.\${key}\`, value));
2669
+ }
2670
+ spans.push({
2671
+ traceId: randomHex(16),
2672
+ spanId: randomHex(8),
2673
+ name: \`event.\${event.type}\`,
2674
+ kind: 1,
2675
+ startTimeUnixNano: timeUnixNano,
2676
+ endTimeUnixNano: timeUnixNano,
2677
+ attributes,
2678
+ });
2679
+ }
2680
+ return {
2681
+ resourceSpans: [
2682
+ {
2683
+ resource: {
2684
+ attributes: [
2685
+ attribute('service.name', SERVICE_NAME),
2686
+ attribute('service.version', GENERATOR_VERSION),
2687
+ ],
2688
+ },
2689
+ scopeSpans: [{ scope: { name: 'redocly-sdk-telemetry' }, spans }],
2690
+ },
2691
+ ],
2692
+ };
2693
+ }
2694
+
2695
+ function attribute(key: string, value: string | number): OtlpAttribute {
2696
+ if (typeof value === 'string') return { key, value: { stringValue: value } };
2697
+ if (Number.isInteger(value)) return { key, value: { intValue: value } };
2698
+ return { key, value: { doubleValue: value } };
2699
+ }
2700
+
2701
+ function randomHex(byteCount: number): string {
2702
+ const bytes = crypto.getRandomValues(new Uint8Array(byteCount));
2703
+ let hex = '';
2704
+ for (const byte of bytes) hex += byte.toString(16).padStart(2, '0');
2705
+ return hex;
2706
+ }
2707
+ `;export{e as a,t as b,n as c,r as d};
@@ -4,7 +4,7 @@ import { dirname as __pathDirname } from 'node:path';
4
4
  const require = __createRequire(import.meta.url);
5
5
  var __filename = __fileURLToPath(import.meta.url);
6
6
  var __dirname = __pathDirname(__filename);
7
- import{h as g}from"./3JYQOGV3.js";import{f as C,m as u,n as p}from"./RU7T4CKG.js";import{c as j,d as v}from"./FDGP3ZYZ.js";import{ia as b}from"./22EANOP2.js";import{a as S,b as k}from"./UW4UC7ZI.js";import{join as $}from"node:path";function h(r){return(r??"").replace(/\s+/g," ").trim().replace(/\\/g,"\\\\").replace(/\|/g,"\\|")}function w(r){return[r.group===void 0?void 0:u(r.group),r.name].filter(Boolean).join(" ")}function T(r,e){return[r,w(e),...e.positionals.map(o=>`<${o.name}>`),...e.flags.filter(o=>o.required).map(o=>`--${o.name} <${o.type}>`),...e.body?[e.body.required?"--json '<json>'":"[--json '<json>']"]:[]].filter(o=>o!=="").join(" ")}function B(r,e){r.line("| Flag | Type | Required | Description |"),r.line("| ---- | ---- | -------- | ----------- |");for(let n of e){let o=[h(n.description),n.enum===void 0?"":`One of ${n.enum.map(t=>`\`${t}\``).join(", ")}.`,n.type==="array"?"Repeat the flag for multiple values.":""].filter(t=>t!=="").join(" ");r.line(`| \`--${n.name}\` | ${n.type} | ${n.required?"yes":"no"} | ${o} |`)}r.blank()}function D(r,e,n){if(r.line(`### \`${w(e)}\``),r.blank(),e.summary!==void 0&&(r.line(h(e.summary)),r.blank()),r.line(`\`${e.method} ${e.path}\``),r.blank(),r.line("```sh"),r.line(T(n.name,e)),r.line("```"),r.blank(),e.positionals.length>0){r.line("| Argument | Description |"),r.line("| -------- | ----------- |");for(let t of e.positionals)r.line(`| \`<${t.name}>\` | ${h(t.description)} |`);r.blank()}e.flags.length>0&&B(r,e.flags);let o=[e.body===void 0?"":`Takes a JSON body${e.body.required?" (required)":""}: \`--json '<json>'\`, \`--json @file.json\`, or \`--json @-\` for stdin.`,e.unsupportedBody===void 0?"":`Takes a \`${e.unsupportedBody}\` body, which the CLI cannot build \u2014 call this operation through the generated client instead.`,e.paginated===!0?"Paginated: `--page-all` follows every page, printing one JSON page per line.":"",e.sse===!0?"Streams server-sent events as one JSON object per line.":"",e.blob===!0?"Returns binary content, so `--output <path>` is required.":""].filter(t=>t!=="");for(let t of o)r.line(t);o.length>0&&r.blank()}function R(r,e){let n=new S;e.frontmatter&&(n.line("---"),n.line(`title: ${e.title}`),n.line("---"),n.blank()),n.line(`# ${e.title}`),n.blank(),n.line(`Generated command-line reference for \`${e.name}\`, produced from the API description by \`redocly generate-client\`.`),n.line("Re-run generation to update it \u2014 this file is not hand-edited."),n.blank(),n.line("## Usage"),n.blank(),n.line("```sh"),n.line(`${e.name} <command> [flags]`),n.line(`${e.name} --help`),n.line(`${e.name} schema <command> # request/response schemas`),n.line("```"),n.blank(),n.line("Install the file under any `bin` name: the command takes that name, and the credential variables below do not change."),n.blank(),n.line("## Global flags"),n.blank(),n.line("| Flag | Description |"),n.line("| ---- | ----------- |");let o=e.schemes.some(i=>i.kind==="bearer");for(let[i,s]of[["--server-url <url>","Override the server URL included in the client."],["--format <json\\|ndjson>","Output format."],["--dry-run","Print the prepared request, credentials redacted, without sending it."],["--page-all","Follow pagination, printing one JSON page per line."],["--output <path>","Write the response body to a file. Required for binary responses."],...o?[["--token <token>","Bearer token, overriding the environment."]]:[],["--json <json\\|@file\\|@->","Request body, inline or from a file or stdin."]])n.line(`| \`${i}\` | ${s} |`);n.blank();let t=p(e.name);if(n.line("## Credentials"),n.blank(),e.schemes.length===0)n.line("The description declares no security schemes, so no credentials are read.");else{n.line("Credentials come from the environment:"),n.blank(),n.line("| Scheme | Variable |"),n.line("| ------ | -------- |");for(let i of e.schemes){let s=i.kind==="bearer"?`\`${t}_TOKEN\` (or \`--token\`)`:i.kind==="basic"?`\`${t}_USERNAME\` and \`${t}_PASSWORD\``:`\`${t}_API_KEY_${p(i.key)}\``;n.line(`| ${i.kind} (\`${i.key}\`) | ${s} |`)}}n.blank(),n.line("## Exit codes"),n.blank(),n.line("| Code | Meaning |"),n.line("| ---- | ------- |");for(let[i,s]of[[0,"success"],[1,"API error (status other than 401 or 403)"],[2,"auth error (401 or 403)"],[3,"validation error"],[4,"usage error (unknown command or flag, bad `--json`)"]])n.line(`| ${i} | ${s} |`);n.blank(),n.line("Errors print one JSON object to stderr, so stdout stays clean for piping."),n.blank();let a=[...new Set(r.map(i=>i.group))];for(let i of a){let s=r.filter(l=>l.group===i);i===void 0?(n.line("## Commands"),n.blank()):(n.line(`## ${i}`),n.blank(),n.line(`Addressed as \`${e.name} ${u(i)} <command>\`.`),n.blank());for(let l of s)D(n,l,e)}return n.toString().replace(/\n{3,}/g,`
7
+ import{h as g}from"./CEASD5U3.js";import{f as C,m as u,n as p}from"./JQJ5TDVP.js";import{c as j,d as v}from"./UNOXQ62I.js";import{ia as b}from"./EQTXHL74.js";import{a as S,b as k}from"./UW4UC7ZI.js";import{join as $}from"node:path";function h(r){return(r??"").replace(/\s+/g," ").trim().replace(/\\/g,"\\\\").replace(/\|/g,"\\|")}function w(r){return[r.group===void 0?void 0:u(r.group),r.name].filter(Boolean).join(" ")}function T(r,e){return[r,w(e),...e.positionals.map(o=>`<${o.name}>`),...e.flags.filter(o=>o.required).map(o=>`--${o.name} <${o.type}>`),...e.body?[e.body.required?"--json '<json>'":"[--json '<json>']"]:[]].filter(o=>o!=="").join(" ")}function B(r,e){r.line("| Flag | Type | Required | Description |"),r.line("| ---- | ---- | -------- | ----------- |");for(let n of e){let o=[h(n.description),n.enum===void 0?"":`One of ${n.enum.map(t=>`\`${t}\``).join(", ")}.`,n.type==="array"?"Repeat the flag for multiple values.":""].filter(t=>t!=="").join(" ");r.line(`| \`--${n.name}\` | ${n.type} | ${n.required?"yes":"no"} | ${o} |`)}r.blank()}function D(r,e,n){if(r.line(`### \`${w(e)}\``),r.blank(),e.summary!==void 0&&(r.line(h(e.summary)),r.blank()),r.line(`\`${e.method} ${e.path}\``),r.blank(),r.line("```sh"),r.line(T(n.name,e)),r.line("```"),r.blank(),e.positionals.length>0){r.line("| Argument | Description |"),r.line("| -------- | ----------- |");for(let t of e.positionals)r.line(`| \`<${t.name}>\` | ${h(t.description)} |`);r.blank()}e.flags.length>0&&B(r,e.flags);let o=[e.body===void 0?"":`Takes a JSON body${e.body.required?" (required)":""}: \`--json '<json>'\`, \`--json @file.json\`, or \`--json @-\` for stdin.`,e.unsupportedBody===void 0?"":`Takes a \`${e.unsupportedBody}\` body, which the CLI cannot build \u2014 call this operation through the generated client instead.`,e.paginated===!0?"Paginated: `--page-all` follows every page, printing one JSON page per line.":"",e.sse===!0?"Streams server-sent events as one JSON object per line.":"",e.blob===!0?"Returns binary content, so `--output <path>` is required.":""].filter(t=>t!=="");for(let t of o)r.line(t);o.length>0&&r.blank()}function R(r,e){let n=new S;e.frontmatter&&(n.line("---"),n.line(`title: ${e.title}`),n.line("---"),n.blank()),n.line(`# ${e.title}`),n.blank(),n.line(`Generated command-line reference for \`${e.name}\`, produced from the API description by \`redocly generate-client\`.`),n.line("Re-run generation to update it \u2014 this file is not hand-edited."),n.blank(),n.line("## Usage"),n.blank(),n.line("```sh"),n.line(`${e.name} <command> [flags]`),n.line(`${e.name} --help`),n.line(`${e.name} schema <command> # request/response schemas`),n.line("```"),n.blank(),n.line("Install the file under any `bin` name: the command takes that name, and the credential variables below do not change."),n.blank(),n.line("## Global flags"),n.blank(),n.line("| Flag | Description |"),n.line("| ---- | ----------- |");let o=e.schemes.some(i=>i.kind==="bearer");for(let[i,s]of[["--server-url <url>","Override the server URL included in the client."],["--format <json\\|ndjson>","Output format."],["--dry-run","Print the prepared request, credentials redacted, without sending it."],["--page-all","Follow pagination, printing one JSON page per line."],["--output <path>","Write the response body to a file. Required for binary responses."],...o?[["--token <token>","Bearer token, overriding the environment."]]:[],["--json <json\\|@file\\|@->","Request body, inline or from a file or stdin."]])n.line(`| \`${i}\` | ${s} |`);n.blank();let t=p(e.name);if(n.line("## Credentials"),n.blank(),e.schemes.length===0)n.line("The description declares no security schemes, so no credentials are read.");else{n.line("Credentials come from the environment:"),n.blank(),n.line("| Scheme | Variable |"),n.line("| ------ | -------- |");for(let i of e.schemes){let s=i.kind==="bearer"?`\`${t}_TOKEN\` (or \`--token\`)`:i.kind==="basic"?`\`${t}_USERNAME\` and \`${t}_PASSWORD\``:`\`${t}_API_KEY_${p(i.key)}\``;n.line(`| ${i.kind} (\`${i.key}\`) | ${s} |`)}}n.blank(),n.line("## Exit codes"),n.blank(),n.line("| Code | Meaning |"),n.line("| ---- | ------- |");for(let[i,s]of[[0,"success"],[1,"API error (status other than 401 or 403)"],[2,"auth error (401 or 403)"],[3,"validation error"],[4,"usage error (unknown command or flag, bad `--json`)"]])n.line(`| ${i} | ${s} |`);n.blank(),n.line("Errors print one JSON object to stderr, so stdout stays clean for piping."),n.blank();let a=[...new Set(r.map(i=>i.group))];for(let i of a){let s=r.filter(l=>l.group===i);i===void 0?(n.line("## Commands"),n.blank()):(n.line(`## ${i}`),n.blank(),n.line(`Addressed as \`${e.name} ${u(i)} <command>\`.`),n.blank());for(let l of s)D(n,l,e)}return n.toString().replace(/\n{3,}/g,`
8
8
 
9
9
  `).trimEnd()+`
10
10
  `}function x(){return v["cli.ts"]}function E(){return j["cli.ts"]}var q="// Generated by @redocly/client-generator \u2014 do not edit by hand.\n// Source: OpenAPI description. Re-run `redocly generate-client` to update.";function P(r){return k.snake(r).replace(/_/g,"-")}function O(r){let e=r.schema,n=e.kind==="array"?"array":e.kind==="scalar"&&(e.scalar==="integer"||e.scalar==="number")?"number":e.kind==="scalar"&&e.scalar==="boolean"?"boolean":"string";return{name:P(r.name),param:r.name,type:n,required:r.required,...e.kind==="enum"?{enum:e.values.map(String)}:{},...r.description!==void 0?{description:r.description}:{}}}function F(r){let e=r.successResponses;return e.some(n=>n.contentType.toLowerCase().includes("json"))?!1:e.some(n=>C(n.contentType))}function M(r){return r.successResponses.find(e=>e.contentType.toLowerCase().includes("json"))?.schema}function U(r,e,n){if(n!=="flat")return{};let o=g(r,e.schemas);return"mergeBody"in o&&o.mergeBody?{merged:!0}:{}}function _(r,e,n){return n!=="flat"?{}:"collisions"in g(r,e.schemas)?{argsStyle:"grouped"}:{}}function f(r,e){let n=[];for(let o of r.services)for(let t of o.operations){let a=t.requestBody?.contentType.toLowerCase().includes("json")?t.requestBody:void 0,i=M(t);n.push({...t.tags.length>0?{group:t.tags[0]}:{},name:t.name,...t.summary!==void 0?{summary:t.summary}:{},method:t.method.toUpperCase(),path:t.path,positionals:t.pathParams.map(s=>({name:s.name,type:O(s).type,...s.description!==void 0?{description:s.description}:{}})),flags:t.queryParams.map(O),...a?{body:{required:a.required,...U(t,r,e.argsStyle)}}:{},...a===void 0&&t.requestBody!==void 0?{unsupportedBody:t.requestBody.contentType}:{},...e.pagination?.has(t.name)===!0?{paginated:!0}:{},..._(t,r,e.argsStyle),...t.sse!==void 0?{sse:!0}:{},...F(t)?{blob:!0}:{},...a!==void 0||i!==void 0?{schemas:{...a?{request:a.schema}:{},...i!==void 0?{response:i}:{}}}:{}})}return n}var A=`function isProcessEntry(): boolean {