Skip to content

Commit

Permalink
DEX-424 feat: added comments for references generation
Browse files Browse the repository at this point in the history
  • Loading branch information
kamal-skyflow committed Dec 18, 2023
1 parent dff2131 commit 0f71625
Show file tree
Hide file tree
Showing 20 changed files with 391 additions and 3 deletions.
87 changes: 87 additions & 0 deletions .github/workflows/update-refs-in-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Update references in Docsite

on:
push:
branches:
- DEX-424/ref-test

jobs:
generate-react-native-sdk-refs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: DEX-424/ref-test
fetch-depth: 0
persist-credentials: false

- uses: actions/setup-node@v1
with:
node-version: 14.17.6
- run: npm install

- name: Generate React Native SDK references
run: |
mkdir docs
npm run docs-gen
cd ../..
mkdir refs
cp -r skyflow-react-native/skyflow-react-native/docs/markdown/* refs/
cd skyflow-react-native/skyflow-react-native/
rm -r lib/
echo "SHORT_SHA=$(git rev-parse --short "$GITHUB_SHA")" >> $GITHUB_ENV
git clean -df
- name: Create a branch in skyflow-docs
env:
TOKEN: ${{ secrets.PAT_ACTIONS }}
REPO_OWNER: skyflowapi
REPO_NAME: skyflow-docs
ACTOR: ${{ github.actor }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Create a new branch in skyflow-docs
cd $GITHUB_WORKSPACE
git remote add skyflow-docs https://${TOKEN}@github.com/${REPO_OWNER}/${REPO_NAME}.git
git fetch skyflow-docs main
BRANCH_NAME="SDK/react-native/${{ env.SHORT_SHA }}"
git remote set-url --push skyflow-docs https://${ACTOR}:${TOKEN}@github.com/${REPO_OWNER}/${REPO_NAME}.git
git checkout -b $BRANCH_NAME skyflow-docs/main
cp -r ../../refs/* src/pages/content/docs/sdks/skyflow-react-native/
- name: Push files and raise a PR
env:
TOKEN: ${{ secrets.PAT_ACTIONS }}
REPO_OWNER: skyflowapi
REPO_NAME: skyflow-docs
ACTOR: ${{ github.actor }}
run: |
git config user.name ${{ github.actor }}
git config user.email ${{ github.actor }}@users.noreply.github.com
BRANCH_NAME="SDK/react-native/${{ env.SHORT_SHA }}"
git add .
# Check if there are changes to commit
if [[ -n "$(git status --porcelain)" ]]; then
git commit -m "SDK-${{ env.SHORT_SHA }} Added React Native SDK references"
git push skyflow-docs $BRANCH_NAME
# Raise a pull request
BASE_BRANCH="main"
BRANCH_NAME="SDK/react-native/${{ env.SHORT_SHA }}"
TITLE="SDK-${{ env.SHORT_SHA }}: Updated React Native SDK references"
BODY="This pull request adds the latest React Native SDK references. Commit id for reference: $GITHUB_SHA"
API_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/pulls"
echo "API URL: $API_URL"
RESPONSE=$(curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $TOKEN" \
-d "{\"title\":\"$TITLE\",\"body\":\"$BODY\",\"head\":\"${BRANCH_NAME}\",\"base\":\"$BASE_BRANCH\"}" \
"$API_URL")
echo "Response Body: $RESPONSE"
PR_URL=$(echo "$RESPONSE" | jq -r '.html_url')
echo "Pull Request URL: $PR_URL"
else
echo "No changes to commit. Skipping push files and raise a PR."
exit 0
fi
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"prepare": "bob build",
"example": "yarn --cwd example",
"bootstrap": "yarn example && yarn && yarn example pods",
"build": "bob build"
"build": "bob build",
"docs-gen": "node scripts/doc-gen/components-json-gen.js && node scripts/doc-gen/markdown-gen.js"
},
"keywords": [
"react-native",
Expand Down Expand Up @@ -129,6 +130,7 @@
"dependencies": {
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"react-docgen-typescript": "^2.2.2",
"react-native-uuid": "^2.0.1",
"set-value": "^4.1.0"
}
Expand Down
68 changes: 68 additions & 0 deletions scripts/doc-gen/components-json-gen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable no-undef */
/* eslint-disable @typescript-eslint/no-var-requires */
const fs = require('fs');
const path = require('path');
const docgen = require('react-docgen-typescript');

