Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Externalize scim endpoints parameters #467

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ Once you're done, add the results to the main documentation with:
./api/build.sh
```

Before editing the API take a look at `./api/parameters.js` script. Parameters for endpoints need
to be externalized for Swagger UI (and Grist API console) to work correctly. This script explains
it in more details and offer some help with the process.

## Updating function reference

To update `help/en/docs/functions.md` from the documentation comments in Grist, run:
Expand Down
85 changes: 85 additions & 0 deletions api/parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env node

// This script is an attempt to automate work started in https://github.com/gristlabs/grist-help/pull/293
// TLDR: Swagger UI (and Grist API) console doesn't support inline parameters well, so they need to be
// converted to shared parameters. This script does that conversion, but it's not perfect and may need
// manual tweaking afterwards if the parameters are complex or have shared names.

const fs = require('fs');
const yaml = require('js-yaml');

// Get command-line arguments
const inputFilePath = process.argv[2];
const outputFilePath = process.argv[3];

if (!inputFilePath) {
console.error('Usage: node parameters.js <inputFilePath> [outputFilePath]');
process.exit(1);
}

try {
const fileContents = fs.readFileSync(inputFilePath, 'utf8');
const apiSpec = yaml.load(fileContents);

// Initialize shared parameters in the components section if not already present
apiSpec.components = apiSpec.components || {};
apiSpec.components.parameters = apiSpec.components.parameters || {};

// Function to generate a unique parameter name based on its contents
const generateParameterName = (param) => {
const baseName = param.name;
return `${baseName}Param`;
};

// Function to create shared parameter references
const createSharedParameter = (param) => {
const paramName = generateParameterName(param);
if (!apiSpec.components.parameters[paramName]) {
apiSpec.components.parameters[paramName] = {
in: param.in,
name: param.name,
schema: param.schema,
description: param.description || `${param.name} parameter`,
required: param.required
};
}
return { $ref: `#/components/parameters/${paramName}` };
};

// Function to process each endpoint's parameters
const processParameters = (parameters) => {
return parameters.map((param) => {
// Skip parameters that are already references
if (param.$ref) {
return param;
}
return createSharedParameter(param);
});
};

// Update paths to use shared parameters
Object.keys(apiSpec.paths).forEach((path) => {
const methods = apiSpec.paths[path];
Object.keys(methods).forEach((method) => {
const operation = methods[method];
if (operation.parameters) {
operation.parameters = processParameters(operation.parameters);
}
});
});

// Write the updated YAML
const updatedYaml = yaml.dump(apiSpec);

if (outputFilePath === '-') {
fs.writeFileSync(inputFilePath, updatedYaml, 'utf8');
console.log(`Overwritten API spec at ${inputFilePath}`);
} else if (outputFilePath) {
fs.writeFileSync(outputFilePath, updatedYaml, 'utf8');
console.log(`Updated API spec written to ${outputFilePath}`);
} else {
process.stdout.write(updatedYaml);
}
} catch (e) {
console.error(e);
}
49 changes: 28 additions & 21 deletions api/scim/users.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,9 @@ paths:
tags:
- scim
parameters:
- name: startIndex
in: query
description: The starting index for pagination.
required: false
schema:
type: integer
example: 1
- name: count
in: query
description: The number of users to retrieve.
required: false
schema:
type: integer
example: 10
- name: filter
in: query
description: Filter users based on specific criteria.
required: false
schema:
type: string
example: "userName pr"
- $ref: '#/components/parameters/startIndexParam'
- $ref: '#/components/parameters/countParam'
- $ref: '#/components/parameters/filterParam'
responses:
'200':
description: Successfully retrieved list of users.
Expand Down Expand Up @@ -417,3 +399,28 @@ components:
description: The unique identifier of the user.
example: "1"
- $ref: '#/components/schemas/UserInRequest'
parameters:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see there are already some keys in params. Any reason why we shouldn't put these there too?

startIndexParam:
in: query
name: startIndex
schema:
type: integer
example: 1
description: The starting index for pagination.
required: false
countParam:
in: query
name: count
schema:
type: integer
example: 10
description: The number of users to retrieve.
required: false
filterParam:
in: query
name: filter
schema:
type: string
example: userName pr
description: Filter users based on specific criteria.
required: false
2 changes: 1 addition & 1 deletion help/en/docs/api.md

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"redoc-cli": "^0.13.20"
},
"devDependencies": {
"js-yaml": "^4.1.0",
"typedoc": "^0.23.9",
"typedoc-plugin-markdown": "3.13.4",
"typescript": "^4.7.4"
Expand Down
Loading