Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions src/components/APIRequest.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ const props = z
method: z.enum(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH"]),
parameters: z.record(z.string(), z.any()).optional(),
json: z.record(z.string(), z.any()).optional(),
form: z.record(z.string(), z.any()).optional(),
})
.strict();

let { path, method, parameters, json } = props.parse(Astro.props);
let { path, method, parameters, json, form } = props.parse(Astro.props);

if (json && form) {
throw new Error(`[APIRequest] Cannot use both "json" and "form" properties.`);
}

const schema = await getSchema();

Expand Down Expand Up @@ -52,7 +57,7 @@ const extraneousParameters = providedParameters.filter(

if (extraneousParameters.length > 0) {
throw new Error(
`[APIRequest] Provided parameters ${extraneousParameters.join(", ")} not found in schema.`,
`[APIRequest] Provided parameters ${extraneousParameters.join(", ")} not found in ${method} ${path} schema.`,
);
}

Expand Down Expand Up @@ -101,21 +106,17 @@ const jsonSchema = requestBody?.content?.["application/json"]?.schema as
| undefined;

if (jsonSchema?.required) {
json ??= {};

const providedProperties = Object.keys(json);
const providedProperties = Object.keys(json ?? {});
const requiredProperties = jsonSchema.required;

const missingProperties = requiredProperties.filter(
(property) => !providedProperties.includes(property),
);

for (const property of missingProperties) {
const defaultValue =
(jsonSchema.properties?.[property] as OpenAPIV3.SchemaObject).default ??
property;

json[property] = defaultValue;
if (missingProperties.length > 0) {
throw new Error(
`[APIRequest] Missing the following required properties for ${method} ${path}: ${missingProperties.join(", ")}`,
);
}
}

Expand Down Expand Up @@ -144,6 +145,7 @@ const tokenGroups = operation["x-api-token-group"];
method={method}
headers={headers}
json={json}
form={form}
code={{
title: operation.summary,
}}
Expand Down
14 changes: 13 additions & 1 deletion src/components/CURL.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ const props = z.object({
url: z.string().url(),
headers: z.record(z.string(), z.string()).default({}),
json: z.record(z.string(), z.any()).optional(),
form: z.record(z.string(), z.any()).optional(),
code: z
.custom<Omit<ComponentProps<typeof Code>, "code" | "lang">>()
.optional(),
});

const { method, url, headers, json, code } = props.parse(Astro.props);
const { method, url, headers, json, form, code } = props.parse(Astro.props);

if (json && form) {
throw new Error("[CURL] Cannot use both 'json' and 'form' properties.");
}

const lines = [`curl ${url}`, `\t--request ${method}`];

Expand All @@ -33,6 +38,13 @@ if (json) {

lines.push(`\t--json '${jsonLines.join("\n")}'`);
}

if (form) {
const formLines = Object.entries(form).map(
([key, value]) => `\t--form "${key}=${value}"`,
);
lines.push(...formLines);
}
---

<Code {...code} lang="bash" code={lines.join(" \\\n")} />
19 changes: 18 additions & 1 deletion src/content/docs/style-guide/components/api-request.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ import { APIRequest } from "~/components";
setting_id: "ciphers",
}}
/>

<APIRequest
path="/accounts/{account_id}/images/v2/direct_upload"
method="POST"
form={{
requireSignedURLs: true,
metadata: '{"key":"value"}'
}}
/>
```

## `<APIRequest>` Props
Expand Down Expand Up @@ -64,4 +73,12 @@ If not provided, the component will default to an environment variable. For exam

The JSON payload to send.

Default values can be omitted, and the component will use default values for any missing fields.
If required properties are missing, the component will throw an error.

### `form`

**type:** `Record<string, any>`

The FormData payload to send.

This field is not currently validated against the schema.
19 changes: 18 additions & 1 deletion src/content/docs/style-guide/components/curl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { CURL } from "~/components";
import { CURL } from "~/components";

<CURL
url="https://example.com"
url="https://httpbin.org/anything"
method="POST"
json={{
key: "value",
Expand All @@ -25,6 +25,17 @@ import { CURL } from "~/components";
mark: "value"
}}
/>

<CURL
url="https://httpbin.org/anything"
method="POST"
form={{
key: "value",
}}
code={{
mark: "value"
}}
/>
```

## `<CURL>` Props
Expand Down Expand Up @@ -57,6 +68,12 @@ The headers to include in the request.

JSON data to include in the request.

### `form`

**type:** `Record<string, any>`

The FormData payload to send.

### `code`

**type:** `object`
Expand Down