const tsConfigParser = docgen.withCustomConfig('./tsconfig.json', {
savePropValueAsString: true,
skipChildrenPropWithoutDoc: false,
propFilter: {
skipPropsWithoutDoc: false,
skipPropsWithName: 'children',
},
shouldExtractLiteralValuesFromEnum: true,
});

const paths = ['components', 'hooks'];
const excludeDirs = [];

function getFiles(dir, files = []) {
const fileNames = fs.readdirSync(dir);

fileNames.forEach((fileName) => {
const filePath = path.join(dir, fileName);
const stat = fs.statSync(filePath);
if (stat.isDirectory() && !excludeDirs.includes(fileName)) {
getFiles(filePath, files);
} else if (fileName === 'index.tsx' || fileName === 'index.ts') {
files.push(filePath);
}
});

return files;
}

function generateDocumentationJson() {
const docJson = {};
const rootPath = path.join(__dirname, '../../');

paths.forEach((item) => {
const pathJsonArray = [];
const folderPath = path.join(rootPath, 'src', item);
const files = getFiles(folderPath);
files.forEach((file) => {
const relativePath = path.relative(rootPath, file);
const docs = tsConfigParser.parse(relativePath);
pathJsonArray.push(docs[0]);
});
docJson[item] = pathJsonArray;
});
return docJson;
}

function createDocJsonFile(json) {
const dirPath = path.join(__dirname, '../../', 'docs', 'json');
const filePath = path.join(dirPath, 'components.json');

// Create docs/json folder if it doesn't exist
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}

// Write to components.json file
fs.writeFileSync(filePath, JSON.stringify(json, null, 2));
console.log('Json documentation is generated at docs/json');
}

createDocJsonFile(generateDocumentationJson());
137 changes: 137 additions & 0 deletions scripts/doc-gen/markdown-gen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const components = require('../../docs/json/components.json');
const fs = require('fs');
const path = require('path');

function containsInternalAnnotation(description) {
return /\@internal/i.test(description);
}

function formatTypeColumn(str, propType) {
if (!str) {
return '';
}
const parts = str.split('|').map((s) => s.trim());
if (parts.length === 1) {
return `\`${str}\``;
}
if (!propType) {
return `\`${parts[0]}\``;
}
return `\`${parts[0]} / ${parts[1]}\``;
}

// Output directory for Markdown files
const outputDir = './docs/markdown';

// Overview page to list elements
let overviewContent = `
{% env enable="reactNativeSdkRef" %}
# React-Native
`;

