Skip to content

Commit 66f8637

Browse files
committed
Feat: auto-generate x-codesamples
1 parent a32c56e commit 66f8637

File tree

6 files changed

+64
-16
lines changed

6 files changed

+64
-16
lines changed

.redocly.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ plugins:
2727
decorators:
2828
apify/legacy-doc-url-decorator: on
2929
apify/client-references-links-decorator: on
30+
apify/code-samples-decorator: on
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { ApifyClient } from 'apify-client';
22

33
const apifyClient = new ApifyClient({ token: 'my-token' });
4-
const actorCollectionClient = apifyClient.actors();
5-
6-
const { items } = await actorCollectionClient.list();
4+
const { items } = await apifyClient.actors().list();
75

86
console.log(items);
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { ApifyClient } from 'apify-client';
22

33
const apifyClient = new ApifyClient({ token: 'my-token' });
4-
const actorCollectionClient = apifyClient.actors();
5-
6-
const myActor = await actorCollectionClient.create({ name: 'my-actor' });
4+
const myActor = await apifyClient.actors().create({ name: 'my-actor' });
75

86
console.log(myActor);

apify-api/openapi/paths/actors/acts.yaml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,6 @@ get:
9494
x-py-parent: ActorCollectionClientAsync
9595
x-py-name: list
9696
x-py-doc-url: https://docs.apify.com/api/client/python/reference/class/ActorCollectionClientAsync#list
97-
x-codeSamples:
98-
- lang: JavaScript
99-
label: JS client
100-
source:
101-
$ref: ../../code_samples/js/acts_get.js
10297

10398
post:
10499
tags:
@@ -245,8 +240,3 @@ post:
245240
x-py-parent: ActorCollectionClientAsync
246241
x-py-name: create
247242
x-py-doc-url: https://docs.apify.com/api/client/python/reference/class/ActorCollectionClientAsync#create
248-
x-codeSamples:
249-
- lang: JavaScript
250-
label: JS client
251-
source:
252-
$ref: ../../code_samples/js/acts_post.js

apify-api/plugins/apify.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const ClientReferencesLinksDecorator = require('./decorators/client-references-links-decorator');
2+
const CodeSamplesDecorator = require('./decorators/code-samples-decorator');
23
const LegacyDocUrlDecorator = require('./decorators/legacy-doc-url-decorator');
34

45
module.exports = {
@@ -7,6 +8,7 @@ module.exports = {
78
oas3: {
89
'legacy-doc-url-decorator': LegacyDocUrlDecorator,
910
'client-references-links-decorator': ClientReferencesLinksDecorator,
11+
'code-samples-decorator': CodeSamplesDecorator,
1012
},
1113
},
1214
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const { existsSync } = require('fs');
2+
const path = require('path');
3+
4+
const X_CODE_SAMPLES_PROPERTY = 'x-codeSamples';
5+
6+
const LANGUAGES = [
7+
{ lang: 'JavaScript', label: 'JS client' },
8+
];
9+
10+
/**
11+
* This decorator adds the x-codeSamples property to the schema object if a file with the operationId exists in the
12+
* code samples directory.
13+
* This helps us add the samples in a consistent way and find out which operations are missing a sample.
14+
*
15+
* The added sample link will look like this:
16+
* x-codeSamples:
17+
* - lang: JavaScript
18+
* label: JS client
19+
* source:
20+
* $ref: ../../code_samples/js/acts_post.js
21+
*/
22+
function CodeSamplesDecorator(target) {
23+
if (!target.operationId) return;
24+
25+
const codeSamples = [];
26+
27+
for (const { lang, label } of LANGUAGES) {
28+
const codeSamplePath = path.join(__dirname, `../../openapi/code_samples/${lang.toLowerCase()}/${target.operationId}.js`);
29+
30+
if (!existsSync(codeSamplePath)) {
31+
// Just use this console log in development to see which operations are missing a code sample.
32+
// console.log(`Missing code sample for operation ${target.operationId}`);
33+
return;
34+
}
35+
36+
codeSamples.push({
37+
lang,
38+
label,
39+
source: {
40+
$ref: codeSamplePath,
41+
},
42+
});
43+
}
44+
45+
if (codeSamples.length) {
46+
target[X_CODE_SAMPLES_PROPERTY] = codeSamples;
47+
}
48+
}
49+
50+
module.exports = () => ({
51+
// Redocly is using a visitor pattern. What the following code does is that whenever the traverser leaves a node of
52+
// type Tag or Operation, it executes CodeSamplesDecorator on it.
53+
Tag: {
54+
leave: CodeSamplesDecorator,
55+
},
56+
Operation: {
57+
leave: CodeSamplesDecorator,
58+
},
59+
});

0 commit comments

Comments
 (0)