@scalar/api-client 3.9.0 → 3.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/plugins/posthog/sanitize-event-payload.d.ts.map +1 -1
  3. package/dist/plugins/posthog/sanitize-event-payload.js +2 -0
  4. package/dist/plugins/posthog/sanitize-event-payload.js.map +1 -1
  5. package/dist/style.css +10 -17
  6. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
  7. package/dist/v2/blocks/operation-block/helpers/send-request.js +5 -8
  8. package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
  9. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts +7 -4
  10. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts.map +1 -1
  11. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js +1 -1
  12. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js.map +1 -1
  13. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js +28 -15
  14. package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map +1 -1
  15. package/dist/v2/blocks/operation-code-sample/helpers/find-client.d.ts +31 -31
  16. package/dist/v2/blocks/operation-code-sample/helpers/find-client.d.ts.map +1 -1
  17. package/dist/v2/blocks/operation-code-sample/helpers/find-client.js +32 -39
  18. package/dist/v2/blocks/operation-code-sample/helpers/find-client.js.map +1 -1
  19. package/dist/v2/blocks/operation-code-sample/helpers/format-language.d.ts +8 -0
  20. package/dist/v2/blocks/operation-code-sample/helpers/format-language.d.ts.map +1 -0
  21. package/dist/v2/blocks/operation-code-sample/helpers/format-language.js +70 -0
  22. package/dist/v2/blocks/operation-code-sample/helpers/format-language.js.map +1 -0
  23. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.d.ts +15 -5
  24. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.d.ts.map +1 -1
  25. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.js +23 -6
  26. package/dist/v2/blocks/operation-code-sample/helpers/generate-client-options.js.map +1 -1
  27. package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts.map +1 -1
  28. package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js +2 -2
  29. package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js.map +1 -1
  30. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.d.ts +2 -1
  31. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.d.ts.map +1 -1
  32. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.js +23 -17
  33. package/dist/v2/blocks/operation-code-sample/helpers/get-clients.js.map +1 -1
  34. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.d.ts +38 -3
  35. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.d.ts.map +1 -1
  36. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.js +74 -8
  37. package/dist/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.js.map +1 -1
  38. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts.map +1 -1
  39. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js +12 -87
  40. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js.map +1 -1
  41. package/dist/v2/blocks/operation-code-sample/index.d.ts +1 -1
  42. package/dist/v2/blocks/operation-code-sample/index.d.ts.map +1 -1
  43. package/dist/v2/blocks/operation-code-sample/index.js +2 -2
  44. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
  45. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
  46. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +11 -6
  47. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
  48. package/dist/v2/constants.js +1 -1
  49. package/dist/v2/workspace-events.d.ts.map +1 -1
  50. package/dist/v2/workspace-events.js +2 -0
  51. package/dist/v2/workspace-events.js.map +1 -1
  52. package/dist/vue-styles.css +7 -7
  53. package/package.json +12 -13
@@ -1,28 +1,34 @@
1
- import { generateCustomId } from "./generate-client-options.js";
1
+ import { formatLanguage } from "./format-language.js";
2
+ import { getCustomClientIds } from "./generate-client-options.js";
3
+ import { CODE_EXAMPLES_GROUP_LABEL } from "./get-custom-code-samples.js";
2
4
  //#region src/v2/blocks/operation-code-sample/helpers/get-clients.ts
3
5
  /**
4
6
  * Merges custom code samples with the client options
5
7
  *
6
8
  * @param customCodeSamples - The custom code samples from the operation to merge with the client options
7
9
  * @param clientOptions - The client options to merge with the custom code samples
10
+ * @param label - The label for the custom samples group (e.g. "SDK" or "Code Examples")
8
11
  * @returns A list of client option groups
9
12
  */
10
- var getClients = (customCodeSamples, clientOptions) => {
11
- if (customCodeSamples.length) return [{
12
- label: "Code Examples",
13
- key: "custom",
14
- options: customCodeSamples.map((sample, index) => {
15
- const id = generateCustomId(index);
16
- const label = sample.label || sample.lang || id;
17
- return {
18
- id,
19
- lang: sample.lang || "plaintext",
20
- title: label,
21
- label,
22
- clientKey: "custom"
23
- };
24
- })
25
- }, ...clientOptions];
13
+ var getClients = (customCodeSamples, clientOptions, label = CODE_EXAMPLES_GROUP_LABEL) => {
14
+ if (customCodeSamples.length) {
15
+ const ids = getCustomClientIds(customCodeSamples);
16
+ return [{
17
+ label,
18
+ key: "custom",
19
+ options: customCodeSamples.map((sample, index) => {
20
+ const id = ids[index] ?? `custom/${index}`;
21
+ const label = sample.label || formatLanguage(sample.lang) || id;
22
+ return {
23
+ id,
24
+ lang: sample.lang || "plaintext",
25
+ title: label,
26
+ label,
27
+ clientKey: "custom"
28
+ };
29
+ })
30
+ }, ...clientOptions];
31
+ }
26
32
  return clientOptions;
27
33
  };
28
34
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"get-clients.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-clients.ts"],"sourcesContent":["import type { TargetId } from '@scalar/types/snippetz'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\n\nimport type { ClientOptionGroup, CustomClientOption } from '@/v2/blocks/operation-code-sample'\nimport { generateCustomId } from '@/v2/blocks/operation-code-sample/helpers/generate-client-options'\nimport type { CustomClientOptionGroup } from '@/v2/blocks/operation-code-sample/types'\n\n/**\n * Merges custom code samples with the client options\n *\n * @param customCodeSamples - The custom code samples from the operation to merge with the client options\n * @param clientOptions - The client options to merge with the custom code samples\n * @returns A list of client option groups\n */\nexport const getClients = (\n customCodeSamples: XCodeSample[],\n clientOptions: ClientOptionGroup[],\n): CustomClientOptionGroup[] => {\n // Handle custom code examples\n if (customCodeSamples.length) {\n const customClients = customCodeSamples.map((sample, index) => {\n const id = generateCustomId(index)\n const label = sample.label || sample.lang || id\n const lang = (sample.lang as TargetId) || 'plaintext'\n\n return {\n id,\n lang,\n title: label,\n label,\n clientKey: 'custom',\n } satisfies CustomClientOption\n })\n\n return [\n {\n label: 'Code Examples',\n key: 'custom',\n options: customClients,\n },\n ...clientOptions,\n ]\n }\n\n return clientOptions\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,cACX,mBACA,kBAC8B;AAE9B,KAAI,kBAAkB,OAepB,QAAO,CACL;EACE,OAAO;EACP,KAAK;EACL,SAlBkB,kBAAkB,KAAK,QAAQ,UAAU;GAC7D,MAAM,KAAK,iBAAiB,MAAM;GAClC,MAAM,QAAQ,OAAO,SAAS,OAAO,QAAQ;AAG7C,UAAO;IACL;IACA,MAJY,OAAO,QAAqB;IAKxC,OAAO;IACP;IACA,WAAW;IACZ;IACD;EAOC,EACD,GAAG,cACJ;AAGH,QAAO"}
1
+ {"version":3,"file":"get-clients.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-clients.ts"],"sourcesContent":["import type { TargetId } from '@scalar/types/snippetz'\nimport type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\n\nimport type { ClientOptionGroup, CustomClientOption } from '@/v2/blocks/operation-code-sample'\nimport { formatLanguage } from '@/v2/blocks/operation-code-sample/helpers/format-language'\nimport { getCustomClientIds } from '@/v2/blocks/operation-code-sample/helpers/generate-client-options'\nimport { CODE_EXAMPLES_GROUP_LABEL } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport type { CustomClientOptionGroup } from '@/v2/blocks/operation-code-sample/types'\n\n/**\n * Merges custom code samples with the client options\n *\n * @param customCodeSamples - The custom code samples from the operation to merge with the client options\n * @param clientOptions - The client options to merge with the custom code samples\n * @param label - The label for the custom samples group (e.g. \"SDK\" or \"Code Examples\")\n * @returns A list of client option groups\n */\nexport const getClients = (\n customCodeSamples: XCodeSample[],\n clientOptions: ClientOptionGroup[],\n label: string = CODE_EXAMPLES_GROUP_LABEL,\n): CustomClientOptionGroup[] => {\n // Handle custom code examples\n if (customCodeSamples.length) {\n // Language-keyed ids so the same sample can be selected across operations\n const ids = getCustomClientIds(customCodeSamples)\n\n const customClients = customCodeSamples.map((sample, index) => {\n const id = ids[index] ?? `custom/${index}`\n const label = sample.label || formatLanguage(sample.lang) || id\n const lang = (sample.lang as TargetId) || 'plaintext'\n\n return {\n id,\n lang,\n title: label,\n label,\n clientKey: 'custom',\n } satisfies CustomClientOption\n })\n\n return [\n {\n label,\n key: 'custom',\n options: customClients,\n },\n ...clientOptions,\n ]\n }\n\n return clientOptions\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,IAAa,cACX,mBACA,eACA,QAAgB,8BACc;AAE9B,KAAI,kBAAkB,QAAQ;EAE5B,MAAM,MAAM,mBAAmB,kBAAkB;AAgBjD,SAAO,CACL;GACE;GACA,KAAK;GACL,SAlBkB,kBAAkB,KAAK,QAAQ,UAAU;IAC7D,MAAM,KAAK,IAAI,UAAU,UAAU;IACnC,MAAM,QAAQ,OAAO,SAAS,eAAe,OAAO,KAAK,IAAI;AAG7D,WAAO;KACL;KACA,MAJY,OAAO,QAAqB;KAKxC,OAAO;KACP;KACA,WAAW;KACZ;KACD;GAOC,EACD,GAAG,cACJ;;AAGH,QAAO"}
@@ -1,10 +1,45 @@
1
1
  import type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation';
2
2
  import type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document';
