diff --git a/.github/workflows/update_references.yml b/.github/workflows/update_references.yml new file mode 100644 index 00000000000..1be0999295e --- /dev/null +++ b/.github/workflows/update_references.yml @@ -0,0 +1,47 @@ +name: Receive repository dispatch event + +on: + # Listen to a repository dispatch event by the name of `dispatch-event` + repository_dispatch: + types: [update-references] + workflow_dispatch: +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + create-pull-request: + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + + - name: Setup Node.js 20 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 20.x + + - name: Set github commit user + env: + GITHUB_EMAIL: ${{ vars.GH_EMAIL }} + GITHUB_USER: ${{ vars.GH_USER }} + run: | + git config --global user.email $GITHUB_EMAIL + git config --global user.name $GITHUB_USER + + # Set branch name to be used as environment variable + - name: Set Branch Name + run: echo "BRANCH_NAME=$(echo update-ref-$(date +%s))" >> $GITHUB_ENV + + # Create new branch, download, and commit changes to the new branch + - name: Create new branch + run: | + git checkout -b ${{ env.BRANCH_NAME }} + curl -L -o ${{ vars.REF_LOC }} ${{ vars.REMOTE_REF }} + node tasks/clean-references.mjs + git add ${{ vars.REF_LOC }} ${{ vars.CLEAN_LOC }} + git commit -m "updating references" + git push -u origin ${{ env.BRANCH_NAME }} + + # Open pull request + - name: Create Pull Request + run: gh pr create -B main -H ${{ env.BRANCH_NAME }} --title 'Merge ${{ env.BRANCH_NAME }} into main' --body 'Created by Github action' diff --git a/src/directory/apiReferences.json b/src/references/raw-references.json similarity index 100% rename from src/directory/apiReferences.json rename to src/references/raw-references.json diff --git a/tasks/clean-references.mjs b/tasks/clean-references.mjs new file mode 100644 index 00000000000..88fa07d94fc --- /dev/null +++ b/tasks/clean-references.mjs @@ -0,0 +1,167 @@ +import references from '../src/references/raw-references.json' assert { type: 'json' }; +import { writeFileSync } from 'fs'; +import { + API_CATEGORIES, + API_SUB_CATEGORIES +} from '../src/data/api-categories.mjs'; + +/** + * The purpose of this script is to create generate an object that only contains + * the desired category nodes and every node needed to generate the api documentation + * for these nodes. This is done by iterating over the needed category nodes and + * then recursively adding every node found into cleanReferences. + */ + +const cleanReferences = {}; +const categoryNodes = []; + +function recursivelyPopulateNodes(node) { + /** + * Ids to look for and populate are + * target + * type + * typeArguments[] + * types[] + * declaration->children[] + * elementType -> target + * children[] + * signatures[] + * parameters[] + * + * The above list are the ids that are looked for within each node, if any of these ids + * are found then the node is added to cleanReferences and the newly found node is traversed. + */ + if (!node) return; + + // add the current node to cleanReferences + if (node.id) { + if (cleanReferences.hasOwnProperty(node.id)) return; + cleanReferences[node.id] = node; + } + + // populate "target" + if (node.target && typeof node.target === 'number') { + recursivelyPopulateNodes(references[node.target]); + } + + // populate "type" + if (node.type) { + if (typeof node.type === 'number') { + const nextNode = references[node.type]; + recursivelyPopulateNodes(nextNode); + } else if (typeof node.type === 'object') { + recursivelyPopulateNodes(node.type); + } + } + + // populate "typeArguments" + if (node.typeArguments && Array.isArray(node.typeArguments)) { + node.typeArguments.forEach((arg) => { + if (typeof arg === 'number') { + recursivelyPopulateNodes(references[arg]); + } else if (typeof arg === 'object' && arg !== null) { + recursivelyPopulateNodes(arg); + } + }); + } + + // populate "types" + if (node.types && Array.isArray(node.types)) { + node.types.forEach((arg) => { + if (typeof arg === 'number') { + recursivelyPopulateNodes(references[arg]); + } else if (typeof arg === 'object' && arg !== null) { + recursivelyPopulateNodes(arg); + } + }); + } + + // populate "declaration.children" + if ( + node.declaration && + node.declaration.children && + Array.isArray(node.declaration.children) + ) { + node.declaration.children.forEach((arg) => { + if (typeof arg === 'number') { + recursivelyPopulateNodes(references[arg]); + } else if (typeof arg === 'object' && arg !== null) { + recursivelyPopulateNodes(arg); + } + }); + } + + // populate "elementType" + if (node.elementType && node.elementType.target) { + const elemType = node.elementType.target; + if (typeof elemType === 'number') { + recursivelyPopulateNodes(references[elemType]); + } else if (typeof elemType === 'object' && elemType !== null) { + recursivelyPopulateNodes(elemType); + } + } + + // populate "children" + if (node.children && Array.isArray(node.children)) { + node.children.forEach((arg) => { + if (typeof arg === 'number') { + recursivelyPopulateNodes(references[arg]); + } else if (typeof arg === 'object' && arg !== null) { + recursivelyPopulateNodes(arg); + } + }); + } + + // populate "signatures" + if (node.signatures && Array.isArray(node.signatures)) { + node.signatures.forEach((arg) => { + if (typeof arg === 'number') { + recursivelyPopulateNodes(references[arg]); + } else if (typeof arg === 'object' && arg !== null) { + recursivelyPopulateNodes(arg); + } + }); + } + + // populate "parameters" + if (node.parameters && Array.isArray(node.parameters)) { + node.parameters.forEach((arg) => { + if (typeof arg === 'number') { + recursivelyPopulateNodes(references[arg]); + } else if (typeof arg === 'object' && arg !== null) { + recursivelyPopulateNodes(arg); + } + }); + } +} + +const categories = Object.values(API_CATEGORIES).concat( + Object.values(API_SUB_CATEGORIES) +); + +// iterate over all categories and populate all nodes +categories.forEach((catName) => { + const catNode = references.categories.filter((cat) => { + return cat.name === catName; + })[0]; + + if (catNode) { + categoryNodes.push(catNode); + recursivelyPopulateNodes(catNode); + } +}); + +cleanReferences['categories'] = categoryNodes; + +// write the cleaned references object, this will happen as part of the +// update_references workflow and will be committed. +try { + writeFileSync( + 'src/references/references.json', + JSON.stringify(cleanReferences, null, 2), + 'utf8' + ); + console.log('Data successfully saved to disk'); +} catch (error) { + console.log('An error has occurred ', error); +}