// Loop through each component in the JSON object
Object.keys(components).forEach((key) => {
overviewContent += `\n## ${
key == 'core'
? 'Skyflow Provider'
: key == 'elements'
? 'Components'
: key.charAt(0).toUpperCase() + key.slice(1)
}\n\n`;

components[key]
.filter((component) => component)
.forEach((component) => {
// Skip generating the Markdown file if the component description contains '@internal'
if (
!component.description.trim() &&
Object.keys(component.props).every((propName) => !component.props[propName].description.trim())
) {
return;
}

// Create the Markdown file path based on the component name
const componentPath = path.join(
outputDir,
key,
`${component.displayName}.md`
);

const name = `${component.displayName}`;
overviewContent += `- [${name}](/sdks/skyflow-react-native/${key}/${name})\n`;

const sortedProps = Object.entries(component.props)
.sort(([_, propA], [__, propB]) => {
if (propA.required && !propB.required) {
return -1; // propA comes before propB
} else if (!propA.required && propB.required) {
return 1; // propB comes before propA
}
return 0; // no change in order
})
.reduce((sorted, [key, value]) => {
sorted[key] = value;
return sorted;
}, {});
// Generate the Markdown content for the component
let markdownContent = `---
id: ${component.displayName}
title: ${component.displayName}
sidebar_label: ${component.displayName}
---
{% env enable="reactNativeSdkRef" %}
# ${component.displayName}
${component.description}
## Import
\`\`\`
import {${component.displayName}} from 'skyflow-react-native';
\`\`\`
`;
const propsDetails = `
## Props
| Name | Type | Description | Required |
|-------------------------|----------------------|---------------------------------------------------------|------------------|
${Object.keys(sortedProps)
.map((propName) => {
const prop = sortedProps[propName];
const isInternal = prop.description && prop.description.includes('@internal');
const description = isInternal ? '' : prop.description;
return description ? `| ${prop.name} | ${formatTypeColumn(
prop.type.name,
prop.required
)} | ${description} | ${prop.required} |` : null;
})
.filter(Boolean)
.join('\n')}
`;
if (Object.keys(component.props).length) {
markdownContent += propsDetails;
}

if (Object.keys(component.tags).length > 0 && component.tags['returns']) {
markdownContent += `\n## Returns\n${component.tags['returns']}\n\n`;
}

markdownContent += '{% /env %}';
const folderPath = path.dirname(componentPath);

// Create the folder if it doesn't exist
if (!fs.existsSync(folderPath)) {
fs.mkdirSync(folderPath, { recursive: true });
}
// Write the Markdown content to the file
fs.writeFileSync(componentPath, markdownContent);
});
});
overviewContent += '\n{% /env %}';
fs.writeFileSync(path.join(outputDir, 'Overview.md'), overviewContent);
console.log('markdown files generated at docs/markdown');
3 changes: 3 additions & 0 deletions src/components/CardHolderNameElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';

/**
* Element to collect cardholder names.
*/
const CardHolderNameElement: React.FC<CollectElementProps> = ({ container, options = { required: false }, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>();
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
3 changes: 3 additions & 0 deletions src/components/CardNumberElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';

/**
* Element to collect card numbers.
*/
const CardNumberElement: React.FC<CollectElementProps> = ({ container, options = { required: false }, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>(undefined);
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
6 changes: 5 additions & 1 deletion src/components/ComposableContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";

export interface IComposableContainer {
/** Type of the container. */
container: CoreComposableContainer,
/** Function to call when the onSubmit event triggers. */
onSubmit?: () => void
}


/**
* Container Component for all composable elements.
*/
const ComposableContainer: React.FC<IComposableContainer> = (props) => {
const containerRef = useRef([]);
const { container, children } = props;
Expand Down
3 changes: 3 additions & 0 deletions src/components/CvvElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';

/**
* Element to collect CVVs.
*/
const CvvElement: React.FC<CollectElementProps> = ({ container, options = { requried: false }, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>();
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
3 changes: 3 additions & 0 deletions src/components/ExpirationDateElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';

/**
* Element to collect expiration dates.
*/
const ExpirationDateElement: React.FC<CollectElementProps> = ({ container, options, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>();
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
3 changes: 3 additions & 0 deletions src/components/ExpirationMonthElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';

/**
* Element to collect expiration month values.
*/
const ExpirationMonthElement: React.FC<CollectElementProps> = ({ container, options = { required: false }, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>();
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
3 changes: 3 additions & 0 deletions src/components/ExpirationYearElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';


/**
* Element to collect expiration year values.
*/
const ExpirationYearElement: React.FC<CollectElementProps> = ({ container, options, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>();
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
3 changes: 3 additions & 0 deletions src/components/InputFieldElement/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import SkyflowError from "../../utils/skyflow-error";
import SKYFLOW_ERROR_CODE from "../../utils/skyflow-error-code";
import uuid from 'react-native-uuid';

/**
* Element to collect arbitrary values.
*/
const InputFieldElement: React.FC<CollectElementProps> = ({ container, options = { required: false }, ...rest }) => {
const [element, setElement] = React.useState<CollectElement>(undefined);
const [elementValue, setElementValue] = React.useState<string>('');
Expand Down
Loading

0 comments on commit 0f71625

Please sign in to comment.