3
+ /** Picker group label for samples generated by an SDK provider (Scalar, Stainless, …). */
4
+ declare const SDK_GROUP_LABEL = "SDK";
5
+ /** Picker group label for generic or docs-platform samples (the standard `x-codeSamples` family, ReadMe, …). */
6
+ export declare const CODE_EXAMPLES_GROUP_LABEL = "Code Examples";
7
+ type CustomCodeSampleGroupLabel = typeof SDK_GROUP_LABEL | typeof CODE_EXAMPLES_GROUP_LABEL;
8
+ type CustomCodeSamples = {
9
+ /**
10
+ * Group label for the code sample picker.
11
+ *
12
+ * Samples that come from an SDK provider extension (`x-scalar-examples`,
13
+ * `x-stainless-snippets`, `x-stainless-examples`) surface under "SDK". Generic
14
+ * or docs-platform samples (`x-readme`, the `x-codeSamples` family) surface
15
+ * under "Code Examples".
16
+ */
17
+ label: CustomCodeSampleGroupLabel;
18
+ /** The custom code samples, in picker order. */
19
+ samples: XCodeSample[];
20
+ };
3
21
  /**
4
- * Grabs any custom code samples from the operation
22
+ * Grabs any custom code samples from the operation.
23
+ *
24
+ * Several tools write code samples into OpenAPI under different extensions. When
25
+ * more than one is present we use the highest-priority source only, rather than
26
+ * showing duplicates from every tool. Priority, highest first:
27
+ *
28
+ * 1. `x-scalar-examples` (SDK)
29
+ * 2. `x-stainless-snippets` (SDK, overrides `x-stainless-examples`)
30
+ * 3. `x-stainless-examples` (SDK)
31
+ * 4. `x-readme.code-samples` (Code Examples)
32
+ * 5. `x-codeSamples` / `x-code-samples` / `x-custom-examples` (Code Examples)
33
+ *
34
+ * The winning source also determines the picker group label: SDK-provider
35
+ * extensions surface under "SDK", everything else under "Code Examples".
36
+ *
37
+ * Note that Speakeasy does not have its own extension — it writes into the
38
+ * standard `x-codeSamples`, so its snippets surface under "Code Examples".
5
39
  *
6
40
  * @param operation - The operation to get the custom code samples from
7
- * @returns An array of custom code samples which exist in the operation
41
+ * @returns The picker group label and the custom code samples which exist in the operation
8
42
  */
9
- export declare const getCustomCodeSamples: (operation: OperationObject) => XCodeSample[];
43
+ export declare const getCustomCodeSamples: (operation: OperationObject) => CustomCodeSamples;
44
+ export {};
10
45
  //# sourceMappingURL=get-custom-code-samples.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-custom-code-samples.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sDAAsD,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AAEnG;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,WAAW,eAAe,KAAG,WAAW,EAG5E,CAAA"}
1
+ {"version":3,"file":"get-custom-code-samples.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAGZ,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AA+BnG,0FAA0F;AAC1F,QAAA,MAAM,eAAe,QAAQ,CAAA;AAE7B,gHAAgH;AAChH,eAAO,MAAM,yBAAyB,kBAAkB,CAAA;AAExD,KAAK,0BAA0B,GAAG,OAAO,eAAe,GAAG,OAAO,yBAAyB,CAAA;AAE3F,KAAK,iBAAiB,GAAG;IACvB;;;;;;;OAOG;IACH,KAAK,EAAE,0BAA0B,CAAA;IACjC,gDAAgD;IAChD,OAAO,EAAE,WAAW,EAAE,CAAA;CACvB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oBAAoB,GAAI,WAAW,eAAe,KAAG,iBAuBjE,CAAA"}
@@ -1,18 +1,84 @@
1
1
  //#region src/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.ts
2
+ /** Turns a `{ language: source }` map (x-stainless-snippets) into code samples. */
3
+ var fromSnippetMap = (snippets, label) => Object.entries(snippets ?? {}).map(([lang, source]) => ({
4
+ lang,
5
+ source,
6
+ ...label ? { label } : {}
7
+ }));
2
8
  /**
3
- * Grabs any custom code samples from the operation
9
+ * Turns `x-stainless-examples` / `x-scalar-examples` into code samples.
10
+ *
11
+ * Each example carries per-language request snippets and an optional title that
12
+ * we surface as the picker label. The response is only used for documentation,
13
+ * so it is ignored here.
14
+ */
15
+ var fromLanguageExamples = (examples) => {
16
+ if (!examples) return [];
17
+ return (Array.isArray(examples) ? examples : [examples]).flatMap((example) => fromSnippetMap(example.request, example.title));
18
+ };
19
+ /** Turns ReadMe's `x-readme.code-samples` into code samples. */
20
+ var fromReadmeSamples = (samples) => (samples ?? []).map((sample) => ({
21
+ lang: sample.language,
22
+ source: sample.code,
23
+ ...sample.name ? { label: sample.name } : {}
24
+ }));
25
+ /** Picker group label for samples generated by an SDK provider (Scalar, Stainless, …). */
26
+ var SDK_GROUP_LABEL = "SDK";
27
+ /** Picker group label for generic or docs-platform samples (the standard `x-codeSamples` family, ReadMe, …). */
28
+ var CODE_EXAMPLES_GROUP_LABEL = "Code Examples";
29
+ /**
30
+ * Grabs any custom code samples from the operation.
31
+ *
32
+ * Several tools write code samples into OpenAPI under different extensions. When
33
+ * more than one is present we use the highest-priority source only, rather than
34
+ * showing duplicates from every tool. Priority, highest first:
35
+ *
36
+ * 1. `x-scalar-examples` (SDK)
37
+ * 2. `x-stainless-snippets` (SDK, overrides `x-stainless-examples`)
38
+ * 3. `x-stainless-examples` (SDK)
39
+ * 4. `x-readme.code-samples` (Code Examples)
40
+ * 5. `x-codeSamples` / `x-code-samples` / `x-custom-examples` (Code Examples)
41
+ *
42
+ * The winning source also determines the picker group label: SDK-provider
43
+ * extensions surface under "SDK", everything else under "Code Examples".
44
+ *
45
+ * Note that Speakeasy does not have its own extension — it writes into the
46
+ * standard `x-codeSamples`, so its snippets surface under "Code Examples".
4
47
  *
5
48
  * @param operation - The operation to get the custom code samples from
6
- * @returns An array of custom code samples which exist in the operation
49
+ * @returns The picker group label and the custom code samples which exist in the operation
7
50
  */
8
51
  var getCustomCodeSamples = (operation) => {
9
- return [
10
- "x-custom-examples",
11
- "x-codeSamples",
12
- "x-code-samples"
13
- ].flatMap((key) => operation[key] ?? []);
52
+ const scalarExamples = operation["x-scalar-examples"] ?? [];
53
+ if (scalarExamples.length) return {
54
+ label: SDK_GROUP_LABEL,
55
+ samples: scalarExamples
56
+ };
57
+ const stainlessSnippets = fromSnippetMap(operation["x-stainless-snippets"]);
58
+ if (stainlessSnippets.length) return {
59
+ label: SDK_GROUP_LABEL,
60
+ samples: stainlessSnippets
61
+ };
62
+ const stainlessExamples = fromLanguageExamples(operation["x-stainless-examples"]);
63
+ if (stainlessExamples.length) return {
64
+ label: SDK_GROUP_LABEL,
65
+ samples: stainlessExamples
66
+ };
67
+ const readmeSamples = fromReadmeSamples(operation["x-readme"]?.["code-samples"]);
68
+ if (readmeSamples.length) return {
69
+ label: CODE_EXAMPLES_GROUP_LABEL,
70
+ samples: readmeSamples
71
+ };
72
+ return {
73
+ label: CODE_EXAMPLES_GROUP_LABEL,
74
+ samples: [
75
+ "x-custom-examples",
76
+ "x-codeSamples",
77
+ "x-code-samples"
78
+ ].flatMap((key) => operation[key] ?? [])
79
+ };
14
80
  };
15
81
  //#endregion
16
- export { getCustomCodeSamples };
82
+ export { CODE_EXAMPLES_GROUP_LABEL, getCustomCodeSamples };
17
83
 
