Skip to content

Commit

Permalink
feat: implement reference generation in generator-cli (#1070)
Browse files Browse the repository at this point in the history
  • Loading branch information
armandobelardo authored Jun 26, 2024
1 parent f107b56 commit a0f252b
Show file tree
Hide file tree
Showing 7 changed files with 442 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`basic-reference > basic-reference > generate reference file 1`] = `
"## Accounts
This package contains all endpoints on accounts...
<details><summary><code><a href="./src/accounts.py">client.accounts.get()</a></code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Some description specific to the endpoint about accounts, etc. etc.
It can also be multi-line.
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
\`\`\`python
client.accounts.get(account_id="ID")
\`\`\`
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**account_id:** \`str\`
The ID of the account to retrieve.
This is a multi-line description as well.
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
## Users
This package contains all endpoints on users...
<details><summary><code><a href="./src/users.py">client.users.get()</a></code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Some description specific to the endpoint about users, etc. etc.
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
\`\`\`python
client.users.get(user_id="ID", account_id="ACCOUNT_ID")
\`\`\`
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**user_id:** \`str\` — The ID of the user to retrieve.
</dd>
</dl>
<dl>
<dd>
**account_id:** \`str\` — The ID of the account to retrieve the user from.
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
<details><summary><code><a href="./src/users.py">client.users.update()</a></code></summary>
<dl>
<dd>
#### 📝 Description
<dl>
<dd>
<dl>
<dd>
Some description specific to the endpoint about users, etc. etc.
</dd>
</dl>
</dd>
</dl>
#### 🔌 Usage
<dl>
<dd>
<dl>
<dd>
\`\`\`python
client.users.get(update=User(id="ID")
\`\`\`
</dd>
</dl>
</dd>
</dl>
#### ⚙️ Parameters
<dl>
<dd>
<dl>
<dd>
**update:** \`<a href="./src/users.py">User</a>\` — The updated user object to send to the server.
</dd>
</dl>
</dd>
</dl>
</dd>
</dl>
</details>
"
`;
8 changes: 8 additions & 0 deletions clis/generator-cli/src/__test__/basic-reference.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { testGenerateReference } from "./testGenerateReference";

describe("basic-reference", () => {
testGenerateReference({
fixtureName: "basic-reference",
referenceConfigFilename: "reference.json",
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"sections": [
{
"title": "Accounts",
"description": "This package contains all endpoints on accounts...",
"endpoints": [
{
"title": {
"snippetParts": [
{
"text": "client.accounts.get()",
"location": { "path": "./src/accounts.py" }
}
]
},
"description": "Some description specific to the endpoint about accounts, etc. etc.\n\nIt can also be multi-line.",
"snippet": "client.accounts.get(account_id=\"ID\")",
"parameters": [
{
"name": "account_id",
"type": "str",
"description": "The ID of the account to retrieve.\n\nThis is a multi-line description as well.",
"required": true
}
]
}
]
},
{
"title": "Users",
"description": "This package contains all endpoints on users...",
"endpoints": [
{
"title": {
"snippetParts": [
{
"text": "client.users.get()",
"location": { "path": "./src/users.py" }
}
]
},
"description": "Some description specific to the endpoint about users, etc. etc.",
"snippet": "client.users.get(user_id=\"ID\", account_id=\"ACCOUNT_ID\")",
"parameters": [
{
"name": "user_id",
"type": "str",
"description": "The ID of the user to retrieve.",
"required": true
},
{
"name": "account_id",
"type": "str",
"description": "The ID of the account to retrieve the user from.",
"required": true
}
]
},
{
"title": {
"snippetParts": [
{
"text": "client.users.update()",
"location": { "path": "./src/users.py" }
}
]
},
"description": "Some description specific to the endpoint about users, etc. etc.",
"snippet": "client.users.get(update=User(id=\"ID\")",
"parameters": [
{
"name": "update",
"type": "User",
"location": { "path": "./src/users.py" },
"description": "The updated user object to send to the server.",
"required": true
}
]
}
]
}
],
"language": "PYTHON"
}
35 changes: 35 additions & 0 deletions clis/generator-cli/src/__test__/testGenerateReference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import execa from "execa";
import path from "path";

const FIXTURES_PATH = path.join(__dirname, "fixtures");

export function testGenerateReference({
fixtureName,
referenceConfigFilename,
}: {
fixtureName: string;
referenceConfigFilename: string;
}): void {
// eslint-disable-next-line vitest/valid-title
describe(fixtureName, () => {
it("generate reference file", async () => {
const absolutePathToReferenceConfig = getAbsolutePathToFixtureFile({
fixtureName,
filepath: referenceConfigFilename,
});
const args = [
path.join(__dirname, "../../dist/cli.cjs"),
"generate-reference",
"--config",
absolutePathToReferenceConfig,
];

const { stdout } = await execa("node", args);
expect(stdout).toMatchSnapshot();
});
});
}

function getAbsolutePathToFixtureFile({ fixtureName, filepath }: { fixtureName: string; filepath: string }): string {
return path.join(FIXTURES_PATH, fixtureName, filepath);
}
33 changes: 33 additions & 0 deletions clis/generator-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import path from "path";
import { hideBin } from "yargs/helpers";
import yargs from "yargs/yargs";
import { loadReadmeConfig } from "./configuration/loadReadmeConfig";
import { loadReferenceConfig } from "./configuration/loadReferenceConfig";
import { ReadmeGenerator } from "./readme/ReadmeGenerator";
import { ReadmeParser } from "./readme/ReadmeParser";
import { ReferenceGenerator } from "./reference/ReferenceGenerator";

void yargs(hideBin(process.argv))
.scriptName(process.env.CLI_NAME ?? "generator-cli")
Expand Down Expand Up @@ -48,6 +50,37 @@ void yargs(hideBin(process.argv))
process.exit(0);
},
)
.command(
"generate-reference",
"Generate an SDK reference (`reference.md`) using the provided configuration file.",
(argv) =>
argv
.option("config", {
string: true,
requred: true,
})
.option("output", {
string: true,
requred: false,
}),
async (argv) => {
if (argv.config == null) {
process.stderr.write("missing required arguments; please specify the --config flag\n");
process.exit(1);
}
const wd = cwd();
const referenceConfig = await loadReferenceConfig({
absolutePathToConfig: resolve(wd, argv.config),
});
const generator = new ReferenceGenerator({
referenceConfig,
});
await generator.generate({
output: await createWriteStream(argv.output),
});
process.exit(0);
},
)
.demandCommand()
.showHelpOnFail(true)
.parse();
Expand Down
12 changes: 12 additions & 0 deletions clis/generator-cli/src/configuration/loadReferenceConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AbsoluteFilePath } from "@fern-api/fs-utils";
import { readFile } from "fs/promises";
import { FernGeneratorCli } from "./generated";

export async function loadReferenceConfig({
absolutePathToConfig,
}: {
absolutePathToConfig: AbsoluteFilePath;
}): Promise<FernGeneratorCli.ReferenceConfig> {
const rawContents = await readFile(absolutePathToConfig, "utf8");
return JSON.parse(rawContents);
}
Loading

0 comments on commit a0f252b

Please sign in to comment.