Skip to content
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
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:
- main

jobs:
generate-react-native-sdk-refs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: main
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