18
84
  //# sourceMappingURL=get-custom-code-samples.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-custom-code-samples.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.ts"],"sourcesContent":["import type { XCodeSample } from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\n/**\n * Grabs any custom code samples from the operation\n *\n * @param operation - The operation to get the custom code samples from\n * @returns An array of custom code samples which exist in the operation\n */\nexport const getCustomCodeSamples = (operation: OperationObject): XCodeSample[] => {\n const customCodeKeys = ['x-custom-examples', 'x-codeSamples', 'x-code-samples'] as const\n return customCodeKeys.flatMap((key) => operation[key] ?? [])\n}\n"],"mappings":";;;;;;;AASA,IAAa,wBAAwB,cAA8C;AAEjF,QADuB;EAAC;EAAqB;EAAiB;EAAiB,CACzD,SAAS,QAAQ,UAAU,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"get-custom-code-samples.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/helpers/get-custom-code-samples.ts"],"sourcesContent":["import type {\n XCodeSample,\n XLanguageExample,\n XReadmeCodeSample,\n} from '@scalar/workspace-store/schemas/extensions/operation'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\n/** Turns a `{ language: source }` map (x-stainless-snippets) into code samples. */\nconst fromSnippetMap = (snippets: Record<string, string> | undefined, label?: string): XCodeSample[] =>\n Object.entries(snippets ?? {}).map(([lang, source]) => ({ lang, source, ...(label ? { label } : {}) }))\n\n/**\n * Turns `x-stainless-examples` / `x-scalar-examples` into code samples.\n *\n * Each example carries per-language request snippets and an optional title that\n * we surface as the picker label. The response is only used for documentation,\n * so it is ignored here.\n */\nconst fromLanguageExamples = (examples: XLanguageExample | XLanguageExample[] | undefined): XCodeSample[] => {\n if (!examples) {\n return []\n }\n\n return (Array.isArray(examples) ? examples : [examples]).flatMap((example) =>\n fromSnippetMap(example.request, example.title),\n )\n}\n\n/** Turns ReadMe's `x-readme.code-samples` into code samples. */\nconst fromReadmeSamples = (samples: XReadmeCodeSample[] | undefined): XCodeSample[] =>\n (samples ?? []).map((sample) => ({\n lang: sample.language,\n source: sample.code,\n ...(sample.name ? { label: sample.name } : {}),\n }))\n\n/** Picker group label for samples generated by an SDK provider (Scalar, Stainless, …). */\nconst SDK_GROUP_LABEL = 'SDK'\n\n/** Picker group label for generic or docs-platform samples (the standard `x-codeSamples` family, ReadMe, …). */\nexport const CODE_EXAMPLES_GROUP_LABEL = 'Code Examples'\n\ntype CustomCodeSampleGroupLabel = typeof SDK_GROUP_LABEL | typeof CODE_EXAMPLES_GROUP_LABEL\n\ntype CustomCodeSamples = {\n /**\n * Group label for the code sample picker.\n *\n * Samples that come from an SDK provider extension (`x-scalar-examples`,\n * `x-stainless-snippets`, `x-stainless-examples`) surface under \"SDK\". Generic\n * or docs-platform samples (`x-readme`, the `x-codeSamples` family) surface\n * under \"Code Examples\".\n */\n label: CustomCodeSampleGroupLabel\n /** The custom code samples, in picker order. */\n samples: XCodeSample[]\n}\n\n/**\n * Grabs any custom code samples from the operation.\n *\n * Several tools write code samples into OpenAPI under different extensions. When\n * more than one is present we use the highest-priority source only, rather than\n * showing duplicates from every tool. Priority, highest first:\n *\n * 1. `x-scalar-examples` (SDK)\n * 2. `x-stainless-snippets` (SDK, overrides `x-stainless-examples`)\n * 3. `x-stainless-examples` (SDK)\n * 4. `x-readme.code-samples` (Code Examples)\n * 5. `x-codeSamples` / `x-code-samples` / `x-custom-examples` (Code Examples)\n *\n * The winning source also determines the picker group label: SDK-provider\n * extensions surface under \"SDK\", everything else under \"Code Examples\".\n *\n * Note that Speakeasy does not have its own extension — it writes into the\n * standard `x-codeSamples`, so its snippets surface under \"Code Examples\".\n *\n * @param operation - The operation to get the custom code samples from\n * @returns The picker group label and the custom code samples which exist in the operation\n */\nexport const getCustomCodeSamples = (operation: OperationObject): CustomCodeSamples => {\n const scalarExamples = operation['x-scalar-examples'] ?? []\n if (scalarExamples.length) {\n return { label: SDK_GROUP_LABEL, samples: scalarExamples }\n }\n\n const stainlessSnippets = fromSnippetMap(operation['x-stainless-snippets'])\n if (stainlessSnippets.length) {\n return { label: SDK_GROUP_LABEL, samples: stainlessSnippets }\n }\n\n const stainlessExamples = fromLanguageExamples(operation['x-stainless-examples'])\n if (stainlessExamples.length) {\n return { label: SDK_GROUP_LABEL, samples: stainlessExamples }\n }\n\n const readmeSamples = fromReadmeSamples(operation['x-readme']?.['code-samples'])\n if (readmeSamples.length) {\n return { label: CODE_EXAMPLES_GROUP_LABEL, samples: readmeSamples }\n }\n\n const customCodeKeys = ['x-custom-examples', 'x-codeSamples', 'x-code-samples'] as const\n return { label: CODE_EXAMPLES_GROUP_LABEL, samples: customCodeKeys.flatMap((key) => operation[key] ?? []) }\n}\n"],"mappings":";;AAQA,IAAM,kBAAkB,UAA8C,UACpE,OAAO,QAAQ,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,aAAa;CAAE;CAAM;CAAQ,GAAI,QAAQ,EAAE,OAAO,GAAG,EAAE;CAAG,EAAE;;;;;;;;AASzG,IAAM,wBAAwB,aAA+E;AAC3G,KAAI,CAAC,SACH,QAAO,EAAE;AAGX,SAAQ,MAAM,QAAQ,SAAS,GAAG,WAAW,CAAC,SAAS,EAAE,SAAS,YAChE,eAAe,QAAQ,SAAS,QAAQ,MAAM,CAC/C;;;AAIH,IAAM,qBAAqB,aACxB,WAAW,EAAE,EAAE,KAAK,YAAY;CAC/B,MAAM,OAAO;CACb,QAAQ,OAAO;CACf,GAAI,OAAO,OAAO,EAAE,OAAO,OAAO,MAAM,GAAG,EAAE;CAC9C,EAAE;;AAGL,IAAM,kBAAkB;;AAGxB,IAAa,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;AAwCzC,IAAa,wBAAwB,cAAkD;CACrF,MAAM,iBAAiB,UAAU,wBAAwB,EAAE;AAC3D,KAAI,eAAe,OACjB,QAAO;EAAE,OAAO;EAAiB,SAAS;EAAgB;CAG5D,MAAM,oBAAoB,eAAe,UAAU,wBAAwB;AAC3E,KAAI,kBAAkB,OACpB,QAAO;EAAE,OAAO;EAAiB,SAAS;EAAmB;CAG/D,MAAM,oBAAoB,qBAAqB,UAAU,wBAAwB;AACjF,KAAI,kBAAkB,OACpB,QAAO;EAAE,OAAO;EAAiB,SAAS;EAAmB;CAG/D,MAAM,gBAAgB,kBAAkB,UAAU,cAAc,gBAAgB;AAChF,KAAI,cAAc,OAChB,QAAO;EAAE,OAAO;EAA2B,SAAS;EAAe;AAIrE,QAAO;EAAE,OAAO;EAA2B,SADpB;GAAC;GAAqB;GAAiB;GAAiB,CACZ,SAAS,QAAQ,UAAU,QAAQ,EAAE,CAAC;EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"process-body.d.ts","sourceRoot":"","sources":["../../../../../../src/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,8DAA8D,CAAA;AAErE,OAAO,KAAK,EAAS,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,KAAK,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,GAAG,SAAS,GAAG,iCAAiC,CAAC,GAAG;IACjH,WAAW,EAAE,iBAAiB,CAAA;CAC/B,CAAA;AAwOD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,yEAKzB,gBAAgB,KAAG,QAAQ,GAAG,SAyFhC,CAAA"}
