@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.
- package/THIRD_PARTY_NOTICES +1 -1
- package/lib/chunks/{37WWN4MA.js → 2DKR4Z25.js} +1 -1
- package/lib/chunks/{S6NFOZ34.js → 2MCPXKB6.js} +1 -1
- package/lib/chunks/2ZIICV4T.js +7 -0
- package/lib/chunks/3CSDNX6S.js +20 -0
- package/lib/chunks/{KOR5TUJG.js → 4EAF6XUQ.js} +1 -1
- package/lib/chunks/5PR7FNUB.js +59 -0
- package/lib/chunks/{5X35UU2C.js → 654FMWX6.js} +1 -1
- package/lib/chunks/{4AM55DEH.js → 6FADWAOY.js} +1 -1
- package/lib/chunks/{3FXYWWTJ.js → 6MP4DHWK.js} +1 -1
- package/lib/chunks/{SLQPKXO2.js → 7APJVQSB.js} +1 -1
- package/lib/chunks/{KRCCY64H.js → AC62H63B.js} +1 -1
- package/lib/chunks/{ZCVUIIPU.js → ALBI5SPY.js} +1 -1
- package/lib/chunks/{SXBAAS4M.js → B5ZOH4BB.js} +1 -1
- package/lib/chunks/{V2YF33JL.js → BGGUKU7E.js} +1 -1
- package/lib/chunks/{6EGJEFXO.js → BWXAXULF.js} +1 -1
- package/lib/chunks/{3JYQOGV3.js → CEASD5U3.js} +1 -1
- package/lib/chunks/{TBZEEKTV.js → CVPT656W.js} +1 -1
- package/lib/chunks/{5PG3ST2N.js → DL4VP2Z4.js} +2 -2
- package/lib/chunks/DPNI74SB.js +69 -0
- package/lib/chunks/{GWXT3QO6.js → ENIPOAVJ.js} +2 -2
- package/lib/chunks/{22EANOP2.js → EQTXHL74.js} +101 -101
- package/lib/chunks/{3WHXM4DJ.js → FU7GBMUU.js} +1 -1
- package/lib/chunks/{JLVGRO3I.js → FVGFKJ67.js} +7 -7
- package/lib/chunks/{73RBZL53.js → FXKIC5R3.js} +1 -1
- package/lib/chunks/{2OBVZIAW.js → GKCVQWOQ.js} +3 -3
- package/lib/chunks/{MNH2K4WM.js → GKSUZULD.js} +1 -1
- package/lib/chunks/GOTKYHFM.js +20 -0
- package/lib/chunks/{2XK7ML3U.js → GRTUPOKN.js} +1 -1
- package/lib/chunks/{XJE2OFDN.js → HAOBCQWB.js} +358 -19
- package/lib/chunks/{IUSSBOYO.js → HIII45WJ.js} +1 -1
- package/lib/chunks/{2OVI7BIW.js → HYMULX2S.js} +1 -1
- package/lib/chunks/{FDMXHRDK.js → I6NMWBVI.js} +1 -1
- package/lib/chunks/{SHZZKTDE.js → IH3N62Q4.js} +1 -1
- package/lib/chunks/{V3ILUN2S.js → J665DSDI.js} +1 -1
- package/lib/chunks/JQJ5TDVP.js +11 -0
- package/lib/chunks/{HWTYAU4Y.js → L5X7LBV6.js} +1 -1
- package/lib/chunks/{VXONEXYX.js → LCAJ35J6.js} +1 -1
- package/lib/chunks/{US7X4XPD.js → LG3SUXEW.js} +1 -1
- package/lib/chunks/{YDVWNFMS.js → LMO5V2XF.js} +1 -1
- package/lib/chunks/{XFBJHVYU.js → M4NCSK7Q.js} +1 -1
- package/lib/chunks/{RPHIT72T.js → M74SGAZK.js} +1 -1
- package/lib/chunks/{M3XPS7UF.js → MVCGBDOY.js} +1 -1
- package/lib/chunks/{HYE4U6V5.js → N4R4236N.js} +1 -1
- package/lib/chunks/{6NB3FKVN.js → NRWIPPEV.js} +1 -1
- package/lib/chunks/{3C6UUCEW.js → OGNRVBTI.js} +1 -1
- package/lib/chunks/{6MH5ZWLD.js → ONBORCDJ.js} +1 -1
- package/lib/chunks/{ENSYM7KY.js → OS52EARM.js} +1 -1
- package/lib/chunks/{6DO6IN4A.js → QCOPS234.js} +1 -1
- package/lib/chunks/{CQKQB4PJ.js → QWTSCCNH.js} +1 -1
- package/lib/chunks/{4OEXH5EV.js → RRQJCLNO.js} +1 -1
- package/lib/chunks/{HBENVUR4.js → RWDQI2KD.js} +1 -1
- package/lib/chunks/{I5CGSLGR.js → S3W5GQGC.js} +1 -1
- package/lib/chunks/{HUWKDZPP.js → SRRHJLPL.js} +1 -1
- package/lib/chunks/{7WM6VLB3.js → TTE4EAVV.js} +3 -2
- package/lib/chunks/{LRLGVYCG.js → TWFZE4OF.js} +1 -1
- package/lib/chunks/{OP7NIAI7.js → U4RAHOFK.js} +1 -1
- package/lib/chunks/{36IHQANV.js → UC5EDLXL.js} +1 -1
- package/lib/chunks/{TKLMYBPI.js → ULQK2S4O.js} +1 -1
- package/lib/chunks/{FDGP3ZYZ.js → UNOXQ62I.js} +363 -156
- package/lib/chunks/{6WZUCZGV.js → UQW6CW3M.js} +1 -1
- package/lib/chunks/{DS4SCWID.js → VKTRI5YG.js} +1 -1
- package/lib/chunks/{PTNNX4IU.js → VMIHLA3H.js} +1 -1
- package/lib/chunks/{WX24BERR.js → VWF52WKH.js} +1 -1
- package/lib/chunks/WKQJPOYW.js +7 -0
- package/lib/chunks/{SYWAPWW7.js → WQBSNQXL.js} +1 -1
- package/lib/chunks/{CIDSJFJO.js → X6TQQHRM.js} +1 -1
- package/lib/chunks/{XJTGJYVS.js → XDBFHG7X.js} +1 -1
- package/lib/chunks/{LVGVWPDB.js → XYU2LTWU.js} +1 -1
- package/lib/chunks/{2OQM5ARW.js → Z4X6WES7.js} +1 -1
- package/lib/chunks/{3JYY42DL.js → ZFXOCOU6.js} +1 -1
- package/lib/chunks/{3DEJQSYG.js → ZM3M44Q3.js} +1 -1
- package/lib/eject-assets/generators/cli/docs.ts +1 -1
- package/lib/eject-assets/generators/cli/engine-source.ts +1 -1
- package/lib/eject-assets/generators/cli/index.ts +2 -2
- package/lib/eject-assets/generators/cli/render.ts +1 -1
- package/lib/eject-assets/generators/go/client.ts +1 -1
- package/lib/eject-assets/generators/go/descriptor.ts +2 -1
- package/lib/eject-assets/generators/go/index.ts +2 -2
- package/lib/eject-assets/generators/go/models.ts +1 -1
- package/lib/eject-assets/generators/go/naming.ts +1 -1
- package/lib/eject-assets/generators/go/operations.ts +1 -1
- package/lib/eject-assets/generators/go/pagination.ts +1 -1
- package/lib/eject-assets/generators/go/types.ts +1 -1
- package/lib/eject-assets/generators/mock/faker.ts +1 -1
- package/lib/eject-assets/generators/mock/index.ts +2 -2
- package/lib/eject-assets/generators/mock/render.ts +1 -1
- package/lib/eject-assets/generators/mock/sample.ts +1 -1
- package/lib/eject-assets/generators/mock/values.ts +1 -1
- package/lib/eject-assets/generators/php/client.ts +1 -1
- package/lib/eject-assets/generators/php/descriptor.ts +2 -1
- package/lib/eject-assets/generators/php/index.ts +2 -2
- package/lib/eject-assets/generators/php/models.ts +1 -1
- package/lib/eject-assets/generators/php/naming.ts +1 -1
- package/lib/eject-assets/generators/php/operations.ts +1 -1
- package/lib/eject-assets/generators/php/pagination.ts +1 -1
- package/lib/eject-assets/generators/php/types.ts +1 -1
- package/lib/eject-assets/generators/python/client.ts +1 -1
- package/lib/eject-assets/generators/python/descriptor.ts +2 -1
- package/lib/eject-assets/generators/python/index.ts +2 -2
- package/lib/eject-assets/generators/python/models.ts +1 -1
- package/lib/eject-assets/generators/python/naming.ts +1 -1
- package/lib/eject-assets/generators/python/operations.ts +1 -1
- package/lib/eject-assets/generators/python/pagination.ts +1 -1
- package/lib/eject-assets/generators/python/types.ts +1 -1
- package/lib/eject-assets/generators/swr/index.ts +2 -2
- package/lib/eject-assets/generators/swr/render.ts +1 -1
- package/lib/eject-assets/generators/tanstack-query/index.ts +2 -2
- package/lib/eject-assets/generators/tanstack-query/render.ts +56 -9
- package/lib/eject-assets/generators/transformers/index.ts +2 -2
- package/lib/eject-assets/generators/transformers/render.ts +1 -1
- package/lib/eject-assets/generators/typescript/banner.ts +1 -1
- package/lib/eject-assets/generators/typescript/client.ts +1 -1
- package/lib/eject-assets/generators/typescript/descriptor.ts +1 -1
- package/lib/eject-assets/generators/typescript/index.ts +29 -3
- package/lib/eject-assets/generators/typescript/inline-runtime.ts +1 -1
- package/lib/eject-assets/generators/typescript/operation-signature.ts +1 -1
- package/lib/eject-assets/generators/typescript/operation-types.ts +1 -1
- package/lib/eject-assets/generators/typescript/operations.ts +1 -1
- package/lib/eject-assets/generators/typescript/response-headers.ts +1 -1
- package/lib/eject-assets/generators/typescript/type-guards.ts +1 -1
- package/lib/eject-assets/generators/typescript/types.ts +1 -1
- package/lib/eject-assets/generators/zod/index.ts +2 -2
- package/lib/eject-assets/generators/zod/schemas.ts +1 -1
- package/lib/eject-assets/skills/tanstack-query-generator/SKILL.md +5 -2
- package/lib/eject-assets/skills/typescript-generator/SKILL.md +24 -0
- package/lib/index.js +5 -5
- package/package.json +1 -1
- package/lib/chunks/5SIJI5LC.js +0 -42
- package/lib/chunks/7WTV5KH3.js +0 -67
- package/lib/chunks/EDQ6QRIB.js +0 -20
- package/lib/chunks/LCFG5N4V.js +0 -7
- package/lib/chunks/PWGFZ5ZK.js +0 -7
- package/lib/chunks/RU7T4CKG.js +0 -11
- 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
|
|
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
|
-
|
|
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\`
|
|
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 =
|
|
1291
|
-
|
|
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),
|
|
1963
|
-
# \`Link: rel="next"\` following
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
`};
|
|
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"./
|
|
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 {
|