diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 940073d2fc..53fc713230 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -190,18 +190,22 @@ Content lives in the following locations:
### Overview
-The API reference documentation at [docs.apify.com](https://docs.apify.com/) is built directly from our OpenAPI specification. The source of truth for the API specification lives in the `/apify-api/openapi` directory within [apify-docs](https://github.com/apify/apify-docs) repository.
+The API reference documentation at [docs.apify.com/api/v2](https://docs.apify.com/api/v2) is built from our OpenAPI specification. The source of truth lives in the `/apify-api/openapi` directory.
-### Setup requirements
+### Tooling
-1. Install Node.js
-2. Clone the repository
-3. Run `npm install`
+We use the following tools for API documentation:
+
+- **[OpenAPI 3.0](https://spec.openapis.org/oas/v3.0.3)** - API specification format
+- **[Redocly CLI](https://redocly.com/docs/cli/)** - Linting and validation of OpenAPI specs
+- **[`docusaurus-plugin-openapi-docs`](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs)** - Generates MDX docs from OpenAPI
+- **[`docusaurus-theme-openapi-docs`](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs)** - Renders API reference with interactive explorer
### Basic commands
- `npm start` - Starts docs preview server including API reference
-- `npm test` - Validates the definition
+- `npm run openapi:lint:redocly` - Validates OpenAPI spec with Redocly CLI
+- `npm run api:rebuild` - Regenerates API docs from OpenAPI specs
### Adding new documentation
diff --git a/apify-api/openapi/components/schemas/actor-runs/Metamorph.yaml b/apify-api/openapi/components/schemas/actor-runs/Metamorph.yaml
new file mode 100644
index 0000000000..6f5e887c9a
--- /dev/null
+++ b/apify-api/openapi/components/schemas/actor-runs/Metamorph.yaml
@@ -0,0 +1,25 @@
+title: Metamorph
+description: Information about a metamorph event that occurred during the run.
+type: object
+required:
+ - createdAt
+ - actorId
+ - buildId
+properties:
+ createdAt:
+ type: string
+ format: date-time
+ description: Time when the metamorph occurred.
+ examples: ["2019-11-30T07:39:24.202Z"]
+ actorId:
+ type: string
+ description: ID of the Actor that the run was metamorphed to.
+ examples: [nspoEjklmnsF2oosD]
+ buildId:
+ type: string
+ description: ID of the build used for the metamorphed Actor.
+ examples: [ME6oKecqy5kXDS4KQ]
+ inputKey:
+ type: [string, "null"]
+ description: Key of the input record in the key-value store.
+ examples: [INPUT-METAMORPH-1]
diff --git a/apify-api/openapi/components/schemas/actor-runs/Run.yaml b/apify-api/openapi/components/schemas/actor-runs/Run.yaml
index 017df74365..9b3c8fc65f 100644
--- a/apify-api/openapi/components/schemas/actor-runs/Run.yaml
+++ b/apify-api/openapi/components/schemas/actor-runs/Run.yaml
@@ -128,3 +128,10 @@ properties:
anyOf:
- $ref: ./RunUsageUsd.yaml
- type: "null"
+ metamorphs:
+ description: List of metamorph events that occurred during the run.
+ anyOf:
+ - type: array
+ items:
+ $ref: ./Metamorph.yaml
+ - type: "null"
diff --git a/apify-api/openapi/components/schemas/actor-runs/RunMeta.yaml b/apify-api/openapi/components/schemas/actor-runs/RunMeta.yaml
index 5114049965..a23f070d65 100644
--- a/apify-api/openapi/components/schemas/actor-runs/RunMeta.yaml
+++ b/apify-api/openapi/components/schemas/actor-runs/RunMeta.yaml
@@ -5,3 +5,16 @@ type: object
properties:
origin:
$ref: ./RunOrigin.yaml
+ clientIp:
+ type: [string, "null"]
+ description: IP address of the client that started the run.
+ userAgent:
+ type: [string, "null"]
+ description: User agent of the client that started the run.
+ scheduleId:
+ type: [string, "null"]
+ description: ID of the schedule that triggered the run.
+ scheduledAt:
+ type: [string, "null"]
+ format: date-time
+ description: Time when the run was scheduled.
diff --git a/apify-api/openapi/components/schemas/actors/CreateOrUpdateVersionRequest.yaml b/apify-api/openapi/components/schemas/actors/CreateOrUpdateVersionRequest.yaml
index df03340e27..820bf52b78 100644
--- a/apify-api/openapi/components/schemas/actors/CreateOrUpdateVersionRequest.yaml
+++ b/apify-api/openapi/components/schemas/actors/CreateOrUpdateVersionRequest.yaml
@@ -21,3 +21,12 @@ properties:
examples: [latest]
sourceFiles:
$ref: ./VersionSourceFiles.yaml
+ gitRepoUrl:
+ type: [string, "null"]
+ description: URL of the Git repository when sourceType is GIT_REPO.
+ tarballUrl:
+ type: [string, "null"]
+ description: URL of the tarball when sourceType is TARBALL.
+ gitHubGistUrl:
+ type: [string, "null"]
+ description: URL of the GitHub Gist when sourceType is GITHUB_GIST.
diff --git a/apify-api/openapi/components/schemas/actors/Version.yaml b/apify-api/openapi/components/schemas/actors/Version.yaml
index 6012a52a1c..ba6044cdc9 100644
--- a/apify-api/openapi/components/schemas/actors/Version.yaml
+++ b/apify-api/openapi/components/schemas/actors/Version.yaml
@@ -24,3 +24,12 @@ properties:
examples: [latest]
sourceFiles:
$ref: ./VersionSourceFiles.yaml
+ gitRepoUrl:
+ type: [string, "null"]
+ description: URL of the Git repository when sourceType is GIT_REPO.
+ tarballUrl:
+ type: [string, "null"]
+ description: URL of the tarball when sourceType is TARBALL.
+ gitHubGistUrl:
+ type: [string, "null"]
+ description: URL of the GitHub Gist when sourceType is GITHUB_GIST.
diff --git a/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationError.yaml b/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationError.yaml
index ab2bba21b1..a0cc7ff389 100644
--- a/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationError.yaml
+++ b/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationError.yaml
@@ -1,5 +1,13 @@
title: DatasetSchemaValidationError
type: object
properties:
- error:
- $ref: ./DatasetSchemaValidationErrorDetails.yaml
+ type:
+ type: string
+ description: The type of the error.
+ examples: [schema-validation-error]
+ message:
+ type: string
+ description: A human-readable message describing the error.
+ examples: [Schema validation failed]
+ data:
+ $ref: ./SchemaValidationErrorData.yaml
diff --git a/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationErrorDetails.yaml b/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationErrorDetails.yaml
deleted file mode 100644
index d130a0bd70..0000000000
--- a/apify-api/openapi/components/schemas/datasets/DatasetSchemaValidationErrorDetails.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-title: DatasetSchemaValidationErrorDetails
-required:
- - type
- - message
- - data
-type: object
-properties:
- type:
- type: string
- description: The type of the error.
- examples: [schema-validation-error]
- message:
- type: string
- description: A human-readable message describing the error.
- examples: [Schema validation failed]
- data:
- $ref: ./SchemaValidationErrorData.yaml
diff --git a/apify-api/openapi/components/schemas/request-queues/RequestDraft.yaml b/apify-api/openapi/components/schemas/request-queues/RequestDraft.yaml
index 936899728e..1ee0890a12 100644
--- a/apify-api/openapi/components/schemas/request-queues/RequestDraft.yaml
+++ b/apify-api/openapi/components/schemas/request-queues/RequestDraft.yaml
@@ -6,6 +6,10 @@ required:
- method
type: object
properties:
+ id:
+ type: string
+ description: A unique identifier assigned to the request.
+ examples: [sbJ7klsdf7ujN9l]
uniqueKey:
type: string
description: A unique key used for request de-duplication. Requests with the same unique key are considered identical.
diff --git a/apify-api/openapi/components/schemas/store/StoreListActor.yaml b/apify-api/openapi/components/schemas/store/StoreListActor.yaml
index be762bc69f..33c930c091 100644
--- a/apify-api/openapi/components/schemas/store/StoreListActor.yaml
+++ b/apify-api/openapi/components/schemas/store/StoreListActor.yaml
@@ -53,3 +53,6 @@ properties:
$ref: ../actors/ActorStats.yaml
currentPricingInfo:
$ref: ./CurrentPricingInfo.yaml
+ isWhiteListedForAgenticPayment:
+ type: [boolean, "null"]
+ description: Whether the Actor is whitelisted for agentic payment processing.
diff --git a/apify-api/plugins/apify.mjs b/apify-api/plugins/apify.mjs
index ac5abcee7b..5af7ce84c0 100644
--- a/apify-api/plugins/apify.mjs
+++ b/apify-api/plugins/apify.mjs
@@ -1,4 +1,3 @@
-import ClientReferencesLinksDecorator from './decorators/client-references-links-decorator.mjs';
import CodeSamplesDecorator from './decorators/code-samples-decorator.mjs';
import LegacyDocUrlDecorator from './decorators/legacy-doc-url-decorator.mjs';
@@ -7,7 +6,6 @@ export default () => ({
decorators: {
oas3: {
'legacy-doc-url-decorator': LegacyDocUrlDecorator,
- 'client-references-links-decorator': ClientReferencesLinksDecorator,
'code-samples-decorator': CodeSamplesDecorator,
},
},
diff --git a/apify-api/plugins/decorators/client-references-links-decorator.mjs b/apify-api/plugins/decorators/client-references-links-decorator.mjs
deleted file mode 100644
index 888f841aa6..0000000000
--- a/apify-api/plugins/decorators/client-references-links-decorator.mjs
+++ /dev/null
@@ -1,75 +0,0 @@
-const X_PY_DOC_URLS_PROPERTY = 'x-py-doc-url';
-const X_JS_DOC_URLS_PROPERTY = 'x-js-doc-url';
-
-/**
- * This decorator adds links to the Apify API Client libraries Python and JS references.
- *
- * The Apify API OpenAPI specification has been enriched with Apify specific vendor extensions
- * on `operation` and `tag` level to link the Apify Client functionality e.g. for `actorBuild_get`:
- * ```
- * x-js-parent: BuildClient
- * x-js-name: get
- * x-js-doc-url: https://docs.apify.com/api/client/js/reference/class/BuildClient#get
- * x-py-parent: BuildClientAsync
- * x-py-name: get
- * x-py-doc-url: https://docs.apify.com/api/client/python/reference/class/BuildClientAsync#get
- * ```
- *
- * The prepended HTML example:
- * ```
- *
- *
- * Python doc
- *
- * |
- *
- * JS doc
- *
- *
- *
- * TODO: The HTML/CSS above will be subject of further design development, placeholder for now.
- * ```
- */
-function ClientReferencesLinksDecorator(target) {
- const pyLink = target[X_PY_DOC_URLS_PROPERTY];
- const jsLink = target[X_JS_DOC_URLS_PROPERTY];
-
- const jsImgUrl = '/img/javascript-40x40.svg';
- const pyImgUrl = '/img/python-40x40.svg';
-
- const jsAlt = 'Apify API JavaScript Client Reference';
- const pyAlt = 'Apify API Python Client Reference';
-
- // Purposely using `span` element here instead of `div`
- // Due to how redoc works, when `div` used, the markdown rendering in of `description` ceased to work.
- let prepend = ``;
-
- if (pyLink || jsLink) {
- prepend += `Clients`;
- }
-
- if (pyLink) {
- prepend += `
-
Python`;
- }
-
- if (jsLink) {
- prepend += `
-
JavaScript`;
- }
-
- prepend += ``;
-
- target.description = `${prepend}${target.description || ''}`;
-}
-
-export default () => ({
- // Redocly is using a visitor pattern. What the following code does is that whenever the traverser leaves a node of
- // type Tag or Operation, it executes prependLegacyUrlAnchor on it.
- Tag: {
- leave: ClientReferencesLinksDecorator,
- },
- Operation: {
- leave: ClientReferencesLinksDecorator,
- },
-});
diff --git a/apify-docs-theme/src/roa-loader/index.js b/apify-docs-theme/src/roa-loader/index.js
index a57b1dc37b..9ab5557b10 100644
--- a/apify-docs-theme/src/roa-loader/index.js
+++ b/apify-docs-theme/src/roa-loader/index.js
@@ -3,11 +3,13 @@ const { inspect } = require('node:util');
const { urlToRequest } = require('loader-utils');
+const SIGNING_TOKEN = process.env.APIFY_SIGNING_TOKEN;
const signingUrl = new URL('https://api.apify.com/v2/tools/encode-and-sign');
-signingUrl.searchParams.set('token', process.env.APIFY_SIGNING_TOKEN);
+signingUrl.searchParams.set('token', SIGNING_TOKEN || '');
const queue = [];
const cache = {};
let working = false;
+let warnedAboutMissingToken = false;
function hash(source) {
return createHash('sha1').update(source).digest('hex');
@@ -80,6 +82,15 @@ module.exports = async function (code) {
return { code, hash: 'fast' };
}
+ // Skip signing if token is not configured
+ if (!SIGNING_TOKEN) {
+ if (!warnedAboutMissingToken) {
+ console.warn('APIFY_SIGNING_TOKEN is not set, skipping code signing for runnable examples.');
+ warnedAboutMissingToken = true;
+ }
+ return { code, hash: 'unsigned' };
+ }
+
console.log(`Signing ${urlToRequest(this.resourcePath)}...`, { working, queue: queue.length });
const codeHash = await encodeAndSign(code);
diff --git a/apify-docs-theme/src/theme/custom.css b/apify-docs-theme/src/theme/custom.css
index b8dfb2933a..ff3efeaa5f 100644
--- a/apify-docs-theme/src/theme/custom.css
+++ b/apify-docs-theme/src/theme/custom.css
@@ -1785,56 +1785,70 @@ iframe[src*="youtube"] {
.theme-api-markdown .openapi-clients-box {
display: block;
float: right;
- padding-left: 12px;
- padding-right: 6px;
+ margin-top: 16px;
+ margin-left: 16px;
+ margin-bottom: 12px;
+ padding: 10px 16px;
+ min-width: 140px;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-toc-border-color);
+ border-radius: 8px;
}
-.client-docs-link img {
- border: 1px solid var(--color-neutral-action-secondary);
- border-radius: 8px;
+.theme-api-markdown .openapi-clients-box-heading {
+ display: block;
+ font-size: 11px;
+ font-weight: 600;
+ letter-spacing: 0.5px;
+ text-transform: uppercase;
+ color: var(--ifm-color-emphasis-600);
+ margin-bottom: 4px;
}
.client-docs-link {
display: flex;
flex-direction: row;
align-items: center;
- justify-content: left;
- gap: 8px;
- padding: 4px 8px 8px 0px;
+ gap: 6px;
+ padding: 2px 0;
+ text-decoration: none;
+ transition: opacity 0.15s ease;
}
-a.client-docs-link {
- font-weight: 500;
- color: var(--color-neutral-text-muted);
+.client-docs-link:hover {
+ opacity: 0.8;
+ text-decoration: none;
}
-.theme-admonition {
- clear: right;
+a.client-docs-link {
+ font-size: 13px;
+ font-weight: 500;
+ color: var(--ifm-color-emphasis-800);
}
-.theme-api-markdown .openapi-clients-box-heading {
- display: inline-block;
- font-family: 'San Francisco', Helvetica, Arial, sans-serif;
- color: var(--color-neutral-text-muted);
- font-style: normal;
- font-weight: 700;
- font-size: 14px;
- line-height: 20px;
- text-transform: uppercase;
- padding-bottom: 6px;
+.client-docs-link img {
+ border-radius: 4px;
}
.theme-api-markdown .openapi-clients-box-icon {
display: block;
- padding: 2px;
margin: 0 !important;
}
+.theme-admonition {
+ clear: right;
+}
+
.theme-api-markdown .openapi__method-endpoint-path,
.theme-api-markdown .openapi-security__summary-header {
margin-top: 0;
}
+.theme-api-markdown .openapi-explorer__details-summary:before {
+ width: 1.6rem;
+ height: 1.6rem;
+}
+
.theme-api-markdown .prism-code .token-line::before {
display: none !important;
}
diff --git a/docusaurus.config.js b/docusaurus.config.js
index 22309f94de..3c389633c0 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -2,7 +2,7 @@ const { join, resolve } = require('node:path');
const { parse } = require('node:url');
const clsx = require('clsx');
-const { createApiPageMD, createInfoPageMD } = require('docusaurus-plugin-openapi-docs/lib/markdown');
+const { createApiPageMD } = require('docusaurus-plugin-openapi-docs/lib/markdown');
const { config } = require('./apify-docs-theme');
const { collectSlugs } = require('./tools/utils/collectSlugs');
@@ -77,8 +77,6 @@ module.exports = {
onBrokenLinks:
/** @type {import('@docusaurus/types').ReportingSeverity} */ ('throw'),
- onBrokenMarkdownLinks:
- /** @type {import('@docusaurus/types').ReportingSeverity} */ ('throw'),
onBrokenAnchors:
/** @type {import('@docusaurus/types').ReportingSeverity} */ ('warn'),
themes: [
@@ -202,21 +200,6 @@ module.exports = {
md = md.replace('-->', '-->');
}
- // Find the first Heading h1 and add LLMButtons after it
- // eslint-disable-next-line max-len
- const headingRegex = /(]*as=\{"h1"\}[^>]*className=\{"openapi__heading"\}[^>]*children=\{[^}]*\}[^>]*>\s*<\/Heading>)/;
- md = md.replace(headingRegex, '$1\n\n\n');
-
- return md;
- },
- createInfoPageMD: (pageData) => {
- let md = createInfoPageMD(pageData);
-
- // Find the first Heading h1 and add LLMButtons after it
- // eslint-disable-next-line max-len
- const headingRegex = /(]*as=\{"h1"\}[^>]*className=\{"openapi__heading"\}[^>]*children=\{[^}]*\}[^>]*>\s*<\/Heading>)/;
- md = md.replace(headingRegex, '$1\n\n\n');
-
return md;
},
},
@@ -379,6 +362,10 @@ module.exports = {
],
markdown: {
mermaid: true,
+ hooks: {
+ onBrokenMarkdownLinks:
+ /** @type {import('@docusaurus/types').ReportingSeverity} */ ('throw'),
+ },
parseFrontMatter: async (params) => {
const result = await params.defaultParseFrontMatter(params);
diff --git a/package-lock.json b/package-lock.json
index 2befe27290..46e641c35e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8531,21 +8531,20 @@
}
},
"node_modules/@redocly/cli": {
- "version": "2.14.5",
- "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-2.14.5.tgz",
- "integrity": "sha512-02Zz7YS7UwfBpbHbF64ApUkspr8Ar2XytgZ7JUljVwz+VjzCRcxkGMGE82BVYYQNKkw/YwlNOIX+lYYNbowTcw==",
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-2.15.0.tgz",
+ "integrity": "sha512-PjqCE1HDSHgHOrNxixeJSrumy8an2O4rcjXCIfdiHAjB1HOlMEtdgrz5OCx9f0lzcOXrgi61ThFNvO5jG56tUw==",
"license": "MIT",
"dependencies": {
"@opentelemetry/exporter-trace-otlp-http": "0.202.0",
"@opentelemetry/resources": "2.0.1",
"@opentelemetry/sdk-trace-node": "2.0.1",
"@opentelemetry/semantic-conventions": "1.34.0",
- "@redocly/openapi-core": "2.14.5",
- "@redocly/respect-core": "2.14.5",
+ "@redocly/openapi-core": "2.15.0",
+ "@redocly/respect-core": "2.15.0",
"abort-controller": "^3.0.0",
"ajv": "npm:@redocly/ajv@8.17.1",
"ajv-formats": "^3.0.1",
- "chokidar": "^3.5.1",
"colorette": "^1.2.0",
"cookie": "^0.7.2",
"dotenv": "16.4.7",
@@ -8562,7 +8561,7 @@
"simple-websocket": "^9.0.0",
"styled-components": "^6.0.7",
"ulid": "^3.0.1",
- "undici": "^6.21.3",
+ "undici": "^6.23.0",
"yargs": "17.0.1"
},
"bin": {
@@ -8584,14 +8583,14 @@
}
},
"node_modules/@redocly/openapi-core": {
- "version": "2.14.5",
- "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-2.14.5.tgz",
- "integrity": "sha512-MQQR+RCG0V+jZV6msgKv1CNi/+TZUXmjMAAuTEktaTOYIsQWTCV9GYSD/2n94eMDZwxI4olr05OPzOZo9z0EMg==",
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-2.15.0.tgz",
+ "integrity": "sha512-q/2UM5tA9mgk4zaIDUkKOG9KBUqIdSIhp5DugHmFOszOE+WMiL23BIV40K79jNF9aSU3zF1p1c/Zu0UoBmBsZg==",
"license": "MIT",
"dependencies": {
- "@redocly/ajv": "^8.17.1",
+ "@redocly/ajv": "^8.17.2",
"@redocly/config": "^0.41.2",
- "ajv": "npm:@redocly/ajv@8.17.1",
+ "ajv": "npm:@redocly/ajv@8.17.2",
"ajv-formats": "^3.0.1",
"colorette": "^1.2.0",
"js-levenshtein": "^1.1.6",
@@ -8605,16 +8604,49 @@
"npm": ">=10"
}
},
+ "node_modules/@redocly/openapi-core/node_modules/@redocly/ajv": {
+ "version": "8.17.2",
+ "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.17.2.tgz",
+ "integrity": "sha512-rcbDZOfXAgGEJeJ30aWCVVJvxV9ooevb/m1/SFblO2qHs4cqTk178gx7T/vdslf57EA4lTofrwsq5K8rxK9g+g==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@redocly/openapi-core/node_modules/ajv": {
+ "name": "@redocly/ajv",
+ "version": "8.17.2",
+ "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.17.2.tgz",
+ "integrity": "sha512-rcbDZOfXAgGEJeJ30aWCVVJvxV9ooevb/m1/SFblO2qHs4cqTk178gx7T/vdslf57EA4lTofrwsq5K8rxK9g+g==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
"node_modules/@redocly/respect-core": {
- "version": "2.14.5",
- "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-2.14.5.tgz",
- "integrity": "sha512-zZKYwBZYfRi4/Iv2V7hq9xOYhpO3+IuzYjk8/V0CZjoHCnoW8jgGGhvoXMn/BfedZS9/3fV9n4SEskIbmCPl8Q==",
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-2.15.0.tgz",
+ "integrity": "sha512-0LFtQXNUE+e9OdGDLS+yt4RBx0JTGhM7UAaBC4tzLqPvhtbdWo/WB/WdasGIt4vMM9K47KivxPHmX13sSLEO2Q==",
"license": "MIT",
"dependencies": {
"@faker-js/faker": "^7.6.0",
"@noble/hashes": "^1.8.0",
"@redocly/ajv": "8.17.1",
- "@redocly/openapi-core": "2.14.5",
+ "@redocly/openapi-core": "2.15.0",
"ajv": "npm:@redocly/ajv@8.17.1",
"better-ajv-errors": "^1.2.0",
"colorette": "^2.0.20",
@@ -15156,9 +15188,9 @@
}
},
"node_modules/docusaurus-plugin-openapi-docs": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-4.6.0.tgz",
- "integrity": "sha512-wcRUnZca9hRiuAcw2Iz+YUVO4dh01mV2FoAtomRMVlWZIEgw6TA5SqsfHWRd6on/ibvvVS9Lq6GjZTcSjwLcWQ==",
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-4.7.1.tgz",
+ "integrity": "sha512-RpqvTEnhIfdSuTn/Fa/8bmxeufijLL9HCRb//ELD33AKqEbCw147SKR/CqWu4H4gwi50FZLUbiHKZJbPtXLt9Q==",
"license": "MIT",
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^11.5.4",
@@ -15236,9 +15268,9 @@
}
},
"node_modules/docusaurus-theme-openapi-docs": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-4.6.0.tgz",
- "integrity": "sha512-YCgYReVMcrKDTNvM4dh9+i+ies+sGbCwv12TRCPZZbeif7RqTc/5w4rhxEIfp/v0uOAQGL4iXfTSBAMExotbMQ==",
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-4.7.1.tgz",
+ "integrity": "sha512-OPydf11LoEY3fdxaoqCVO+qCk7LBo6l6s28UvHJ5mIN/2xu+dOOio9+xnKZ5FIPOlD+dx0gVSKzaVCi/UFTxlg==",
"license": "MIT",
"dependencies": {
"@hookform/error-message": "^2.0.1",
diff --git a/package.json b/package.json
index 55a9138ef2..ef94d495d2 100644
--- a/package.json
+++ b/package.json
@@ -25,8 +25,8 @@
"openapi:preview": "redocly preview-docs",
"openapi:bundle": "redocly bundle apify-api/openapi/openapi.yaml -o apify-api",
"openapi:build": "npm run openapi:build:yaml && npm run openapi:build:json",
- "openapi:build:yaml": "redocly bundle apify-api/openapi/openapi.yaml --skip-decorator=apify/legacy-doc-url-decorator --skip-decorator=apify/client-references-links-decorator --skip-decorator=apify/code-samples-decorator -o static/api/openapi.yaml",
- "openapi:build:json": "redocly bundle apify-api/openapi/openapi.yaml --skip-decorator=apify/legacy-doc-url-decorator --skip-decorator=apify/client-references-links-decorator --skip-decorator=apify/code-samples-decorator -o static/api/openapi.json",
+ "openapi:build:yaml": "redocly bundle apify-api/openapi/openapi.yaml --skip-decorator=apify/legacy-doc-url-decorator --skip-decorator=apify/code-samples-decorator -o static/api/openapi.yaml",
+ "openapi:build:json": "redocly bundle apify-api/openapi/openapi.yaml --skip-decorator=apify/legacy-doc-url-decorator --skip-decorator=apify/code-samples-decorator -o static/api/openapi.json",
"openapi:lint": "npm run openapi:lint:redocly && npm run openapi:lint:spectral && npm run openapi:lint:yaml",
"openapi:lint:redocly": "redocly lint apify-api/openapi/openapi.yaml",
"openapi:lint:spectral": "spectral lint apify-api/openapi/openapi.yaml",
diff --git a/patches/docusaurus-plugin-openapi-docs+4.6.0.patch b/patches/docusaurus-plugin-openapi-docs+4.7.1.patch
similarity index 91%
rename from patches/docusaurus-plugin-openapi-docs+4.6.0.patch
rename to patches/docusaurus-plugin-openapi-docs+4.7.1.patch
index 42697f1ae7..7709531125 100644
--- a/patches/docusaurus-plugin-openapi-docs+4.6.0.patch
+++ b/patches/docusaurus-plugin-openapi-docs+4.7.1.patch
@@ -1,17 +1,15 @@
diff --git a/node_modules/docusaurus-plugin-openapi-docs/lib/sidebars/index.js b/node_modules/docusaurus-plugin-openapi-docs/lib/sidebars/index.js
-index 6f97824..075b91e 100644
+index 6f97824..7ff251a 100644
--- a/node_modules/docusaurus-plugin-openapi-docs/lib/sidebars/index.js
+++ b/node_modules/docusaurus-plugin-openapi-docs/lib/sidebars/index.js
-@@ -146,9 +146,16 @@ function groupByTags(items, sidebarOptions, options, tags, docPath) {
+@@ -146,9 +146,14 @@ function groupByTags(items, sidebarOptions, options, tags, docPath) {
}
const taggedApiItems = apiItems.filter((item) => { var _a; return !!((_a = item.api.tags) === null || _a === void 0 ? void 0 : _a.includes(tag)); });
const taggedSchemaItems = schemaItems.filter((item) => { var _a; return !!((_a = item.schema["x-tags"]) === null || _a === void 0 ? void 0 : _a.includes(tag)); });
+ const altids = [];
-+
+ if (tagObject?.['x-legacy-doc-urls']) {
+ altids.push(...tagObject['x-legacy-doc-urls']);
+ }
-+
return {
type: "category",
label: (_a = tagObject === null || tagObject === void 0 ? void 0 : tagObject["x-displayName"]) !== null && _a !== void 0 ? _a : tag,
@@ -19,7 +17,7 @@ index 6f97824..075b91e 100644
link: linkConfig,
collapsible: sidebarCollapsible,
collapsed: sidebarCollapsed,
-@@ -208,11 +215,12 @@ function generateSidebarSlice(sidebarOptions, options, api, tags, docPath, tagGr
+@@ -208,11 +213,12 @@ function generateSidebarSlice(sidebarOptions, options, api, tags, docPath, tagGr
filteredTags.push(tag);
}
});
diff --git a/patches/docusaurus-theme-openapi-docs+4.6.0.patch b/patches/docusaurus-theme-openapi-docs+4.6.0.patch
deleted file mode 100644
index 7f0e674793..0000000000
--- a/patches/docusaurus-theme-openapi-docs+4.6.0.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js
-index 31bf239..6cc68a1 100644
---- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js
-+++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js
-@@ -309,7 +309,7 @@ function CodeSnippets({
- CodeTab,
- {
- value: lang.language,
-- label: lang.language,
-+ label: lang.label ?? lang.language,
- key: lang.language,
- attributes: {
- className: `openapi-tabs__code-item--${lang.logoClass}`,
-diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js
-index a2a4e40..f2d944d 100644
---- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js
-+++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js
-@@ -30,7 +30,7 @@ function Export({ url, proxy }) {
- react_1.default.createElement(
- "button",
- { className: "export-button button button--sm button--secondary" },
-- "Export"
-+ "Download OpenAPI"
- ),
- react_1.default.createElement(
- "ul",
-@@ -48,7 +48,23 @@ function Export({ url, proxy }) {
- className: "dropdown__link",
- href: `${url}`,
- },
-- "OpenAPI Spec"
-+ "YAML"
-+ )
-+ ),
-+ react_1.default.createElement(
-+ "li",
-+ null,
-+ react_1.default.createElement(
-+ "a",
-+ {
-+ onClick: (e) => {
-+ e.preventDefault();
-+ saveFile(`${url.replace(/\.yaml$/, '.json')}`);
-+ },
-+ className: "dropdown__link",
-+ href: `${url.replace(/\.yaml$/, '.json')}`,
-+ },
-+ "JSON"
- )
- )
- )
diff --git a/patches/docusaurus-theme-openapi-docs+4.7.1.patch b/patches/docusaurus-theme-openapi-docs+4.7.1.patch
new file mode 100644
index 0000000000..ba46312c37
--- /dev/null
+++ b/patches/docusaurus-theme-openapi-docs+4.7.1.patch
@@ -0,0 +1,412 @@
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Authorization/slice.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Authorization/slice.js
+index 47f1ec7..9ce8587 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Authorization/slice.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Authorization/slice.js
+@@ -49,7 +49,8 @@ function createAuth({ security, securitySchemes, options: opts }) {
+ const id = Object.keys(option).join(" and ");
+ for (const [schemeID, scopes] of Object.entries(option)) {
+ const scheme = securitySchemes?.[schemeID];
+- if (scheme) {
++ // Apify: Skip apiKey schemes to only support httpBearer tokens
++ if (scheme && scheme.type !== "apiKey") {
+ if (options[id] === undefined) {
+ options[id] = [];
+ }
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js
+index 31bf239..6cc68a1 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/CodeSnippets/index.js
+@@ -309,7 +309,7 @@ function CodeSnippets({
+ CodeTab,
+ {
+ value: lang.language,
+- label: lang.language,
++ label: lang.label ?? lang.language,
+ key: lang.language,
+ attributes: {
+ className: `openapi-tabs__code-item--${lang.logoClass}`,
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js
+index a2a4e40..f2d944d 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/Export/index.js
+@@ -30,7 +30,7 @@ function Export({ url, proxy }) {
+ react_1.default.createElement(
+ "button",
+ { className: "export-button button button--sm button--secondary" },
+- "Export"
++ "Download OpenAPI"
+ ),
+ react_1.default.createElement(
+ "ul",
+@@ -48,7 +48,23 @@ function Export({ url, proxy }) {
+ className: "dropdown__link",
+ href: `${url}`,
+ },
+- "OpenAPI Spec"
++ "YAML"
++ )
++ ),
++ react_1.default.createElement(
++ "li",
++ null,
++ react_1.default.createElement(
++ "a",
++ {
++ onClick: (e) => {
++ e.preventDefault();
++ saveFile(`${url.replace(/\.yaml$/, '.json')}`);
++ },
++ className: "dropdown__link",
++ href: `${url.replace(/\.yaml$/, '.json')}`,
++ },
++ "JSON"
+ )
+ )
+ )
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js
+index f8f722f..ec0c117 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js
+@@ -44,6 +44,7 @@ function ParamBooleanFormItem({ param }) {
+ render: ({ field: { onChange } }) =>
+ react_1.default.createElement(FormSelect_1.default, {
+ options: ["---", "true", "false"],
++ value: (param.value === undefined || param.value === null || param.value === "") ? "---" : String(param.value),
+ onChange: (e) => {
+ const val = e.target.value;
+ dispatch(
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/buildPostmanRequest.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/buildPostmanRequest.js
+index bcebb1c..ac03ec1 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/buildPostmanRequest.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiExplorer/buildPostmanRequest.js
+@@ -117,7 +117,9 @@ function setQueryParams(postman, queryParams) {
+ }
+ } else if (param.explode) {
+ const jsonResult = tryDecodeJsonParam(param.value);
+- if (jsonResult && typeof jsonResult === "object") {
++ // Apify: Only use Object.entries for actual objects, not primitives (boolean, number, string)
++ // JSON.parse("true") returns boolean true, and Object.entries(true) returns [] which breaks the URL
++ if (jsonResult && typeof jsonResult === "object" && !Array.isArray(jsonResult)) {
+ return Object.entries(jsonResult).map(
+ ([key, val]) =>
+ new sdk.QueryParam({
+@@ -125,14 +127,8 @@ function setQueryParams(postman, queryParams) {
+ value: String(val),
+ })
+ );
+- } else {
+- return new sdk.QueryParam({
+- key: param.name,
+- value: Object.entries(jsonResult)
+- .map(([key, val]) => `${key},${val}`)
+- .join(","),
+- });
+ }
++ // For primitive values (including booleans parsed from "true"/"false"), fall through to default handling
+ }
+ // Parameter allows empty value: "/hello?extended"
+ if (param.allowEmptyValue) {
+@@ -144,9 +140,14 @@ function setQueryParams(postman, queryParams) {
+ }
+ return undefined;
+ }
++ // Apify: Handle boolean values - convert to string for proper URL serialization
++ // This handles both actual booleans and ensures string values are passed correctly
++ const finalValue = typeof param.value === "boolean"
++ ? param.value.toString()
++ : String(param.value);
+ return new sdk.QueryParam({
+ key: param.name,
+- value: param.value,
++ value: finalValue,
+ });
+ })
+ .flat() // Flatten the array in case of nested arrays from map
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiItem/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiItem/index.js
+index f6052d1..867bfd2 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiItem/index.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ApiItem/index.js
+@@ -27,6 +27,7 @@ const slice_1 = require("@theme/ApiExplorer/Authorization/slice");
+ const persistenceMiddleware_1 = require("@theme/ApiExplorer/persistenceMiddleware");
+ const storage_utils_1 = require("@theme/ApiExplorer/storage-utils");
+ const Layout_1 = __importDefault(require("@theme/ApiItem/Layout"));
++const LLMButtons_1 = __importDefault(require("@theme/LLMButtons"));
+ const CodeBlock_1 = __importDefault(require("@theme/CodeBlock"));
+ const Metadata_1 = __importDefault(require("@theme/DocItem/Metadata"));
+ const SkeletonLoader_1 = __importDefault(require("@theme/SkeletonLoader"));
+@@ -47,6 +48,81 @@ function base64ToUint8Array(base64) {
+ }
+ return bytes;
+ }
++// Apify: Render clients box with links to Python and JavaScript API client documentation
++function renderClientsBox(api) {
++ const pyUrl = api?.['x-py-doc-url'];
++ const jsUrl = api?.['x-js-doc-url'];
++ if (!pyUrl && !jsUrl) {
++ return null;
++ }
++ return react_1.default.createElement(
++ "div",
++ { className: "openapi-clients-box" },
++ react_1.default.createElement("div", { className: "openapi-clients-box-heading" }, "API Clients"),
++ jsUrl && react_1.default.createElement(
++ "a",
++ {
++ href: jsUrl,
++ target: "_blank",
++ rel: "noopener noreferrer",
++ className: "client-docs-link"
++ },
++ react_1.default.createElement("img", { src: "/img/javascript-40x40.svg", className: "openapi-clients-box-icon", width: "20px", height: "20px", alt: "JavaScript" }),
++ "JavaScript"
++ ),
++ pyUrl && react_1.default.createElement(
++ "a",
++ {
++ href: pyUrl,
++ target: "_blank",
++ rel: "noopener noreferrer",
++ className: "client-docs-link"
++ },
++ react_1.default.createElement("img", { src: "/img/python-40x40.svg", className: "openapi-clients-box-icon", width: "20px", height: "20px", alt: "Python" }),
++ "Python"
++ )
++ );
++}
++// Apify: Component that renders LLMButtons and moves it after the heading
++function LLMButtonsPortal() {
++ const [container, setContainer] = react_1.default.useState(null);
++ react_1.default.useEffect(() => {
++ // Create a container div
++ const div = document.createElement('div');
++ div.className = 'openapi-llm-buttons';
++
++ // Find the heading and insert after it
++ const attemptInsert = () => {
++ const heading = document.querySelector('.openapi__heading');
++ if (heading && heading.parentNode) {
++ heading.parentNode.insertBefore(div, heading.nextSibling);
++ setContainer(div);
++ return true;
++ }
++ return false;
++ };
++
++ // Try immediately, then with delays
++ if (!attemptInsert()) {
++ const timers = [10, 50, 100, 250, 500, 1000].map(delay =>
++ setTimeout(attemptInsert, delay)
++ );
++ return () => timers.forEach(clearTimeout);
++ }
++
++ return () => {
++ if (div.parentNode) {
++ div.parentNode.removeChild(div);
++ }
++ };
++ }, []);
++
++ if (!container) return null;
++ return require("react-dom").createPortal(
++ react_1.default.createElement(LLMButtons_1.default, { isApiReferencePage: true }),
++ container
++ );
++}
+ // @ts-ignore
+ function ApiItem(props) {
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`;
+@@ -158,7 +234,9 @@ function ApiItem(props) {
+ react_1.default.createElement(
+ "div",
+ { className: "col col--7 openapi-left-panel__container" },
+- react_1.default.createElement(MDXComponent, null)
++ react_1.default.createElement(BrowserOnly_1.default, { fallback: null }, () => renderClientsBox(api)),
++ react_1.default.createElement(MDXComponent, null),
++ react_1.default.createElement(LLMButtonsPortal, null)
+ ),
+ react_1.default.createElement(
+ "div",
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ResponseSchema/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ResponseSchema/index.js
+index e84857b..ba445e8 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/ResponseSchema/index.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/ResponseSchema/index.js
+@@ -64,6 +64,8 @@ const ResponseSchemaComponent = ({ title, body, style }) => {
+ )
+ );
+ }
++ // Apify: Check if there's an explicit example - if so, skip auto-generated
++ const hasExplicitExample = responseExample || responseExamples;
+ return (
+ // @ts-ignore
+ react_1.default.createElement(
+@@ -72,6 +74,25 @@ const ResponseSchemaComponent = ({ title, body, style }) => {
+ react_1.default.createElement(
+ SchemaTabs_1.default,
+ { className: "openapi-tabs__schema" },
++ // Apify: Put examples first, before schema
++ // Show explicit examples if available
++ responseExample &&
++ (0, ResponseExamples_1.ResponseExample)({
++ responseExample,
++ mimeType,
++ }),
++ responseExamples &&
++ (0, ResponseExamples_1.ResponseExamples)({
++ responseExamples,
++ mimeType,
++ }),
++ // Only show auto-generated example if no explicit example exists
++ !hasExplicitExample && firstBody &&
++ (0, ResponseExamples_1.ExampleFromSchema)({
++ schema: firstBody,
++ mimeType: mimeType,
++ }),
++ // Schema tab comes after examples
+ react_1.default.createElement(
+ TabItem_1.default,
+ { key: title, label: title, value: title },
+@@ -132,22 +153,7 @@ const ResponseSchemaComponent = ({ title, body, style }) => {
+ })
+ )
+ )
+- ),
+- firstBody &&
+- (0, ResponseExamples_1.ExampleFromSchema)({
+- schema: firstBody,
+- mimeType: mimeType,
+- }),
+- responseExamples &&
+- (0, ResponseExamples_1.ResponseExamples)({
+- responseExamples,
+- mimeType,
+- }),
+- responseExample &&
+- (0, ResponseExamples_1.ResponseExample)({
+- responseExample,
+- mimeType,
+- })
++ )
+ )
+ )
+ );
+diff --git a/node_modules/docusaurus-theme-openapi-docs/lib/theme/Schema/index.js b/node_modules/docusaurus-theme-openapi-docs/lib/theme/Schema/index.js
+index 37190c6..76766ef 100644
+--- a/node_modules/docusaurus-theme-openapi-docs/lib/theme/Schema/index.js
++++ b/node_modules/docusaurus-theme-openapi-docs/lib/theme/Schema/index.js
+@@ -304,7 +304,7 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
+ )
+ );
+ };
+-const Properties = ({ schema, schemaType, schemaPath }) => {
++const Properties = ({ schema, schemaType, schemaPath, depth = 0 }) => {
+ const discriminator = schema.discriminator;
+ if (discriminator && !discriminator.mapping) {
+ const anyOneOf = schema.oneOf ?? schema.anyOf ?? {};
+@@ -344,6 +344,7 @@ const Properties = ({ schema, schemaType, schemaPath }) => {
+ discriminator: discriminator,
+ schemaType: schemaType,
+ schemaPath: schemaPath ? `${schemaPath}.${key}` : undefined,
++ depth, // Apify: pass depth
+ })
+ )
+ );
+@@ -581,7 +582,10 @@ const SchemaNodeDetails = ({
+ required,
+ schemaType,
+ schemaPath,
++ depth = 1, // Apify: track nesting depth, default to 1 (first level)
+ }) => {
++ // Apify: expand first level of nested items (depth 0 or 1)
++ const shouldBeOpen = depth <= 1;
+ return react_1.default.createElement(
+ SchemaItem_1.default,
+ { collapsible: true },
+@@ -589,6 +593,7 @@ const SchemaNodeDetails = ({
+ Details_1.default,
+ {
+ className: "openapi-markdown__details",
++ open: shouldBeOpen, // Apify: expand first level
+ summary: react_1.default.createElement(Summary, {
+ name: name,
+ schemaName: schemaName,
+@@ -611,6 +616,7 @@ const SchemaNodeDetails = ({
+ schema: schema,
+ schemaType: schemaType,
+ schemaPath: schemaPath,
++ depth: depth + 1,
+ })
+ )
+ )
+@@ -703,6 +709,7 @@ const SchemaEdge = ({
+ discriminator,
+ schemaType,
+ schemaPath,
++ depth = 1, // Apify: track nesting depth
+ }) => {
+ if (
+ (schemaType === "request" && schema.readOnly) ||
+@@ -731,6 +738,7 @@ const SchemaEdge = ({
+ schema: schema,
+ nullable: schema.nullable,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (schema.properties) {
+@@ -742,6 +750,7 @@ const SchemaEdge = ({
+ schema: schema,
+ nullable: schema.nullable,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (schema.additionalProperties) {
+@@ -753,6 +762,7 @@ const SchemaEdge = ({
+ schema: schema,
+ nullable: schema.nullable,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (schema.items?.properties) {
+@@ -764,6 +774,7 @@ const SchemaEdge = ({
+ schema: schema,
+ schemaType: schemaType,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (schema.items?.anyOf || schema.items?.oneOf || schema.items?.allOf) {
+@@ -775,6 +786,7 @@ const SchemaEdge = ({
+ schema: schema,
+ schemaType: schemaType,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (schema.allOf) {
+@@ -813,6 +825,7 @@ const SchemaEdge = ({
+ schema: mergedSchemas,
+ schemaType: schemaType,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (mergedSchemas.properties !== undefined) {
+@@ -824,6 +837,7 @@ const SchemaEdge = ({
+ schema: mergedSchemas,
+ schemaType: schemaType,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ if (mergedSchemas.items?.properties) {
+@@ -835,6 +849,7 @@ const SchemaEdge = ({
+ schema: mergedSchemas,
+ schemaType: schemaType,
+ schemaPath: schemaPath,
++ depth,
+ });
+ }
+ return react_1.default.createElement(SchemaItem_1.default, {
diff --git a/redocly.yaml b/redocly.yaml
index 0e57f9938d..a94f47ef8b 100644
--- a/redocly.yaml
+++ b/redocly.yaml
@@ -28,5 +28,4 @@ plugins:
decorators:
apify/legacy-doc-url-decorator: on
- apify/client-references-links-decorator: on
apify/code-samples-decorator: on
diff --git a/typos.toml b/typos.toml
index 9a36a2d6b6..bf2696b1e2 100644
--- a/typos.toml
+++ b/typos.toml
@@ -13,6 +13,7 @@ extend-exclude = [
"*.min.js",
"*.min.css",
"CHANGELOG.md",
+ "patches/",
]
# Add project-specific identifiers that should not be treated as typos