1
+ {"version":3,"file":"process-body.d.ts","sourceRoot":"","sources":["../../../../../../src/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,8DAA8D,CAAA;AAErE,OAAO,KAAK,EAAS,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,KAAK,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,GAAG,SAAS,GAAG,iCAAiC,CAAC,GAAG;IACjH,WAAW,EAAE,iBAAiB,CAAA;CAC/B,CAAA;AAyJD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,yEAKzB,gBAAgB,KAAG,QAAQ,GAAG,SAyFhC,CAAA"}
@@ -1,20 +1,10 @@
1
1
  import { getResolvedRefDeep } from "../get-resolved-ref-deep.js";
2
- import { getExample, getExampleFromSchema, serializeDeepObjectStyle, serializeFormStyle, serializePipeDelimitedStyle, serializeSpaceDelimitedStyle } from "@scalar/workspace-store/request-example";
2
+ import { getExample, getExampleFromSchema, serializeFormPropertyWithEncoding } from "@scalar/workspace-store/request-example";
3
3
  import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
4
4
  import { json2xml } from "@scalar/helpers/file/json2xml";
5
5
  import { unpackProxyObject } from "@scalar/workspace-store/helpers/unpack-proxy";
6
6
  //#region src/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.ts
7
7
  /**
8
- * Stringify a value emitted by `serializeFormStyle` into a HAR param value.
9
- *
10
- * Form-style serialization only addresses one level of nesting per RFC6570;
11
- * deeper structures (an object or array still sitting in `entry.value`) are
12
- * spec-undefined. JSON-stringify them so authors get readable output instead
13
- * of `String(value)` returning `"[object Object]"`. Primitives pass through
14
- * `String()` to preserve the existing wire shape (e.g. `true` → `"true"`).
15
- */
16
- var stringifyEntryValue = (value) => value !== null && typeof value === "object" ? JSON.stringify(value) : String(value);
17
- /**
18
8
  * Converts a form-data body into HAR `Param[]` entries for `multipart/form-data`
19
9
  * and `application/x-www-form-urlencoded` requests.
20
10
  *
@@ -56,83 +46,18 @@ var objectToFormParams = (obj, encoding, parentKey, isMultipart = false) => {
56
46
  */
57
47
  const explicitContentType = hasFormStyle || !isMultipart ? void 0 : partEncoding?.contentType;
58
48
  /**
59
- * Per OpenAPI 3.1.x Encoding Object: when style/explode/allowReserved is set on a
60
- * `multipart/form-data` or `application/x-www-form-urlencoded` part, the value is
61
- * serialized as if it were a query-style parameter and contentType is ignored. For
62
- * multipart the query delimiters are stripped per §Appendix C; HAR represents both
63
- * content types via `PostData.params`, so the same shape works for both.
64
- *
65
- * Primitives skip this branch and fall through to the String(value) path below since
66
- * style is a no-op for primitives. Files skip too, as do arrays containing Files —
67
- * RFC6570 expansion of binary data is undefined per §Appendix C, and the array branch
68
- * below already emits one `@filename` part per File.
69
- *
70
- * allowReserved only affects percent-encoding, which is a no-op at the HAR layer per
71
- * OAS 3.1.2 ("`allowReserved` has no effect" for multipart); its presence still opts
72
- * into this branch per spec.
49
+ * When the encoding sets style/explode/allowReserved, serialize the value RFC6570-style
50
+ * (bracket/exploded notation) and ignore contentType. See `serializeFormPropertyWithEncoding`
51
+ * for the per-style rules; it returns null for primitives, Files, and arrays of Files, which
52
+ * then fall through to the dedicated branches below. HAR represents multipart and urlencoded
53
+ * the same way via `PostData.params`, so the resulting parts work for both.
73
54
  */
74
- if (!parentKey && hasFormStyle && typeof value === "object" && value !== null && !(value instanceof File) && !(Array.isArray(value) && value.some((item) => item instanceof File))) {
75
- const unpacked = unpackProxyObject(value);
76
- /**
77
- * OAS 3.1.x Encoding Object: encoding follows query-parameter defaults — when no
78
- * `style` is set, the default is "form"; when no `explode` is set, the default is
79
- * `true` for "form" and `false` for every other style.
80
- */
81
- const style = partEncoding?.style ?? "form";
82
- const explode = partEncoding?.explode ?? style === "form";
83
- if (style === "deepObject") if (Array.isArray(unpacked)) {
84
- /**
85
- * OAS 3.1.1 marks deepObject-on-array as n/a; fall back to the form/explode:true
86
- * shape so the array still reaches the wire instead of being silently dropped.
87
- */
88
- const serialized = serializeFormStyle(unpacked, true);
89
- if (Array.isArray(serialized)) for (const entry of serialized) params.push({
90
- name: entry.key || key,
91
- value: stringifyEntryValue(entry.value)
92
- });
93
- else params.push({
94
- name: key,
95
- value: String(serialized)
96
- });
97
- } else
98
- /**
99
- * explode:false with deepObject is undefined per spec; we invoke the serializer
100
- * either way so authors get useful output instead of nothing.
101
- */
102
- for (const entry of serializeDeepObjectStyle(key, unpacked)) params.push({
103
- name: entry.key,
104
- value: String(entry.value)
105
- });
106
- else if (style === "spaceDelimited") params.push({
107
- name: key,
108
- value: String(serializeSpaceDelimitedStyle(unpacked))
109
- });
110
- else if (style === "pipeDelimited") params.push({
111
- name: key,
112
- value: String(serializePipeDelimitedStyle(unpacked))
113
- });
114
- else {
115
- const serialized = serializeFormStyle(unpacked, explode);
116
- if (Array.isArray(serialized)) for (const entry of serialized)
117
- /**
118
- * Arrays: entry.key === '' → fall back to the outer name.
119
- * Objects: entry.key is the inner property name (spec strips the outer name).
120
- *
121
- * Nested objects/arrays inside entry.value are spec-undefined (RFC6570 form-style
122
- * only addresses one level of nesting); JSON-stringify them instead of letting
123
- * String() emit "[object Object]". The escape hatch for cleaner output is
124
- * style: deepObject + explode: true.
125
- */
126
- params.push({
127
- name: entry.key || key,
128
- value: stringifyEntryValue(entry.value)
129
- });
130
- else params.push({
131
- name: key,
132
- value: String(serialized)
133
- });
134
- }
135
- } else if (value instanceof File) {
55
+ const styleParams = parentKey ? null : serializeFormPropertyWithEncoding(key, value, partEncoding);
56
+ if (styleParams) for (const param of styleParams) params.push({
57
+ name: param.key,
58
+ value: param.value
59
+ });
60
+ else if (value instanceof File) {
136
61
  /**
137
62
  * File values render as `@filename` references, the conventional cURL syntax for an
138
63
  * attached file. Picked up by snippet renderers downstream (e.g. `--form 'x=@file.png'`).
@@ -1 +1 @@
1
- {"version":3,"file":"process-body.js","names":[],"sources":["../../../../../../src/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.ts"],"sourcesContent":["import { json2xml } from '@scalar/helpers/file/json2xml'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExample,\n getExampleFromSchema,\n serializeDeepObjectStyle,\n serializeFormStyle,\n serializePipeDelimitedStyle,\n serializeSpaceDelimitedStyle,\n} from '@scalar/workspace-store/request-example'\nimport type {\n MediaTypeObject,\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { getResolvedRefDeep } from '@v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep'\nimport type { Param, PostData } from 'har-format'\n\nimport type { OperationToHarProps } from './operation-to-har'\n\ntype ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'example' | 'requestBodyCompositionSelection'> & {\n requestBody: RequestBodyObject\n}\n\ntype MultipartEncodingMap = MediaTypeObject['encoding']\n\n/**\n * Stringify a value emitted by `serializeFormStyle` into a HAR param value.\n *\n * Form-style serialization only addresses one level of nesting per RFC6570;\n * deeper structures (an object or array still sitting in `entry.value`) are\n * spec-undefined. JSON-stringify them so authors get readable output instead\n * of `String(value)` returning `\"[object Object]\"`. Primitives pass through\n * `String()` to preserve the existing wire shape (e.g. `true` → `\"true\"`).\n */\nconst stringifyEntryValue = (value: unknown): string =>\n value !== null && typeof value === 'object' ? JSON.stringify(value) : String(value)\n\n/**\n * Converts a form-data body into HAR `Param[]` entries for `multipart/form-data`\n * and `application/x-www-form-urlencoded` requests.\n *\n * Per OpenAPI 3.1.x Encoding Object, each property's serialization is governed\n * by an optional Encoding entry. When `style` / `explode` / `allowReserved` is\n * set, the value is serialized RFC6570-style and `contentType` is ignored.\n * When only `contentType` is set, the property becomes a single part with that\n * type. Otherwise spec defaults apply (object → `application/json` for multipart,\n * primitives → `text/plain`).\n *\n * @param obj - The form-data payload, either an object keyed by property name\n * or a HAR-style `{ name, value, isDisabled }[]` array.\n * @param encoding - The `encoding` map from the Media Type Object, if any.\n * Used only at the top level (`parentKey` undefined).\n * @param parentKey - When set, we are flattening a nested object inside another\n * property; encoding is ignored and keys are joined with `.` (legacy default).\n * @param isMultipart - True for `multipart/form-data`. Gates the spec defaults\n * for object/array properties that should become a single `application/json`\n * part. Urlencoded bodies skip those branches and fall through to flattening.\n */\nconst objectToFormParams = (\n obj: object | { name: string; value: unknown; isDisabled: boolean }[],\n encoding?: MultipartEncodingMap,\n parentKey?: string,\n isMultipart = false,\n): Param[] => {\n const params: Param[] = []\n\n /** Ensure we do not include disabled items */\n const entries: [string, unknown][] = Array.isArray(obj)\n ? obj.filter((item) => !item.isDisabled).map((item) => [String(item.name), item.value])\n : Object.entries(obj)\n\n for (const [key, value] of entries) {\n if (value === undefined || value === null) {\n continue\n }\n\n const partEncoding = parentKey ? undefined : encoding?.[key]\n /**\n * Per OpenAPI 3.1.1: when style, explode, or allowReserved is explicitly set on the\n * encoding entry, contentType (implicit or explicit) is ignored and the value is\n * serialized as if it were a query-style parameter.\n */\n const hasFormStyle =\n partEncoding &&\n (partEncoding.style !== undefined ||\n partEncoding.explode !== undefined ||\n partEncoding.allowReserved !== undefined)\n /**\n * Per OAS 3.1.x Encoding Object: `contentType` SHALL be ignored if the request body\n * media type is not a multipart. For `application/x-www-form-urlencoded` we still\n * honor `style`/`explode`/`allowReserved` (handled above), but a `contentType`-only\n * entry has no effect — values fall through to the dotted-key flattening default.\n */\n const explicitContentType = hasFormStyle || !isMultipart ? undefined : partEncoding?.contentType\n\n /**\n * Per OpenAPI 3.1.x Encoding Object: when style/explode/allowReserved is set on a\n * `multipart/form-data` or `application/x-www-form-urlencoded` part, the value is\n * serialized as if it were a query-style parameter and contentType is ignored. For\n * multipart the query delimiters are stripped per §Appendix C; HAR represents both\n * content types via `PostData.params`, so the same shape works for both.\n *\n * Primitives skip this branch and fall through to the String(value) path below since\n * style is a no-op for primitives. Files skip too, as do arrays containing Files —\n * RFC6570 expansion of binary data is undefined per §Appendix C, and the array branch\n * below already emits one `@filename` part per File.\n *\n * allowReserved only affects percent-encoding, which is a no-op at the HAR layer per\n * OAS 3.1.2 (\"`allowReserved` has no effect\" for multipart); its presence still opts\n * into this branch per spec.\n */\n if (\n !parentKey &&\n hasFormStyle &&\n typeof value === 'object' &&\n value !== null &&\n !(value instanceof File) &&\n !(Array.isArray(value) && value.some((item) => item instanceof File))\n ) {\n const unpacked = unpackProxyObject(value)\n /**\n * OAS 3.1.x Encoding Object: encoding follows query-parameter defaults — when no\n * `style` is set, the default is \"form\"; when no `explode` is set, the default is\n * `true` for \"form\" and `false` for every other style.\n */\n const style = partEncoding?.style ?? 'form'\n const explode = partEncoding?.explode ?? style === 'form'\n\n if (style === 'deepObject') {\n if (Array.isArray(unpacked)) {\n /**\n * OAS 3.1.1 marks deepObject-on-array as n/a; fall back to the form/explode:true\n * shape so the array still reaches the wire instead of being silently dropped.\n */\n const serialized = serializeFormStyle(unpacked, true)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n params.push({ name: entry.key || key, value: stringifyEntryValue(entry.value) })\n }\n } else {\n params.push({ name: key, value: String(serialized) })\n }\n } else {\n /**\n * explode:false with deepObject is undefined per spec; we invoke the serializer\n * either way so authors get useful output instead of nothing.\n */\n for (const entry of serializeDeepObjectStyle(key, unpacked)) {\n params.push({ name: entry.key, value: String(entry.value) })\n }\n }\n } else if (style === 'spaceDelimited') {\n params.push({ name: key, value: String(serializeSpaceDelimitedStyle(unpacked)) })\n } else if (style === 'pipeDelimited') {\n params.push({ name: key, value: String(serializePipeDelimitedStyle(unpacked)) })\n } else {\n const serialized = serializeFormStyle(unpacked, explode)\n if (Array.isArray(serialized)) {\n for (const entry of serialized) {\n /**\n * Arrays: entry.key === '' → fall back to the outer name.\n * Objects: entry.key is the inner property name (spec strips the outer name).\n *\n * Nested objects/arrays inside entry.value are spec-undefined (RFC6570 form-style\n * only addresses one level of nesting); JSON-stringify them instead of letting\n * String() emit \"[object Object]\". The escape hatch for cleaner output is\n * style: deepObject + explode: true.\n */\n params.push({ name: entry.key || key, value: stringifyEntryValue(entry.value) })\n }\n } else {\n params.push({ name: key, value: String(serialized) })\n }\n }\n } else if (value instanceof File) {\n /**\n * File values render as `@filename` references, the conventional cURL syntax for an\n * attached file. Picked up by snippet renderers downstream (e.g. `--form 'x=@file.png'`).\n */\n const file = unpackProxyObject(value)\n params.push({\n name: key,\n value: `@${file.name}`,\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n } else if (explicitContentType && typeof value === 'object') {\n /**\n * Per OAS 3.1.x Encoding Object: an explicit `encoding[key].contentType` on a\n * complex value overrides the default and emits a single part containing the value\n * JSON-stringified into that media type. Only reachable when style/explode/allowReserved\n * are unset (otherwise contentType is ignored — see the style branch above).\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: explicitContentType,\n })\n } else if (isMultipart && !parentKey && !hasFormStyle && typeof value === 'object' && !Array.isArray(value)) {\n /**\n * Per OpenAPI 3.x: a top-level multipart property whose value is an object (and not a File)\n * defaults to a single part encoded as application/json, rather than being flattened\n * into multiple parts with dotted keys.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: 'application/json',\n })\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item instanceof File) {\n const file = unpackProxyObject(item)\n params.push({ name: key, value: `@${file.name}` })\n } else if (isMultipart && !parentKey && !hasFormStyle && typeof item === 'object' && item !== null) {\n /**\n * Per OpenAPI 3.x: a top-level multipart array of complex items defaults each part\n * to application/json, instead of flattening object items into dotted keys.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(item)),\n contentType: 'application/json',\n })\n } else {\n params.push({ name: key, value: String(item) })\n }\n }\n } else if (typeof value === 'object') {\n /**\n * Legacy fallback: flatten nested objects into dotted-key parts. Reached when the\n * multipart JSON-default branches above don't apply — i.e. either inside a recursive\n * call (`parentKey` set) or on `application/x-www-form-urlencoded` bodies without an\n * explicit encoding entry. Strict OAS 3.1.x would use `style: form, explode: true` as\n * the urlencoded default (inner keys become top-level params); we keep dotted keys for\n * backwards compatibility with consumers that already parse this shape.\n */\n const nestedParams = objectToFormParams(value, undefined, key)\n\n for (const param of nestedParams) {\n params.push({ name: `${key}.${param.name}`, value: param.value })\n }\n } else {\n params.push({\n name: key,\n value: String(value),\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n }\n }\n\n return params\n}\n\n/**\n * Processes the request body and returns the processed data\n * Returns undefined if no example is found\n */\nexport const processBody = ({\n requestBody,\n contentType,\n example,\n requestBodyCompositionSelection,\n}: ProcessBodyProps): PostData | undefined => {\n const _contentType = contentType || Object.keys(requestBody.content)[0] || ''\n /** Empty when \"Other\" is selected so snippets do not inject `Content-Type: other`. */\n const harMimeType = _contentType === 'other' ? '' : _contentType\n const formatBinaryFile = (file: File) => {\n const unwrappedFile = unpackProxyObject(file)\n return `@${unwrappedFile.name || 'filename'}`\n }\n const encoding = requestBody.content[_contentType]?.encoding\n\n // Check if this is a form data content type\n const isFormData = _contentType === 'multipart/form-data' || _contentType === 'application/x-www-form-urlencoded'\n\n // Check if this is an XML content type\n const isXml = _contentType === 'application/xml'\n\n // Get the example value\n const _example = getExample(requestBody, example, contentType)?.value\n\n // Return the provided top level example\n if (typeof _example !== 'undefined') {\n const exampleValue = _example !== null && typeof _example === 'object' ? unpackProxyObject(_example) : _example\n\n if (isFormData && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(exampleValue, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(exampleValue),\n }\n }\n\n if (exampleValue instanceof File) {\n return {\n mimeType: harMimeType,\n text: formatBinaryFile(exampleValue),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof exampleValue === 'string' ? exampleValue : JSON.stringify(exampleValue),\n }\n }\n\n // Try to extract examples from the schema\n const contentSchema = getResolvedRef(requestBody.content[_contentType]?.schema)\n if (typeof contentSchema !== 'undefined') {\n const resolvedContentSchema = getResolvedRefDeep(contentSchema) as SchemaObject\n const extractedExample = getExampleFromSchema(\n resolvedContentSchema,\n {\n compositionSelection: requestBodyCompositionSelection,\n mode: 'write',\n xml: isXml,\n },\n {\n schemaPath: ['requestBody'],\n },\n )\n\n if (extractedExample !== undefined) {\n if (isFormData && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(extractedExample, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(extractedExample),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof extractedExample === 'string' ? extractedExample : JSON.stringify(extractedExample),\n }\n }\n }\n\n return undefined\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"process-body.js","names":[],"sources":["../../../../../../src/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.ts"],"sourcesContent":["import { json2xml } from '@scalar/helpers/file/json2xml'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExample,\n getExampleFromSchema,\n serializeFormPropertyWithEncoding,\n} from '@scalar/workspace-store/request-example'\nimport type {\n MediaTypeObject,\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { getResolvedRefDeep } from '@v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep'\nimport type { Param, PostData } from 'har-format'\n\nimport type { OperationToHarProps } from './operation-to-har'\n\ntype ProcessBodyProps = Pick<OperationToHarProps, 'contentType' | 'example' | 'requestBodyCompositionSelection'> & {\n requestBody: RequestBodyObject\n}\n\ntype MultipartEncodingMap = MediaTypeObject['encoding']\n\n/**\n * Converts a form-data body into HAR `Param[]` entries for `multipart/form-data`\n * and `application/x-www-form-urlencoded` requests.\n *\n * Per OpenAPI 3.1.x Encoding Object, each property's serialization is governed\n * by an optional Encoding entry. When `style` / `explode` / `allowReserved` is\n * set, the value is serialized RFC6570-style and `contentType` is ignored.\n * When only `contentType` is set, the property becomes a single part with that\n * type. Otherwise spec defaults apply (object → `application/json` for multipart,\n * primitives → `text/plain`).\n *\n * @param obj - The form-data payload, either an object keyed by property name\n * or a HAR-style `{ name, value, isDisabled }[]` array.\n * @param encoding - The `encoding` map from the Media Type Object, if any.\n * Used only at the top level (`parentKey` undefined).\n * @param parentKey - When set, we are flattening a nested object inside another\n * property; encoding is ignored and keys are joined with `.` (legacy default).\n * @param isMultipart - True for `multipart/form-data`. Gates the spec defaults\n * for object/array properties that should become a single `application/json`\n * part. Urlencoded bodies skip those branches and fall through to flattening.\n */\nconst objectToFormParams = (\n obj: object | { name: string; value: unknown; isDisabled: boolean }[],\n encoding?: MultipartEncodingMap,\n parentKey?: string,\n isMultipart = false,\n): Param[] => {\n const params: Param[] = []\n\n /** Ensure we do not include disabled items */\n const entries: [string, unknown][] = Array.isArray(obj)\n ? obj.filter((item) => !item.isDisabled).map((item) => [String(item.name), item.value])\n : Object.entries(obj)\n\n for (const [key, value] of entries) {\n if (value === undefined || value === null) {\n continue\n }\n\n const partEncoding = parentKey ? undefined : encoding?.[key]\n /**\n * Per OpenAPI 3.1.1: when style, explode, or allowReserved is explicitly set on the\n * encoding entry, contentType (implicit or explicit) is ignored and the value is\n * serialized as if it were a query-style parameter.\n */\n const hasFormStyle =\n partEncoding &&\n (partEncoding.style !== undefined ||\n partEncoding.explode !== undefined ||\n partEncoding.allowReserved !== undefined)\n /**\n * Per OAS 3.1.x Encoding Object: `contentType` SHALL be ignored if the request body\n * media type is not a multipart. For `application/x-www-form-urlencoded` we still\n * honor `style`/`explode`/`allowReserved` (handled above), but a `contentType`-only\n * entry has no effect — values fall through to the dotted-key flattening default.\n */\n const explicitContentType = hasFormStyle || !isMultipart ? undefined : partEncoding?.contentType\n\n /**\n * When the encoding sets style/explode/allowReserved, serialize the value RFC6570-style\n * (bracket/exploded notation) and ignore contentType. See `serializeFormPropertyWithEncoding`\n * for the per-style rules; it returns null for primitives, Files, and arrays of Files, which\n * then fall through to the dedicated branches below. HAR represents multipart and urlencoded\n * the same way via `PostData.params`, so the resulting parts work for both.\n */\n const styleParams = parentKey ? null : serializeFormPropertyWithEncoding(key, value, partEncoding)\n if (styleParams) {\n for (const param of styleParams) {\n params.push({ name: param.key, value: param.value })\n }\n } else if (value instanceof File) {\n /**\n * File values render as `@filename` references, the conventional cURL syntax for an\n * attached file. Picked up by snippet renderers downstream (e.g. `--form 'x=@file.png'`).\n */\n const file = unpackProxyObject(value)\n params.push({\n name: key,\n value: `@${file.name}`,\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n } else if (explicitContentType && typeof value === 'object') {\n /**\n * Per OAS 3.1.x Encoding Object: an explicit `encoding[key].contentType` on a\n * complex value overrides the default and emits a single part containing the value\n * JSON-stringified into that media type. Only reachable when style/explode/allowReserved\n * are unset (otherwise contentType is ignored — see the style branch above).\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: explicitContentType,\n })\n } else if (isMultipart && !parentKey && !hasFormStyle && typeof value === 'object' && !Array.isArray(value)) {\n /**\n * Per OpenAPI 3.x: a top-level multipart property whose value is an object (and not a File)\n * defaults to a single part encoded as application/json, rather than being flattened\n * into multiple parts with dotted keys.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(value)),\n contentType: 'application/json',\n })\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (item instanceof File) {\n const file = unpackProxyObject(item)\n params.push({ name: key, value: `@${file.name}` })\n } else if (isMultipart && !parentKey && !hasFormStyle && typeof item === 'object' && item !== null) {\n /**\n * Per OpenAPI 3.x: a top-level multipart array of complex items defaults each part\n * to application/json, instead of flattening object items into dotted keys.\n */\n params.push({\n name: key,\n value: JSON.stringify(unpackProxyObject(item)),\n contentType: 'application/json',\n })\n } else {\n params.push({ name: key, value: String(item) })\n }\n }\n } else if (typeof value === 'object') {\n /**\n * Legacy fallback: flatten nested objects into dotted-key parts. Reached when the\n * multipart JSON-default branches above don't apply — i.e. either inside a recursive\n * call (`parentKey` set) or on `application/x-www-form-urlencoded` bodies without an\n * explicit encoding entry. Strict OAS 3.1.x would use `style: form, explode: true` as\n * the urlencoded default (inner keys become top-level params); we keep dotted keys for\n * backwards compatibility with consumers that already parse this shape.\n */\n const nestedParams = objectToFormParams(value, undefined, key)\n\n for (const param of nestedParams) {\n params.push({ name: `${key}.${param.name}`, value: param.value })\n }\n } else {\n params.push({\n name: key,\n value: String(value),\n ...(explicitContentType ? { contentType: explicitContentType } : {}),\n })\n }\n }\n\n return params\n}\n\n/**\n * Processes the request body and returns the processed data\n * Returns undefined if no example is found\n */\nexport const processBody = ({\n requestBody,\n contentType,\n example,\n requestBodyCompositionSelection,\n}: ProcessBodyProps): PostData | undefined => {\n const _contentType = contentType || Object.keys(requestBody.content)[0] || ''\n /** Empty when \"Other\" is selected so snippets do not inject `Content-Type: other`. */\n const harMimeType = _contentType === 'other' ? '' : _contentType\n const formatBinaryFile = (file: File) => {\n const unwrappedFile = unpackProxyObject(file)\n return `@${unwrappedFile.name || 'filename'}`\n }\n const encoding = requestBody.content[_contentType]?.encoding\n\n // Check if this is a form data content type\n const isFormData = _contentType === 'multipart/form-data' || _contentType === 'application/x-www-form-urlencoded'\n\n // Check if this is an XML content type\n const isXml = _contentType === 'application/xml'\n\n // Get the example value\n const _example = getExample(requestBody, example, contentType)?.value\n\n // Return the provided top level example\n if (typeof _example !== 'undefined') {\n const exampleValue = _example !== null && typeof _example === 'object' ? unpackProxyObject(_example) : _example\n\n if (isFormData && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(exampleValue, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof exampleValue === 'object' && exampleValue !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(exampleValue),\n }\n }\n\n if (exampleValue instanceof File) {\n return {\n mimeType: harMimeType,\n text: formatBinaryFile(exampleValue),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof exampleValue === 'string' ? exampleValue : JSON.stringify(exampleValue),\n }\n }\n\n // Try to extract examples from the schema\n const contentSchema = getResolvedRef(requestBody.content[_contentType]?.schema)\n if (typeof contentSchema !== 'undefined') {\n const resolvedContentSchema = getResolvedRefDeep(contentSchema) as SchemaObject\n const extractedExample = getExampleFromSchema(\n resolvedContentSchema,\n {\n compositionSelection: requestBodyCompositionSelection,\n mode: 'write',\n xml: isXml,\n },\n {\n schemaPath: ['requestBody'],\n },\n )\n\n if (extractedExample !== undefined) {\n if (isFormData && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n params: objectToFormParams(extractedExample, encoding, undefined, _contentType === 'multipart/form-data'),\n }\n }\n\n if (isXml && typeof extractedExample === 'object' && extractedExample !== null) {\n return {\n mimeType: harMimeType,\n text: json2xml(extractedExample),\n }\n }\n\n return {\n mimeType: harMimeType,\n text: typeof extractedExample === 'string' ? extractedExample : JSON.stringify(extractedExample),\n }\n }\n }\n\n return undefined\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ export { default as ExamplePicker } from './components/ExamplePicker.vue.js';
2
2
  export { default as HttpMethod } from './components/HttpMethod.vue.js';
3
3
  export { default as OperationCodeSample } from './components/OperationCodeSample.vue.js';
4
4
  export { filterClientsByQuery } from './helpers/filter-clients-by-query.js';
5
- export { DEFAULT_CLIENT, findClient, isClient } from './helpers/find-client.js';
5
+ export { DEFAULT_CLIENT, type SelectedClientId, findClient, isClient, isSelectedClient } from './helpers/find-client.js';
6
6
  export { generateClientOptions } from './helpers/generate-client-options.js';
7
7
  export { getResolvedRefDeep } from './helpers/get-resolved-ref-deep.js';
8
8
  export type { ClientOption, ClientOptionGroup, CustomClientOption, CustomClientOptionGroup } from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-code-sample/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,sCAAsC,CAAA;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-code-sample/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,sCAAsC,CAAA;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACrH,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AACpE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA"}
@@ -2,7 +2,7 @@ import ExamplePicker_default from "./components/ExamplePicker.vue.js";
2
2
  import HttpMethod_default from "./components/HttpMethod.vue.js";
3
3
  import { getResolvedRefDeep } from "./helpers/get-resolved-ref-deep.js";
4
4
  import { filterClientsByQuery } from "./helpers/filter-clients-by-query.js";
5
- import { DEFAULT_CLIENT, findClient, isClient } from "./helpers/find-client.js";
5
+ import { DEFAULT_CLIENT, findClient, isClient, isSelectedClient } from "./helpers/find-client.js";
6
6
  import { generateClientOptions } from "./helpers/generate-client-options.js";
7
7
  import OperationCodeSample_default from "./components/OperationCodeSample.vue.js";
8
- export { DEFAULT_CLIENT, ExamplePicker_default as ExamplePicker, HttpMethod_default as HttpMethod, OperationCodeSample_default as OperationCodeSample, filterClientsByQuery, findClient, generateClientOptions, getResolvedRefDeep, isClient };
8
+ export { DEFAULT_CLIENT, ExamplePicker_default as ExamplePicker, HttpMethod_default as HttpMethod, OperationCodeSample_default as OperationCodeSample, filterClientsByQuery, findClient, generateClientOptions, getResolvedRefDeep, isClient, isSelectedClient };
@@ -1 +1 @@
1
- {"version":3,"file":"RequestCodeSnippet.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/request-block/components/RequestCodeSnippet.vue"],"names":[],"mappings":"AAiKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAQvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sEAAsE,CAAA;AAQpH,KAAK,WAAW,GAAG,wBAAwB,GAAG;IAAE,QAAQ,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAqS9E,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"RequestCodeSnippet.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/request-block/components/RequestCodeSnippet.vue"],"names":[],"mappings":"AAuKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAQvE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sEAAsE,CAAA;AAQpH,KAAK,WAAW,GAAG,wBAAwB,GAAG;IAAE,QAAQ,EAAE,iBAAiB,CAAA;CAAE,CAAC;AA2S9E,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"RequestCodeSnippet.vue.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestCodeSnippet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarCodeBlock } from '@scalar/components/code-block'\nimport { ScalarCombobox } from '@scalar/components/combobox'\nimport { ScalarErrorBoundary } from '@scalar/components/error-boundary'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { computed, ref, watch } from 'vue'\n\nimport {\n findClient,\n type ClientOption,\n type CustomClientOption,\n} from '@/v2/blocks/operation-code-sample'\nimport type { OperationCodeSampleProps } from '@/v2/blocks/operation-code-sample/components/OperationCodeSample.vue'\nimport { generateCodeSnippet } from '@/v2/blocks/operation-code-sample/helpers/generate-code-snippet'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport { DataTable, DataTableRow } from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n clientOptions,\n eventBus,\n operation,\n method,\n path,\n selectedContentType,\n selectedServer = null,\n selectedExample,\n securitySchemes,\n selectedClient,\n globalCookies,\n integration,\n} = defineProps<OperationCodeSampleProps & { eventBus: WorkspaceEventBus }>()\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/**\n * The locally selected client which would include code samples from this operation only\n * Must be local state because it contains custom code samples from this operation only\n */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes ?? []))\n\n/** Handle client change */\nconst handleClientChange = (option: ClientOption | undefined) => {\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() =>\n generateCodeSnippet({\n defaultDisabledParameters: true,\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExample,\n globalCookies,\n includeDefaultHeaders: integration === 'client',\n }),\n)\n\n/** Check if there are any clients available (built-in or custom code samples) */\nconst hasClients = computed(() =>\n clients.value.some((group) => group.options.length > 0),\n)\n</script>\n\n<template>\n <CollapsibleSection\n v-show=\"hasClients\"\n class=\"group/preview w-full border-t\"\n :defaultOpen=\"false\">\n <template #title>Code Snippet</template>\n\n <!-- Client selector -->\n <template #actions>\n <div class=\"flex flex-1\">\n <ScalarCombobox\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n @update:modelValue=\"\n (ev) => handleClientChange(ev as ClientOption | undefined)\n \">\n <template #default=\"{ open }\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"mt-0.25 size-3 transition-transform duration-100\"\n :class=\"open && 'rotate-180'\"\n weight=\"bold\" />\n </ScalarButton>\n </template>\n </ScalarCombobox>\n </div>\n </template>\n\n <!-- Code snippet -->\n <ScalarErrorBoundary>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableRow>\n <div class=\"overflow-hidden\">\n <ScalarCodeBlock\n class=\"text-base\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"localSelectedClient?.lang ?? 'plaintext'\"\n lineNumbers />\n </div>\n </DataTableRow>\n </DataTable>\n </ScalarErrorBoundary>\n </CollapsibleSection>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RequestCodeSnippet.vue.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestCodeSnippet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarCodeBlock } from '@scalar/components/code-block'\nimport { ScalarCombobox } from '@scalar/components/combobox'\nimport { ScalarErrorBoundary } from '@scalar/components/error-boundary'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { computed, ref, watch } from 'vue'\n\nimport {\n findClient,\n type ClientOption,\n type CustomClientOption,\n} from '@/v2/blocks/operation-code-sample'\nimport type { OperationCodeSampleProps } from '@/v2/blocks/operation-code-sample/components/OperationCodeSample.vue'\nimport { generateCodeSnippet } from '@/v2/blocks/operation-code-sample/helpers/generate-code-snippet'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport { DataTable, DataTableRow } from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n clientOptions,\n eventBus,\n operation,\n method,\n path,\n selectedContentType,\n selectedServer = null,\n selectedExample,\n securitySchemes,\n selectedClient,\n globalCookies,\n integration,\n} = defineProps<OperationCodeSampleProps & { eventBus: WorkspaceEventBus }>()\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(\n customCodeSamples.value.samples,\n clientOptions,\n customCodeSamples.value.label,\n ),\n)\n\n/**\n * The locally selected client which would include code samples from this operation only\n * Must be local state because it contains custom code samples from this operation only\n */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/**\n * Re-resolve the local client whenever the global selection or the available\n * clients change. Watching `clients` matters when navigating between operations:\n * the stored id stays the same, but the matching option (e.g. a custom sample)\n * differs per operation, so without this the snippet could go stale.\n */\nwatch([() => selectedClient, clients], ([newClient]) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes ?? []))\n\n/** Handle client change */\nconst handleClientChange = (option: ClientOption | undefined) => {\n localSelectedClient.value = option\n\n // Sync the selection globally (built-in client or custom sample keyed by language)\n if (option) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() =>\n generateCodeSnippet({\n defaultDisabledParameters: true,\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value.samples,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExample,\n globalCookies,\n includeDefaultHeaders: integration === 'client',\n }),\n)\n\n/** Check if there are any clients available (built-in or custom code samples) */\nconst hasClients = computed(() =>\n clients.value.some((group) => group.options.length > 0),\n)\n</script>\n\n<template>\n <CollapsibleSection\n v-show=\"hasClients\"\n class=\"group/preview w-full border-t\"\n :defaultOpen=\"false\">\n <template #title>Code Snippet</template>\n\n <!-- Client selector -->\n <template #actions>\n <div class=\"flex flex-1\">\n <ScalarCombobox\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n @update:modelValue=\"\n (ev) => handleClientChange(ev as ClientOption | undefined)\n \">\n <template #default=\"{ open }\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"mt-0.25 size-3 transition-transform duration-100\"\n :class=\"open && 'rotate-180'\"\n weight=\"bold\" />\n </ScalarButton>\n </template>\n </ScalarCombobox>\n </div>\n </template>\n\n <!-- Code snippet -->\n <ScalarErrorBoundary>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableRow>\n <div class=\"overflow-hidden\">\n <ScalarCodeBlock\n class=\"text-base\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"localSelectedClient?.lang ?? 'plaintext'\"\n lineNumbers />\n </div>\n </DataTableRow>\n </DataTable>\n </ScalarErrorBoundary>\n </CollapsibleSection>\n</template>\n"],"mappings":""}
@@ -1,8 +1,8 @@
1
1
  import DataTable_default from "../../../components/data-table/DataTable.vue.js";
2
2
  import DataTableRow_default from "../../../components/data-table/DataTableRow.vue.js";
3
3
  import { findClient } from "../../operation-code-sample/helpers/find-client.js";
4
- import { getClients } from "../../operation-code-sample/helpers/get-clients.js";
5
4
  import { getCustomCodeSamples } from "../../operation-code-sample/helpers/get-custom-code-samples.js";
5
+ import { getClients } from "../../operation-code-sample/helpers/get-clients.js";
6
6
  import { getSecrets } from "../../operation-code-sample/helpers/get-secrets.js";
7
7
  import { generateCodeSnippet } from "../../operation-code-sample/helpers/generate-code-snippet.js";
8
8
  import CollapsibleSection_default from "../../../components/layout/CollapsibleSection.vue.js";
@@ -39,14 +39,19 @@ var RequestCodeSnippet_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
39
39
  /** Grab any custom code samples from the operation */
40
40
  const customCodeSamples = computed(() => getCustomCodeSamples(__props.operation));
41
41
  /** Merge custom code samples with the client options */
42
- const clients = computed(() => getClients(customCodeSamples.value, __props.clientOptions));
42
+ const clients = computed(() => getClients(customCodeSamples.value.samples, __props.clientOptions, customCodeSamples.value.label));
43
43
  /**
44
44
  * The locally selected client which would include code samples from this operation only
45
45
  * Must be local state because it contains custom code samples from this operation only
46
46
  */
47
47
  const localSelectedClient = ref(findClient(clients.value, __props.selectedClient));
48
- /** If the globally selected client changes we can update the local one */
49
- watch(() => __props.selectedClient, (newClient) => {
48
+ /**
49
+ * Re-resolve the local client whenever the global selection or the available
50
+ * clients change. Watching `clients` matters when navigating between operations:
51
+ * the stored id stays the same, but the matching option (e.g. a custom sample)
52
+ * differs per operation, so without this the snippet could go stale.
53
+ */
54
+ watch([() => __props.selectedClient, clients], ([newClient]) => {
50
55
  const client = findClient(clients.value, newClient);
51
56
  if (client) localSelectedClient.value = client;
52
57
  });
@@ -55,13 +60,13 @@ var RequestCodeSnippet_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
55
60
  /** Handle client change */
56
61
  const handleClientChange = (option) => {
57
62
  localSelectedClient.value = option;
58
- if (option && !option.id.startsWith("custom")) __props.eventBus.emit("workspace:update:selected-client", option.id);
63
+ if (option) __props.eventBus.emit("workspace:update:selected-client", option.id);
59
64
  };
60
65
  /** Generate the code snippet for the selected example */
61
66
  const generatedCode = computed(() => generateCodeSnippet({
62
67
  defaultDisabledParameters: true,
63
68
  clientId: localSelectedClient.value?.id,
64
- customCodeSamples: customCodeSamples.value,
69
+ customCodeSamples: customCodeSamples.value.samples,
65
70
  operation: __props.operation,
66
71
  method: __props.method,
67
72
  path: __props.path,
@@ -1 +1 @@
1
- {"version":3,"file":"RequestCodeSnippet.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestCodeSnippet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarCodeBlock } from '@scalar/components/code-block'\nimport { ScalarCombobox } from '@scalar/components/combobox'\nimport { ScalarErrorBoundary } from '@scalar/components/error-boundary'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { computed, ref, watch } from 'vue'\n\nimport {\n findClient,\n type ClientOption,\n type CustomClientOption,\n} from '@/v2/blocks/operation-code-sample'\nimport type { OperationCodeSampleProps } from '@/v2/blocks/operation-code-sample/components/OperationCodeSample.vue'\nimport { generateCodeSnippet } from '@/v2/blocks/operation-code-sample/helpers/generate-code-snippet'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport { DataTable, DataTableRow } from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n clientOptions,\n eventBus,\n operation,\n method,\n path,\n selectedContentType,\n selectedServer = null,\n selectedExample,\n securitySchemes,\n selectedClient,\n globalCookies,\n integration,\n} = defineProps<OperationCodeSampleProps & { eventBus: WorkspaceEventBus }>()\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/**\n * The locally selected client which would include code samples from this operation only\n * Must be local state because it contains custom code samples from this operation only\n */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes ?? []))\n\n/** Handle client change */\nconst handleClientChange = (option: ClientOption | undefined) => {\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() =>\n generateCodeSnippet({\n defaultDisabledParameters: true,\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExample,\n globalCookies,\n includeDefaultHeaders: integration === 'client',\n }),\n)\n\n/** Check if there are any clients available (built-in or custom code samples) */\nconst hasClients = computed(() =>\n clients.value.some((group) => group.options.length > 0),\n)\n</script>\n\n<template>\n <CollapsibleSection\n v-show=\"hasClients\"\n class=\"group/preview w-full border-t\"\n :defaultOpen=\"false\">\n <template #title>Code Snippet</template>\n\n <!-- Client selector -->\n <template #actions>\n <div class=\"flex flex-1\">\n <ScalarCombobox\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n @update:modelValue=\"\n (ev) => handleClientChange(ev as ClientOption | undefined)\n \">\n <template #default=\"{ open }\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"mt-0.25 size-3 transition-transform duration-100\"\n :class=\"open && 'rotate-180'\"\n weight=\"bold\" />\n </ScalarButton>\n </template>\n </ScalarCombobox>\n </div>\n </template>\n\n <!-- Code snippet -->\n <ScalarErrorBoundary>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableRow>\n <div class=\"overflow-hidden\">\n <ScalarCodeBlock\n class=\"text-base\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"localSelectedClient?.lang ?? 'plaintext'\"\n lineNumbers />\n </div>\n </DataTableRow>\n </DataTable>\n </ScalarErrorBoundary>\n </CollapsibleSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsCA,MAAM,oBAAoB,eAAe,qBAAqB,QAAA,UAAU,CAAA;;EAGxE,MAAM,UAAU,eACd,WAAW,kBAAkB,OAAO,QAAA,cAAc,CACpD;;;;;EAMA,MAAM,sBAAsB,IAC1B,WAAW,QAAQ,OAAO,QAAA,eAAe,CAC3C;;AAGA,cACQ,QAAA,iBACL,cAAc;GACb,MAAM,SAAS,WAAW,QAAQ,OAAO,UAAS;AAClD,OAAI,OACF,qBAAoB,QAAQ;IAGlC;;EAGA,MAAM,oBAAoB,eAAe,WAAW,QAAA,mBAAmB,EAAE,CAAC,CAAA;;EAG1E,MAAM,sBAAsB,WAAqC;AAC/D,uBAAoB,QAAQ;AAG5B,OAAI,UAAU,CAAC,OAAO,GAAG,WAAW,SAAS,CAC3C,SAAA,SAAS,KAAK,oCAAoC,OAAO,GAAE;;;EAK/D,MAAM,gBAAgB,eACpB,oBAAoB;GAClB,2BAA2B;GAC3B,UAAU,oBAAoB,OAAO;GACrC,mBAAmB,kBAAkB;GACrC,WAAQ,QAAA;GACR,QAAK,QAAA;GACL,MAAG,QAAA;GACH,aAAa,QAAA;GACb,QAAQ,QAAA;GACR,iBAAc,QAAA;GACd,SAAS,QAAA;GACT,eAAY,QAAA;GACZ,uBAAuB,QAAA,gBAAgB;GACxC,CAAC,CACJ;;EAGA,MAAM,aAAa,eACjB,QAAQ,MAAM,MAAM,UAAU,MAAM,QAAQ,SAAS,EAAE,CACzD;;uCAIE,YAiDqB,MAAA,2BAAA,EAAA;IA/CnB,OAAM;IACL,aAAa;;IACH,OAAK,cAAa,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAZ,gBAAY,GAAA,CAAA,EAAA,CAAA;IAGlB,SAAO,cAsBV,CArBN,mBAqBM,OArBN,YAqBM,CApBJ,YAmBiB,MAAA,eAAA,EAAA;KAlBd,YAAY,oBAAA;KACZ,SAAS,QAAA;KACV,WAAU;KACT,uBAAiB,OAAA,OAAA,OAAA,MAAgB,OAAO,mBAAmB,GAAE;;KAGnD,SAAO,SAUD,EAVK,WAAI,CACxB,YASe,MAAA,aAAA,EAAA;MARb,OAAM;MACN,eAAY;MACZ,SAAQ;;6BACwB,CAAA,gBAAA,gBAA7B,oBAAA,OAAqB,MAAK,GAAG,KAChC,EAAA,EAAA,YAGkB,MAAA,oBAAA,EAAA;OAFhB,OAAK,eAAA,CAAC,oDACE,QAAI,aAAA,CAAA;OACZ,QAAO;;;;;;2BAuBG,CAftB,YAesB,MAAA,oBAAA,EAAA,MAAA;4BADR,CAbZ,YAaY,MAAA,kBAAA,EAAA;MAZT,SAAS,CAAA,GAAI;MACd,gBAAA;;6BAUe,CATf,YASe,MAAA,qBAAA,EAAA,MAAA;8BADP,CAPN,mBAOM,OAPN,YAOM,CANJ,YAKgB,MAAA,gBAAA,EAAA;QAJd,OAAM;QACL,SAAS,cAAA;QACT,iBAAiB,kBAAA;QACjB,MAAM,oBAAA,OAAqB,QAAI;QAChC,aAAA;;;;;;;;;;;;;sBA3CF,WAAA,MAAU,CAAA,CAAA"}
1
+ {"version":3,"file":"RequestCodeSnippet.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestCodeSnippet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarCodeBlock } from '@scalar/components/code-block'\nimport { ScalarCombobox } from '@scalar/components/combobox'\nimport { ScalarErrorBoundary } from '@scalar/components/error-boundary'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { computed, ref, watch } from 'vue'\n\nimport {\n findClient,\n type ClientOption,\n type CustomClientOption,\n} from '@/v2/blocks/operation-code-sample'\nimport type { OperationCodeSampleProps } from '@/v2/blocks/operation-code-sample/components/OperationCodeSample.vue'\nimport { generateCodeSnippet } from '@/v2/blocks/operation-code-sample/helpers/generate-code-snippet'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport { DataTable, DataTableRow } from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n clientOptions,\n eventBus,\n operation,\n method,\n path,\n selectedContentType,\n selectedServer = null,\n selectedExample,\n securitySchemes,\n selectedClient,\n globalCookies,\n integration,\n} = defineProps<OperationCodeSampleProps & { eventBus: WorkspaceEventBus }>()\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(\n customCodeSamples.value.samples,\n clientOptions,\n customCodeSamples.value.label,\n ),\n)\n\n/**\n * The locally selected client which would include code samples from this operation only\n * Must be local state because it contains custom code samples from this operation only\n */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/**\n * Re-resolve the local client whenever the global selection or the available\n * clients change. Watching `clients` matters when navigating between operations:\n * the stored id stays the same, but the matching option (e.g. a custom sample)\n * differs per operation, so without this the snippet could go stale.\n */\nwatch([() => selectedClient, clients], ([newClient]) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes ?? []))\n\n/** Handle client change */\nconst handleClientChange = (option: ClientOption | undefined) => {\n localSelectedClient.value = option\n\n // Sync the selection globally (built-in client or custom sample keyed by language)\n if (option) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() =>\n generateCodeSnippet({\n defaultDisabledParameters: true,\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value.samples,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExample,\n globalCookies,\n includeDefaultHeaders: integration === 'client',\n }),\n)\n\n/** Check if there are any clients available (built-in or custom code samples) */\nconst hasClients = computed(() =>\n clients.value.some((group) => group.options.length > 0),\n)\n</script>\n\n<template>\n <CollapsibleSection\n v-show=\"hasClients\"\n class=\"group/preview w-full border-t\"\n :defaultOpen=\"false\">\n <template #title>Code Snippet</template>\n\n <!-- Client selector -->\n <template #actions>\n <div class=\"flex flex-1\">\n <ScalarCombobox\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n @update:modelValue=\"\n (ev) => handleClientChange(ev as ClientOption | undefined)\n \">\n <template #default=\"{ open }\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"mt-0.25 size-3 transition-transform duration-100\"\n :class=\"open && 'rotate-180'\"\n weight=\"bold\" />\n </ScalarButton>\n </template>\n </ScalarCombobox>\n </div>\n </template>\n\n <!-- Code snippet -->\n <ScalarErrorBoundary>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableRow>\n <div class=\"overflow-hidden\">\n <ScalarCodeBlock\n class=\"text-base\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"localSelectedClient?.lang ?? 'plaintext'\"\n lineNumbers />\n </div>\n </DataTableRow>\n </DataTable>\n </ScalarErrorBoundary>\n </CollapsibleSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsCA,MAAM,oBAAoB,eAAe,qBAAqB,QAAA,UAAU,CAAA;;EAGxE,MAAM,UAAU,eACd,WACE,kBAAkB,MAAM,SACxB,QAAA,eACA,kBAAkB,MAAM,MACzB,CACH;;;;;EAMA,MAAM,sBAAsB,IAC1B,WAAW,QAAQ,OAAO,QAAA,eAAe,CAC3C;;;;;;;AAQA,QAAM,OAAO,QAAA,gBAAgB,QAAQ,GAAG,CAAC,eAAe;GACtD,MAAM,SAAS,WAAW,QAAQ,OAAO,UAAS;AAClD,OAAI,OACF,qBAAoB,QAAQ;IAE/B;;EAGD,MAAM,oBAAoB,eAAe,WAAW,QAAA,mBAAmB,EAAE,CAAC,CAAA;;EAG1E,MAAM,sBAAsB,WAAqC;AAC/D,uBAAoB,QAAQ;AAG5B,OAAI,OACF,SAAA,SAAS,KAAK,oCAAoC,OAAO,GAAE;;;EAK/D,MAAM,gBAAgB,eACpB,oBAAoB;GAClB,2BAA2B;GAC3B,UAAU,oBAAoB,OAAO;GACrC,mBAAmB,kBAAkB,MAAM;GAC3C,WAAQ,QAAA;GACR,QAAK,QAAA;GACL,MAAG,QAAA;GACH,aAAa,QAAA;GACb,QAAQ,QAAA;GACR,iBAAc,QAAA;GACd,SAAS,QAAA;GACT,eAAY,QAAA;GACZ,uBAAuB,QAAA,gBAAgB;GACxC,CAAC,CACJ;;EAGA,MAAM,aAAa,eACjB,QAAQ,MAAM,MAAM,UAAU,MAAM,QAAQ,SAAS,EAAE,CACzD;;uCAIE,YAiDqB,MAAA,2BAAA,EAAA;IA/CnB,OAAM;IACL,aAAa;;IACH,OAAK,cAAa,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAZ,gBAAY,GAAA,CAAA,EAAA,CAAA;IAGlB,SAAO,cAsBV,CArBN,mBAqBM,OArBN,YAqBM,CApBJ,YAmBiB,MAAA,eAAA,EAAA;KAlBd,YAAY,oBAAA;KACZ,SAAS,QAAA;KACV,WAAU;KACT,uBAAiB,OAAA,OAAA,OAAA,MAAgB,OAAO,mBAAmB,GAAE;;KAGnD,SAAO,SAUD,EAVK,WAAI,CACxB,YASe,MAAA,aAAA,EAAA;MARb,OAAM;MACN,eAAY;MACZ,SAAQ;;6BACwB,CAAA,gBAAA,gBAA7B,oBAAA,OAAqB,MAAK,GAAG,KAChC,EAAA,EAAA,YAGkB,MAAA,oBAAA,EAAA;OAFhB,OAAK,eAAA,CAAC,oDACE,QAAI,aAAA,CAAA;OACZ,QAAO;;;;;;2BAuBG,CAftB,YAesB,MAAA,oBAAA,EAAA,MAAA;4BADR,CAbZ,YAaY,MAAA,kBAAA,EAAA;MAZT,SAAS,CAAA,GAAI;MACd,gBAAA;;6BAUe,CATf,YASe,MAAA,qBAAA,EAAA,MAAA;8BADP,CAPN,mBAOM,OAPN,YAOM,CANJ,YAKgB,MAAA,gBAAA,EAAA;QAJd,OAAM;QACL,SAAS,cAAA;QACT,iBAAiB,kBAAA;QACjB,MAAM,oBAAA,OAAqB,QAAI;QAChC,aAAA;;;;;;;;;;;;;sBA3CF,WAAA,MAAU,CAAA,CAAA"}