From c9896f7ea16119a6c9cd12a7196f4d34716021d7 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 10:48:41 -0500 Subject: [PATCH 01/44] Push new workflow --- .github/workflows/merge-to-next-major.yml | 88 +++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 .github/workflows/merge-to-next-major.yml diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml new file mode 100644 index 00000000..fd1d16fc --- /dev/null +++ b/.github/workflows/merge-to-next-major.yml @@ -0,0 +1,88 @@ +name: Attempt to merge next to next-major +on: + workflow_dispatch: + push: + branches: + - "next" + +jobs: + # Always run. Check to see if we can merge "next" into "next-major" + check_merge: + name: check-merge + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} + persist-credentials: true + + # Attempt a dry-run merge + - name: Attempt merge + run: | + git checkout "next-major" + git merge --no-commit --no-ff origin/${{github.ref_name}} + + # Check the status and pass it off to process_merge_status + - name: Check merge status + run: | + if [ $? -eq 0 ]; then + echo "Able to successfully merge next into next-major" + exit 0 + else + echo "Not able to merge next into next-major" + exit 1 + fi + + # Run if we are able to perform a merge from next to next-major + process_merge_on_success: + name: process_merge_on_success + needs: check_merge + runs-on: ubuntu-latest + if: ${{ success() }} + + steps: + - name: Perform Merge + run: | + git checkout "next-major" + checkout_status=$? + + git merge origin/next + merge_status=$? + + git push origin "next-major" + push_status=$? + + if [ "$checkout_status" -eq 0 ] && [ "$merge_status" -eq 0 ] && [ "$push_status" -eq 0 ]; then + echo "Push to next-major succeeded" + else + exit 1 + fi + + # Run if we detected we could not perform a merge due to a conflict + process_merge_on_failure: + name: process_merge_on_failure + needs: check_merge + runs-on: ubuntu-latest + if: ${{ failure() }} + + steps: + - name: Post error message + run: + echo "I'm gonna say I couldn't merge to next-major due to a conflict" + #curl -X POST -H 'Content-type: application/json' --data '{"text":"Merge from next to next-major contains conflicts!"}' | + #${{ secrets.SLACK_WEBHOOK_URL_NEXT_MAJOR_MERGE }} + + # Run if we attempted to merge/push to next-main but were unable to do so + process_push_failure: + needs: process_merge_on_success + runs-on: ubuntu-latest + if: ${{ failure() }} + + steps: + - name: Post push error message + run: + echo "I'm gonna say I tried and failed to merge next to next-major" + #curl -X POST -H 'Content-type: application/json' --data '{"text":"Push to next-major was unsuccessful!"}' | + #${{ secrets.SLACK_WEBHOOK_URL_NEXT_MAJOR_MERGE }} From 0372e6e4b3360af0cfbb34010064dac4dda72e39 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 10:50:45 -0500 Subject: [PATCH 02/44] Remove scary github actions --- .github/workflows/release.yml | 38 ----------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 1e13808a..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Release to GitHub and NPM -on: - workflow_dispatch: - push: - branches: - - 'main' - - 'next' -env: - HUSKY: 0 -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} - persist-credentials: false - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - node-version: 'lts/*' - - name: Set explicit npm dist-tag default - if: github.ref_name == 'main' - run: echo "NPM_DIST_TAG=latest" >> $GITHUB_ENV - - name: Override npm dist-tag for non-main releases - if: github.ref_name != 'main' - run: echo "NPM_DIST_TAG=${{ github.ref_name }}" >> $GITHUB_ENV - - name: Install dependencies - run: npm ci - - name: Release to GitHub and NPM - env: - GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} # <-- Allows semantic-release-bot to push changes to protected branches - NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }} # <-- Allows semantic-release to publish to npm without 2 factor auth. - npm_config_tag: ${{ env.NPM_DIST_TAG }} # <-- For main, this is `latest.` Otherwise, `next`, `next-major`, etc. See ./.releaserc for release branch config. - run: npx semantic-release From 82f409ffe29367504d9c5747a38971efeb1bedaa Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 10:52:15 -0500 Subject: [PATCH 03/44] Update --- .github/workflows/merge-to-next-major.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index fd1d16fc..c7f920f5 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -21,6 +21,8 @@ jobs: # Attempt a dry-run merge - name: Attempt merge run: | + ls -l + git branch git checkout "next-major" git merge --no-commit --no-ff origin/${{github.ref_name}} From fa379941f074cb07dcddbafca9b8bd2838dab9c2 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 10:57:20 -0500 Subject: [PATCH 04/44] Trigger --- .github/workflows/merge-to-next-major.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index c7f920f5..361d5b86 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -6,7 +6,7 @@ on: - "next" jobs: - # Always run. Check to see if we can merge "next" into "next-major" + # Always run. Check to see if we can merge "next" into "next-major " check_merge: name: check-merge runs-on: ubuntu-latest From b1fe3bd14cc009a2276cddfec1e014c67c0d2f56 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 10:59:22 -0500 Subject: [PATCH 05/44] Trigger --- .github/workflows/merge-to-next-major.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 361d5b86..db9552d3 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -18,6 +18,12 @@ jobs: repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} persist-credentials: true + # Set user identity + - name: Set-Identity + run: | + git config --global user.email "kschriefer91@gmail.com" + git config --global user.name "kschrief" + # Attempt a dry-run merge - name: Attempt merge run: | From f5ac990601a12e6722216677013c3dd414745297 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 11:02:30 -0500 Subject: [PATCH 06/44] Trigger --- .github/workflows/merge-to-next-major.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index db9552d3..4818c549 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -51,6 +51,19 @@ jobs: if: ${{ success() }} steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} + persist-credentials: true + + # Set user identity + - name: Set-Identity + run: | + git config --global user.email "kschriefer91@gmail.com" + git config --global user.name "kschrief" + - name: Perform Merge run: | git checkout "next-major" From 806e737993d7bfb8504c4cacb5a63a2582d3f464 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 11:04:14 -0500 Subject: [PATCH 07/44] Introduce conflict --- .github/workflows/merge-to-next-major.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 4818c549..5f01860b 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -6,7 +6,7 @@ on: - "next" jobs: - # Always run. Check to see if we can merge "next" into "next-major " + # I too am a conflict check_merge: name: check-merge runs-on: ubuntu-latest From b423f5c17da5a86426f35c9c6bf20324b7d84e6e Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 23 Feb 2024 11:07:23 -0500 Subject: [PATCH 08/44] Yes. Good. --- .github/workflows/merge-to-next-major.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 5f01860b..76bae868 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -99,7 +99,7 @@ jobs: process_push_failure: needs: process_merge_on_success runs-on: ubuntu-latest - if: ${{ failure() }} + if: ${{ failure() && needs.process_merge_on_success.result != 'skipped' }} steps: - name: Post push error message From 2aa497c6074d39331501cc37c1bb856515a366bd Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 11:43:42 -0500 Subject: [PATCH 09/44] Get version number --- .github/workflows/merge-to-next-major.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 76bae868..c7e7bb65 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -24,6 +24,14 @@ jobs: git config --global user.email "kschriefer91@gmail.com" git config --global user.name "kschrief" + # Get the "next" version number + - name: Extract next version + id: extract_version + run: echo "::set-output name=version::$(node -e 'console.log(require(./package.json).version)')" + + - name: Display version number + run: echo "Version is ${{ steps.extract_version.outputs.version }}" + # Attempt a dry-run merge - name: Attempt merge run: | From 337d36ef2e4d6ed560d1f2b3c6294501cc9615e1 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 11:44:50 -0500 Subject: [PATCH 10/44] Get version number --- .github/workflows/merge-to-next-major.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index c7e7bb65..1aa5c357 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -27,7 +27,7 @@ jobs: # Get the "next" version number - name: Extract next version id: extract_version - run: echo "::set-output name=version::$(node -e 'console.log(require(./package.json).version)')" + run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" - name: Display version number run: echo "Version is ${{ steps.extract_version.outputs.version }}" From 90895c6d3449428f5709342900db2b37868be99c Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 11:52:21 -0500 Subject: [PATCH 11/44] Get version number --- .github/workflows/merge-to-next-major.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 1aa5c357..5bea0272 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -29,15 +29,23 @@ jobs: id: extract_version run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" - - name: Display version number - run: echo "Version is ${{ steps.extract_version.outputs.version }}" + # Checkout "next-major" + - name: Checkout next-major + run: git checkout "next-major" + + # Update package.json version + - name: Update next-major package.json + run: | + jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json + mv temp.json package.json + + # Temp - Print package.json + - name: Temp - Print package.json + run: cat package.json # Attempt a dry-run merge - name: Attempt merge run: | - ls -l - git branch - git checkout "next-major" git merge --no-commit --no-ff origin/${{github.ref_name}} # Check the status and pass it off to process_merge_status From d829527329c2b7435dd427ab4ff28dbaa1ff298b Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 12:01:33 -0500 Subject: [PATCH 12/44] Commit version change --- .github/workflows/merge-to-next-major.yml | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 5bea0272..0e5809f8 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -39,10 +39,6 @@ jobs: jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json mv temp.json package.json - # Temp - Print package.json - - name: Temp - Print package.json - run: cat package.json - # Attempt a dry-run merge - name: Attempt merge run: | @@ -80,18 +76,30 @@ jobs: git config --global user.email "kschriefer91@gmail.com" git config --global user.name "kschrief" - - name: Perform Merge + # Get the "next" version number + - name: Extract next version + id: extract_version + run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" + + - name: Checkout next-major + run: git checkout "next-major" + + # Update package.json version + - name: Update next-major package.json run: | - git checkout "next-major" - checkout_status=$? + jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json + mv temp.json package.json + git commit -m "Sync next->next-major package.json" + - name: Perform Merge + run: | git merge origin/next merge_status=$? git push origin "next-major" push_status=$? - if [ "$checkout_status" -eq 0 ] && [ "$merge_status" -eq 0 ] && [ "$push_status" -eq 0 ]; then + if [ "$merge_status" -eq 0 ] && [ "$push_status" -eq 0 ]; then echo "Push to next-major succeeded" else exit 1 From 3cdbd3c407d567c283f11d05490a7bb24b438fce Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 12:02:38 -0500 Subject: [PATCH 13/44] Commit version change --- .github/workflows/merge-to-next-major.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 0e5809f8..7e002663 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -34,10 +34,10 @@ jobs: run: git checkout "next-major" # Update package.json version - - name: Update next-major package.json - run: | - jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - mv temp.json package.json + #- name: Update next-major package.json + # run: | + # jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json + # mv temp.json package.json # Attempt a dry-run merge - name: Attempt merge From 814e1b58a494d6c8d5ad02e6a4d9146c5bceae99 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 12:04:17 -0500 Subject: [PATCH 14/44] Commit version change --- .github/workflows/merge-to-next-major.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 7e002663..c9fed7f3 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -34,10 +34,10 @@ jobs: run: git checkout "next-major" # Update package.json version - #- name: Update next-major package.json - # run: | - # jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - # mv temp.json package.json + - name: Update next-major package.json + run: | + jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json + mv temp.json package.json # Attempt a dry-run merge - name: Attempt merge @@ -89,6 +89,7 @@ jobs: run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json mv temp.json package.json + git add package.json git commit -m "Sync next->next-major package.json" - name: Perform Merge From 37a11a0465236bdef530bf531490d056c855eea3 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 12:06:15 -0500 Subject: [PATCH 15/44] Exit 0 --- .github/workflows/merge-to-next-major.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index c9fed7f3..96b7e579 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -102,6 +102,7 @@ jobs: if [ "$merge_status" -eq 0 ] && [ "$push_status" -eq 0 ]; then echo "Push to next-major succeeded" + exit 0 else exit 1 fi From a6bd102cc50cb2e8a7675dd604d557586229cbee Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:15:14 -0500 Subject: [PATCH 16/44] Versions --- .github/workflows/merge-to-next-major.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 96b7e579..07dbc9a2 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -88,9 +88,16 @@ jobs: - name: Update next-major package.json run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - mv temp.json package.json - git add package.json - git commit -m "Sync next->next-major package.json" + + #Commit if there was a difference + if diff -q "package.json" "temp.json" > /dev/null; then + mv temp.json package.json + git add package.json + git commit -m "Sync next->next-major package.json" + else + echo "Versions are identical. No update required." + rm temp.json + fi - name: Perform Merge run: | From 70025d4be65a45be30333b2d2a0429e198bffa93 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:17:07 -0500 Subject: [PATCH 17/44] Versions --- .github/workflows/merge-to-next-major.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 07dbc9a2..e502f506 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -89,15 +89,8 @@ jobs: run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - #Commit if there was a difference - if diff -q "package.json" "temp.json" > /dev/null; then - mv temp.json package.json - git add package.json - git commit -m "Sync next->next-major package.json" - else - echo "Versions are identical. No update required." - rm temp.json - fi + mv temp.json package.json + git add package.json && git commit -m "Sync next->next-major package.json" - name: Perform Merge run: | From 39fe788ccb0ee79f17a8afa9d80db3c88a26d7c9 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:20:18 -0500 Subject: [PATCH 18/44] Versions --- .github/workflows/merge-to-next-major.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index e502f506..20a15d19 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -89,8 +89,14 @@ jobs: run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - mv temp.json package.json - git add package.json && git commit -m "Sync next->next-major package.json" + diff -q "package.json" "temp.json" + + if [ "$?" -eq 0 ]; then + mv temp.json package.json + git add package.json && git commit -m "Sync next->next-major package.json" + else + echo "Versions are identical. No change required." + fi - name: Perform Merge run: | From 9849b7cf6157487d621af1d8b2ed2567a2d7db4a Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:21:09 -0500 Subject: [PATCH 19/44] Versions --- .github/workflows/merge-to-next-major.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 20a15d19..df8cc5de 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -91,7 +91,7 @@ jobs: diff -q "package.json" "temp.json" - if [ "$?" -eq 0 ]; then + if [ "$?" -ne 0 ]; then mv temp.json package.json git add package.json && git commit -m "Sync next->next-major package.json" else From 63c4013de2b7cb5b1c111d2a0904d62922dc557c Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:22:38 -0500 Subject: [PATCH 20/44] Conflict --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cafd1855..b7c557ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@firebolt-js/openrpc", - "version": "2.3.0-next.1", + "version": "2.3.0-next.2", "description": "The Firebolt SDK Code & Doc Generator", "main": "languages/javascript/src/sdk.mjs", "type": "module", From cf09ec1304dae3d270726b5296b4b7dbce91523d Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:24:31 -0500 Subject: [PATCH 21/44] Conflict --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b7c557ae..87facaa5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@firebolt-js/openrpc", - "version": "2.3.0-next.2", + "version": "2.3.0-next.3", "description": "The Firebolt SDK Code & Doc Generator", "main": "languages/javascript/src/sdk.mjs", "type": "module", From dddf189f5a3039bbc20a0d288fac54bf6a2d74ae Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:25:44 -0500 Subject: [PATCH 22/44] Conflict --- .github/workflows/merge-to-next-major.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index df8cc5de..572ca68f 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -37,7 +37,16 @@ jobs: - name: Update next-major package.json run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - mv temp.json package.json + + diff -q "package.json" "temp.json" + + if [ "$?" -ne 0 ]; then + mv temp.json package.json + git add package.json && git commit -m "Sync next->next-major package.json" + else + echo "Versions are identical. No change required." + rm temp.json + fi # Attempt a dry-run merge - name: Attempt merge @@ -96,6 +105,7 @@ jobs: git add package.json && git commit -m "Sync next->next-major package.json" else echo "Versions are identical. No change required." + rm temp.json fi - name: Perform Merge From 0848c869ac40ffdefab34c4563c627d1b38993a8 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:28:03 -0500 Subject: [PATCH 23/44] Conflict --- .github/workflows/merge-to-next-major.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 572ca68f..2b401e9a 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -38,14 +38,12 @@ jobs: run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - diff -q "package.json" "temp.json" - - if [ "$?" -ne 0 ]; then - mv temp.json package.json - git add package.json && git commit -m "Sync next->next-major package.json" - else + if diff -q "package.json" "temp.json" >/dev/null; then echo "Versions are identical. No change required." rm temp.json + else + mv temp.json package.json + git add package.json && git commit -m "Sync next->next-major package.json" fi # Attempt a dry-run merge From e6171a99a7beda4f8964de91f3e359d6b5a63f83 Mon Sep 17 00:00:00 2001 From: kschrief Date: Tue, 27 Feb 2024 13:28:54 -0500 Subject: [PATCH 24/44] Conflict --- .github/workflows/merge-to-next-major.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 2b401e9a..52c61f94 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -96,14 +96,12 @@ jobs: run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - diff -q "package.json" "temp.json" - - if [ "$?" -ne 0 ]; then - mv temp.json package.json - git add package.json && git commit -m "Sync next->next-major package.json" - else + if diff -q "package.json" "temp.json" >/dev/null; then echo "Versions are identical. No change required." rm temp.json + else + mv temp.json package.json + git add package.json && git commit -m "Sync next->next-major package.json" fi - name: Perform Merge From fa25feb0a58b9aceed71664f60eda86c5865a8d9 Mon Sep 17 00:00:00 2001 From: kschrief Date: Wed, 28 Feb 2024 10:38:34 -0500 Subject: [PATCH 25/44] Finishing touches --- .github/workflows/merge-to-next-major.yml | 62 +++++++++-------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 52c61f94..141b3b2e 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -6,7 +6,7 @@ on: - "next" jobs: - # I too am a conflict + # Check if next can merge into next-major check_merge: name: check-merge runs-on: ubuntu-latest @@ -21,8 +21,8 @@ jobs: # Set user identity - name: Set-Identity run: | - git config --global user.email "kschriefer91@gmail.com" - git config --global user.name "kschrief" + git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" + git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" # Get the "next" version number - name: Extract next version @@ -33,8 +33,8 @@ jobs: - name: Checkout next-major run: git checkout "next-major" - # Update package.json version - - name: Update next-major package.json + # Update "next-major" package.json to match "next" + - name: Update "next-major" package.json to match "next" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -43,28 +43,18 @@ jobs: rm temp.json else mv temp.json package.json - git add package.json && git commit -m "Sync next->next-major package.json" + git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" fi # Attempt a dry-run merge - - name: Attempt merge + - name: Attempt a dry-run merge run: | git merge --no-commit --no-ff origin/${{github.ref_name}} + exit $? - # Check the status and pass it off to process_merge_status - - name: Check merge status - run: | - if [ $? -eq 0 ]; then - echo "Able to successfully merge next into next-major" - exit 0 - else - echo "Not able to merge next into next-major" - exit 1 - fi - - # Run if we are able to perform a merge from next to next-major + # Attempt to merge to next-major if our dry-run succeeded process_merge_on_success: - name: process_merge_on_success + name: Perform merge from "next" to "next-major" needs: check_merge runs-on: ubuntu-latest if: ${{ success() }} @@ -80,19 +70,20 @@ jobs: # Set user identity - name: Set-Identity run: | - git config --global user.email "kschriefer91@gmail.com" - git config --global user.name "kschrief" + git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" + git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" # Get the "next" version number - name: Extract next version id: extract_version run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" + # Checkout "next-major" - name: Checkout next-major run: git checkout "next-major" - # Update package.json version - - name: Update next-major package.json + # Update "next-major" package.json to match "next" + - name: Update "next-major" package.json to match "next" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -104,7 +95,7 @@ jobs: git add package.json && git commit -m "Sync next->next-major package.json" fi - - name: Perform Merge + - name: Perform the merge from next to next-major run: | git merge origin/next merge_status=$? @@ -119,29 +110,24 @@ jobs: exit 1 fi - # Run if we detected we could not perform a merge due to a conflict + # If the merge cannot be performed, let stakeholders know process_merge_on_failure: - name: process_merge_on_failure + name: Merge dry-run failure needs: check_merge runs-on: ubuntu-latest if: ${{ failure() }} steps: - - name: Post error message - run: - echo "I'm gonna say I couldn't merge to next-major due to a conflict" - #curl -X POST -H 'Content-type: application/json' --data '{"text":"Merge from next to next-major contains conflicts!"}' | - #${{ secrets.SLACK_WEBHOOK_URL_NEXT_MAJOR_MERGE }} + - name: Post error message (To-Do) + run: echo "Next cannot be merged into next-major cleanly" - # Run if we attempted to merge/push to next-main but were unable to do so + # If we attempted to merge/push to next-main but there was a failure process_push_failure: + name: Merge failure needs: process_merge_on_success runs-on: ubuntu-latest if: ${{ failure() && needs.process_merge_on_success.result != 'skipped' }} steps: - - name: Post push error message - run: - echo "I'm gonna say I tried and failed to merge next to next-major" - #curl -X POST -H 'Content-type: application/json' --data '{"text":"Push to next-major was unsuccessful!"}' | - #${{ secrets.SLACK_WEBHOOK_URL_NEXT_MAJOR_MERGE }} + - name: Post error message (To-Do) + run: echo "There was a failure when merging next into next-major" From b2a5c5f7061621b5f6fb5e089fc697704c1aa7da Mon Sep 17 00:00:00 2001 From: kschrief Date: Wed, 28 Feb 2024 10:39:19 -0500 Subject: [PATCH 26/44] Finishing touches --- .github/workflows/merge-to-next-major.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 141b3b2e..d5cb205e 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -8,7 +8,7 @@ on: jobs: # Check if next can merge into next-major check_merge: - name: check-merge + name: Check if "next" can merge into "next-major" runs-on: ubuntu-latest steps: - name: Checkout From d4690bad2f49dbc21aeca62e0814aeeba3379125 Mon Sep 17 00:00:00 2001 From: kschrief Date: Wed, 28 Feb 2024 10:44:26 -0500 Subject: [PATCH 27/44] Merge to main --- .github/workflows/merge-to-main.yml | 94 +++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 .github/workflows/merge-to-main.yml diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml new file mode 100644 index 00000000..edbc5ea1 --- /dev/null +++ b/.github/workflows/merge-to-main.yml @@ -0,0 +1,94 @@ +name: Attempt to merge next to main +on: + workflow_dispatch: + +jobs: + # Check if next can merge into main + check_merge: + name: Check if "next" can merge into "main" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} + persist-credentials: true + + # Set user identity + - name: Set-Identity + run: | + git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" + git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" + + # Checkout "main" + - name: Checkout main + run: git checkout "main" + + # Attempt a dry-run merge + - name: Attempt a dry-run merge + run: | + git merge --no-commit --no-ff origin/${{github.ref_name}} + exit $? + + # Attempt to merge to main if our dry-run succeeded + process_merge_on_success: + name: Perform merge from "next" to "main" + needs: check_merge + runs-on: ubuntu-latest + if: ${{ success() }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} + persist-credentials: true + + # Set user identity + - name: Set-Identity + run: | + git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" + git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" + + # Checkout "main" + - name: Checkout main + run: git checkout "main" + + - name: Perform the merge from next to main + run: | + git merge origin/next + merge_status=$? + + git push origin "main" + push_status=$? + + if [ "$merge_status" -eq 0 ] && [ "$push_status" -eq 0 ]; then + echo "Push to main succeeded" + exit 0 + else + exit 1 + fi + + # If the merge cannot be performed, let stakeholders know + process_merge_on_failure: + name: Merge dry-run failure + needs: check_merge + runs-on: ubuntu-latest + if: ${{ failure() }} + + steps: + - name: Post error message (To-Do) + run: echo "Next cannot be merged into main cleanly" + + # If we attempted to merge/push to next-main but there was a failure + process_push_failure: + name: Merge failure + needs: process_merge_on_success + runs-on: ubuntu-latest + if: ${{ failure() && needs.process_merge_on_success.result != 'skipped' }} + + steps: + - name: Post error message (To-Do) + run: echo "There was a failure when merging next into main" From e67ba1fe879675c1191c8cd16e1565826dd58341 Mon Sep 17 00:00:00 2001 From: kschrief Date: Wed, 28 Feb 2024 11:43:55 -0500 Subject: [PATCH 28/44] Change next->main script --- .github/workflows/merge-to-main.yml | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index edbc5ea1..14b46fe2 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -21,10 +21,28 @@ jobs: git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" + # Get the "next" version number + - name: Extract next version + id: extract_version + run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" + # Checkout "main" - name: Checkout main run: git checkout "main" + # Update "main" package.json to match "next" + - name: Update "main" package.json to match "next" + run: | + jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json + + if diff -q "package.json" "temp.json" >/dev/null; then + echo "Versions are identical. No change required." + rm temp.json + else + mv temp.json package.json + git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" + fi + # Attempt a dry-run merge - name: Attempt a dry-run merge run: | @@ -52,10 +70,28 @@ jobs: git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" + # Get the "next" version number + - name: Extract next version + id: extract_version + run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" + # Checkout "main" - name: Checkout main run: git checkout "main" + # Update "main" package.json to match "next" + - name: Update "main" package.json to match "next" + run: | + jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json + + if diff -q "package.json" "temp.json" >/dev/null; then + echo "Versions are identical. No change required." + rm temp.json + else + mv temp.json package.json + git add package.json && git commit -m "Sync next->main package.json" + fi + - name: Perform the merge from next to main run: | git merge origin/next From 682a75065a75d87158bd8e1194a508987d2eddcd Mon Sep 17 00:00:00 2001 From: kschrief Date: Wed, 28 Feb 2024 11:47:45 -0500 Subject: [PATCH 29/44] Better commit message --- .github/workflows/merge-to-main.yml | 13 ++++++++----- .github/workflows/merge-to-next-major.yml | 10 +++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index 14b46fe2..aaee22f0 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -1,6 +1,9 @@ name: Attempt to merge next to main on: workflow_dispatch: + push: + branches: + - "next" jobs: # Check if next can merge into main @@ -30,8 +33,8 @@ jobs: - name: Checkout main run: git checkout "main" - # Update "main" package.json to match "next" - - name: Update "main" package.json to match "next" + # Update "main" version to match "next" + - name: Update "main" version to match "next" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -79,8 +82,8 @@ jobs: - name: Checkout main run: git checkout "main" - # Update "main" package.json to match "next" - - name: Update "main" package.json to match "next" + # Update "main" version to match "next" + - name: Update "main" version to match "next" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -89,7 +92,7 @@ jobs: rm temp.json else mv temp.json package.json - git add package.json && git commit -m "Sync next->main package.json" + git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" fi - name: Perform the merge from next to main diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index d5cb205e..0b6bfd4f 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -33,8 +33,8 @@ jobs: - name: Checkout next-major run: git checkout "next-major" - # Update "next-major" package.json to match "next" - - name: Update "next-major" package.json to match "next" + # Update "next-major" version to match "next" + - name: Update "next-major" version to match "next" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -82,8 +82,8 @@ jobs: - name: Checkout next-major run: git checkout "next-major" - # Update "next-major" package.json to match "next" - - name: Update "next-major" package.json to match "next" + # Update "next-major" version to match "next" + - name: Update "next-major" version to match "next" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -92,7 +92,7 @@ jobs: rm temp.json else mv temp.json package.json - git add package.json && git commit -m "Sync next->next-major package.json" + git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" fi - name: Perform the merge from next to next-major From 8aab3dfbd347c7027a249a1a91b7640ba7ce612f Mon Sep 17 00:00:00 2001 From: kschrief Date: Wed, 28 Feb 2024 11:48:41 -0500 Subject: [PATCH 30/44] Better commit message --- .github/workflows/merge-to-main.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index aaee22f0..d80d699f 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -1,9 +1,6 @@ name: Attempt to merge next to main on: workflow_dispatch: - push: - branches: - - "next" jobs: # Check if next can merge into main From 3b81a54cbef281b5792f6061f0e3faa01889fea3 Mon Sep 17 00:00:00 2001 From: kschrief Date: Fri, 8 Mar 2024 10:52:06 -0500 Subject: [PATCH 31/44] Reverse temporary changes --- .github/workflows/release.yml | 38 +++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..1e13808a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,38 @@ +name: Release to GitHub and NPM +on: + workflow_dispatch: + push: + branches: + - 'main' + - 'next' +env: + HUSKY: 0 +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + repo-token: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} + persist-credentials: false + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: 'lts/*' + - name: Set explicit npm dist-tag default + if: github.ref_name == 'main' + run: echo "NPM_DIST_TAG=latest" >> $GITHUB_ENV + - name: Override npm dist-tag for non-main releases + if: github.ref_name != 'main' + run: echo "NPM_DIST_TAG=${{ github.ref_name }}" >> $GITHUB_ENV + - name: Install dependencies + run: npm ci + - name: Release to GitHub and NPM + env: + GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_BOT_PAT }} # <-- Allows semantic-release-bot to push changes to protected branches + NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_NPM_TOKEN }} # <-- Allows semantic-release to publish to npm without 2 factor auth. + npm_config_tag: ${{ env.NPM_DIST_TAG }} # <-- For main, this is `latest.` Otherwise, `next`, `next-major`, etc. See ./.releaserc for release branch config. + run: npx semantic-release diff --git a/package.json b/package.json index 87facaa5..cafd1855 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@firebolt-js/openrpc", - "version": "2.3.0-next.3", + "version": "2.3.0-next.1", "description": "The Firebolt SDK Code & Doc Generator", "main": "languages/javascript/src/sdk.mjs", "type": "module", From b126834f640361eb14bb054b1dc279060d620d6b Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Tue, 19 Mar 2024 13:07:54 -0400 Subject: [PATCH 32/44] feat: App Pass-through --- package.json | 4 +- src/firebolt-openrpc.json | 37 +++++++ src/macrofier/engine.mjs | 6 +- src/openrpc/index.mjs | 15 ++- src/shared/modules.mjs | 203 +++++++++++++++++++++++++++++++++++--- src/validate/index.mjs | 4 +- 6 files changed, 245 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index cafd1855..38c3fa89 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ ], "license": "Apache-2.0", "dependencies": { - "ajv": "^8.3.0", - "ajv-formats": "^2.1.0", + "ajv": "^8.12.0", + "ajv-formats": "^2.1.1", "array.prototype.groupby": "^1.1.0", "crocks": "^0.12.4", "deepmerge": "^4.2.2", diff --git a/src/firebolt-openrpc.json b/src/firebolt-openrpc.json index 67cf5d8a..e2c2abc8 100644 --- a/src/firebolt-openrpc.json +++ b/src/firebolt-openrpc.json @@ -1007,8 +1007,45 @@ }, "x-error-for": { "type": "string" + }, + "x-provided-by": { + "type": "string" } }, + "if": { + "required": [ + "x-provided-by" + ] + }, + "then": { + "not": { + "required": [ + "x-provides" + ] + }, + "oneOf": [ + { + "required": [ "x-manages"], + "properties": { + "x-manages": { + "type": "array", + "minItems": 1, + "maxItems": 1 + } + } + }, + { + "required": [ "x-uses"], + "properties": { + "x-uses": { + "type": "array", + "minItems": 1, + "maxItems": 1 + } + } + } + ] + }, "anyOf": [ { "required": [ "x-uses"] diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 3f7596ec..49bda56e 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -754,7 +754,7 @@ function generateSchemas(json, templates, options) { const schemas = JSON.parse(JSON.stringify(json.definitions || (json.components && json.components.schemas) || {})) const generate = (name, schema, uri, { prefix = '' } = {}) => { - // these are internal schemas used by the firebolt-openrpc tooling, and not meant to be used in code/doc generation + // these are internal schemas used by the fireboltize-openrpc tooling, and not meant to be used in code/doc generation if (['ListenResponse', 'ProviderRequest', 'ProviderResponse', 'FederatedResponse', 'FederatedRequest'].includes(name)) { return } @@ -1132,7 +1132,7 @@ function insertMethodMacros(template, methodObj, json, templates, examples = {}) const subscriber = json.methods.find(method => method.tags.find(tag => tag['x-alternative'] === methodObj.name)) const subscriberTemplate = (subscriber ? insertMethodMacros(getTemplate('/codeblocks/subscriber', templates), subscriber, json, templates, examples) : '') const setterFor = methodObj.tags.find(t => t.name === 'setter') && methodObj.tags.find(t => t.name === 'setter')['x-setter-for'] || '' - const pullsResult = (puller || pullsFor) ? localizeDependencies(pullsFor || methodObj, json).params[1].schema : null + const pullsResult = (puller || pullsFor) ? localizeDependencies(pullsFor || methodObj, json).params.findLast(x=>true).schema : null const pullsParams = (puller || pullsFor) ? localizeDependencies(getPayloadFromEvent(puller || methodObj), json, null, { mergeAllOfs: true }).properties.parameters : null const pullsResultType = pullsResult && types.getSchemaShape(pullsResult, json, { destination: state.destination, section: state.section }) const pullsForType = pullsResult && types.getSchemaType(pullsResult, json, { destination: state.destination, section: state.section }) @@ -1467,7 +1467,7 @@ function generateProviderInterfaces(json, templates) { function insertProviderInterfaceMacros(template, capability, moduleJson = {}, templates) { const iface = getProviderInterface(capability, moduleJson, { destination: state.destination, section: state.section })//.map(method => { method.name = method.name.charAt(9).toLowerCase() + method.name.substr(10); return method } ) - const uglyName = capability.split(":").slice(-2).map(capitalize).reverse().join('') + "Provider" + const uglyName = capability.split(':').slice(-2).map(capitalize).map(x => x.split('-').map(capitalize).join('')).reverse().join('') + "Provider" let name = iface.length === 1 ? iface[0].name.charAt(0).toUpperCase() + iface[0].name.substr(1) + "Provider" : uglyName if (moduleJson.info['x-interface-names']) { diff --git a/src/openrpc/index.mjs b/src/openrpc/index.mjs index e0819b7f..5399431d 100644 --- a/src/openrpc/index.mjs +++ b/src/openrpc/index.mjs @@ -65,7 +65,7 @@ const run = async ({ json = addExternalMarkdown(json, markdown) // put module name in front of each method - json.methods.forEach(method => method.name = json.info.title + '.' + method.name) + json.methods.forEach(method => method.name = method.name.includes('\.') ? method.name : json.info.title + '.' + method.name) // merge any info['x-'] extension values (maps & arrays only..) Object.keys(json.info).filter(key => key.startsWith('x-')).forEach(extension => { @@ -101,6 +101,19 @@ const run = async ({ logSuccess(`Generated the ${json.info.title} module.`) }) + // make sure all provided-by APIs point to a real provider method + const appProvided = openrpc.methods.filter(m => m.tags.find(t=>t['x-provided-by'])) || [] + appProvided.forEach(m => { + const providedBy = m.tags.find(t=>t['x-provided-by'])['x-provided-by'] + const provider = openrpc.methods.find(m => m.name === providedBy) + if (!provider) { + throw `Method ${m.name} is provided by an undefined method (${providedBy})` + } + else { + console.log(`Method ${m.name} is provided by ${providedBy}`) + } + }) + await writeJson(output, openrpc) console.log() diff --git a/src/shared/modules.mjs b/src/shared/modules.mjs index 095acd87..f878ff6b 100644 --- a/src/shared/modules.mjs +++ b/src/shared/modules.mjs @@ -376,13 +376,18 @@ const eventDefaults = event => { return event } -const createEventResultSchemaFromProperty = property => { +const createEventResultSchemaFromProperty = (property, type='') => { const subscriberType = property.tags.map(t => t['x-subscriber-type']).find(t => typeof t === 'string') || 'context' - if (property.tags.find(t => (t.name == 'property' || t.name.startsWith('property:')) && (subscriberType === 'global'))) { + const caps = property.tags.find(t => t.name === 'capabilities') + let name = caps['x-provided-by'] ? caps['x-provided-by'].split('.').pop().replace('onRequest', '') : property.name + name = name.charAt(0).toUpperCase() + name.substring(1) + + + if ( subscriberType === 'global') { // wrap the existing result and the params in a new result object const schema = { - title: property.name.charAt(0).toUpperCase() + property.name.substring(1) + 'ChangedInfo', + title: name + type + 'Info', type: "object", properties: { @@ -400,27 +405,32 @@ const createEventResultSchemaFromProperty = property => { schema.properties[property.result.name] = property.result.schema !schema.required.includes(property.result.name) && schema.required.push(property.result.name) - return schema } } -const createEventFromProperty = property => { +const createEventFromProperty = (property, type='', alternative, json) => { + const provider = (property.tags.find(t => t['x-provided-by']) || {})['x-provided-by'] + const pusher = provider ? provider.replace('onRequest', '').split('.').map((x, i, arr) => (i === arr.length-1) ? x.charAt(0).toLowerCase() + x.substr(1) : x).join('.') : undefined const event = eventDefaults(JSON.parse(JSON.stringify(property))) - event.name = 'on' + event.name.charAt(0).toUpperCase() + event.name.substr(1) + 'Changed' +// event.name = (module ? module + '.' : '') + 'on' + event.name.charAt(0).toUpperCase() + event.name.substr(1) + type + event.name = provider ? provider.split('.').pop().replace('onRequest', '') : event.name.charAt(0).toUpperCase() + event.name.substr(1) + type + event.name = event.name.split('.').map((x, i, arr) => (i === arr.length-1) ? 'on' + x.charAt(0).toUpperCase() + x.substr(1) : x).join('.') + const subscriberFor = pusher || (json.info.title + '.' + property.name) + const old_tags = property.tags.concat() - event.tags[0]['x-alternative'] = property.name + alternative && (event.tags[0]['x-alternative'] = alternative) - event.tags.unshift({ + !provider && event.tags.unshift({ name: "subscriber", - 'x-subscriber-for': property.name + 'x-subscriber-for': subscriberFor }) const subscriberType = property.tags.map(t => t['x-subscriber-type']).find(t => typeof t === 'string') || 'context' // if the subscriber type is global, zap all of the parameters and change the result type to the schema that includes them - if (old_tags.find(t => (t.name == 'property' || t.name.startsWith('property:')) && (subscriberType === 'global'))) { + if (subscriberType === 'global') { // wrap the existing result and the params in a new result object const result = { @@ -448,15 +458,60 @@ const createEventFromProperty = property => { } old_tags.forEach(t => { - if (t.name !== 'property' && !t.name.startsWith('property:')) + if (t.name !== 'property' && !t.name.startsWith('property:') && t.name !== 'push-pull' & t.name !== 'requestor') { event.tags.push(t) } }) + provider && (event.tags.find(t => t.name === 'capabilities')['x-provided-by'] = subscriberFor) + return event } +const createPushFromRequestor = (requestor, json) => { + const push = JSON.parse(JSON.stringify(requestor)) + + const caps = push.tags.find(t => t.name === 'capabilities') + push.name = caps['x-provided-by'].replace('onRequest', '') + delete caps['x-provided-by'] + push.name = push.name.split('.').map( (x, i, arr) => (i === arr.length -1) ? x.charAt(0).toLowerCase() + x.substr(1) : x).join('.') + + caps['x-provides'] = caps['x-uses'].pop() + delete caps['x-uses'] + + push.tags = push.tags.filter(t => t.name !== 'push-pull') + push.tags.push({ + name: "push" + }) + + requestor.tags.find(t => t.name === 'push-pull').name = 'requestor' + + push.result.required = true + push.params.push(push.result) + + push.result = { + "name": "result", + "schema": { + "type": "null" + } + } + + push.examples.forEach(example => { + example.params.push(example.result) + example.result = { + "name": "result", + "value": null + } + }) + + return push +} + +const createPushEvent = (requestor, json) => { + return createEventFromProperty(requestor, '', undefined, json) +} + const createPullEventFromPush = (pusher, json) => { const event = eventDefaults(JSON.parse(JSON.stringify(pusher))) event.params = [] @@ -487,7 +542,73 @@ const createPullEventFromPush = (pusher, json) => { }) old_tags.forEach(t => { - if (t.name !== 'polymorphic-pull') + if (t.name !== 'polymorphic-pull' && t.name) + { + event.tags.push(t) + } + }) + + return event +} + +const createPullProvider = (pusher, json) => { + const event = eventDefaults(JSON.parse(JSON.stringify(pusher))) + // insert the method prefix on the last particle of the method name + event.name = event.name.split('.').map((x, i, arr) => (i === arr.length-1) ? 'onRequest' + x.charAt(0).toUpperCase() + x.substr(1) : x).join('.') + const old_tags = pusher.tags.concat() + + const value = event.params.pop() + + event.tags[0]['x-pulls-for'] = pusher.name + event.tags[0]['x-response'] = value.schema + event.tags[0]['x-response'].examples = event.examples.map(e => e.params.pop().value) + + event.result = { + "name": "request", + "schema": { + "type": "object", + "required": ["correlationId", "parameters"], + "properties":{ + "correlationId": { + "type": "string", + }, + "parameters": { + "type": "object", + "required": [], + "properties": { + } + } + }, + "additionalProperties": false + } + } + + event.params.forEach(p => { + event.result.schema.properties.parameters.properties[p.name] = p.schema + if (p.required) { + event.result.schema.properties.parameters.required.push(p.name) + } + }) + + event.params = [] + + event.examples = event.examples.map(example => { + example.result = { + "name": "request", + "value": { + "correlationId": "xyz", + "parameters": {} + } + } + example.params.forEach(p => { + example.result.value.parameters[p.name] = p.value + }) + example.params = [] + return example + }) + + old_tags.forEach(t => { + if (t.name !== 'push-pull') { event.tags.push(t) } @@ -496,6 +617,34 @@ const createPullEventFromPush = (pusher, json) => { return event } +const createPullRequestor = (pusher, json) => { + const module = pusher.tags.find(t => t.name === 'push-pull')['x-requesting-interface'] + const requestor = JSON.parse(JSON.stringify(pusher)) + requestor.name = (module ? module + '.' : '') + 'request' + requestor.name.charAt(0).toUpperCase() + requestor.name.substr(1) + + const value = requestor.params.pop() + delete value.required + + requestor.tags = requestor.tags.filter(t => t.name !== 'push-pull') + requestor.tags.unshift({ + "name": "requestor", + "x-requestor-for": json.info.title + '.' + pusher.name + }) + const caps = requestor.tags.find(t => t.name === 'capabilities') + caps['x-provided-by'] = json.info.title + '.' + pusher.name + caps['x-uses'] = [ caps['x-provides'] ] + delete caps['x-provides'] + + requestor.tags.find(t => t.name === 'capabilities')['x-provided-by'] = json.info.title + '.' + pusher.name + requestor.result = value + + requestor.examples.forEach(example => { + example.result = example.params.pop() + }) + + return requestor +} + const createTemporalEventMethod = (method, json, name) => { const event = createEventFromMethod(method, json, name, 'x-temporal-for', ['temporal-set']) @@ -810,15 +959,15 @@ const generatePropertyEvents = json => { const readonlies = json.methods.filter( m => m.tags && m.tags.find( t => t.name == 'property:readonly')) || [] properties.forEach(property => { - json.methods.push(createEventFromProperty(property)) - const schema = createEventResultSchemaFromProperty(property) + json.methods.push(createEventFromProperty(property, 'Changed', property.name, json)) + const schema = createEventResultSchemaFromProperty(property, 'Changed') if (schema) { json.components.schemas[schema.title] = schema } }) readonlies.forEach(property => { - json.methods.push(createEventFromProperty(property)) - const schema = createEventResultSchemaFromProperty(property) + json.methods.push(createEventFromProperty(property, 'Changed', property.name, json)) + const schema = createEventResultSchemaFromProperty(property, 'Changed') if (schema) { json.components.schemas[schema.title] = schema } @@ -843,6 +992,27 @@ const generatePolymorphicPullEvents = json => { return json } +const generatePushPullMethods = json => { + const requestors = json.methods.filter( m => m.tags && m.tags.find( t => t.name == 'push-pull')) || [] + const pushers = requestors.map(m => createPushFromRequestor(m, json)) + pushers.forEach(m => json.methods.push(m)) + + pushers.forEach(pusher => json.methods.push(createPullProvider(pusher))) + requestors.forEach(requestor => json.methods.push(createPushEvent(requestor, json))) + +// pushers.forEach(property => json.methods.push(createPullRequestor(property, json))) + requestors.forEach(requestor => { + const schema = createEventResultSchemaFromProperty(requestor) + if (schema) { + json.components = json.components || {} + json.components.schemas = json.components.schemas || {} + json.components.schemas[schema.title] = schema + } + }) + + return json +} + const generateTemporalSetMethods = json => { const temporals = json.methods.filter( m => m.tags && m.tags.find( t => t.name == 'temporal-set')) || [] @@ -1083,6 +1253,7 @@ const getPathFromModule = (module, path) => { const fireboltize = (json) => { json = generatePropertyEvents(json) json = generatePropertySetters(json) + json = generatePushPullMethods(json) json = generatePolymorphicPullEvents(json) json = generateProviderMethods(json) json = generateTemporalSetMethods(json) diff --git a/src/validate/index.mjs b/src/validate/index.mjs index 33cc6aea..1ac9d7cc 100644 --- a/src/validate/index.mjs +++ b/src/validate/index.mjs @@ -49,6 +49,7 @@ const run = async ({ result.errors.forEach(error => { displayError(error) + // console.dir(error, { depth: 100 }) }) } } @@ -185,7 +186,7 @@ const run = async ({ "methods": { "type": "array", "items": { - "allOf": json.methods.map(method => ({ + "allOf": json.methods.filter(m => m.result).map(method => ({ "if": { "type": "object", "properties": { @@ -265,7 +266,6 @@ const run = async ({ } ] - const examples = ajv.compile(exampleSpec) try { From 40c70b66e5cdba48038510ffa93cfdeaad20fc01 Mon Sep 17 00:00:00 2001 From: kschrief Date: Mon, 25 Mar 2024 10:48:56 -0400 Subject: [PATCH 33/44] Reverse versioning override --- .github/workflows/merge-to-main.yml | 36 ------------------- .github/workflows/merge-to-next-major.yml | 44 ++++++++++++++--------- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index d80d699f..edbc5ea1 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -21,28 +21,10 @@ jobs: git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" - # Get the "next" version number - - name: Extract next version - id: extract_version - run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" - # Checkout "main" - name: Checkout main run: git checkout "main" - # Update "main" version to match "next" - - name: Update "main" version to match "next" - run: | - jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - - if diff -q "package.json" "temp.json" >/dev/null; then - echo "Versions are identical. No change required." - rm temp.json - else - mv temp.json package.json - git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" - fi - # Attempt a dry-run merge - name: Attempt a dry-run merge run: | @@ -70,28 +52,10 @@ jobs: git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" - # Get the "next" version number - - name: Extract next version - id: extract_version - run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" - # Checkout "main" - name: Checkout main run: git checkout "main" - # Update "main" version to match "next" - - name: Update "main" version to match "next" - run: | - jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json - - if diff -q "package.json" "temp.json" >/dev/null; then - echo "Versions are identical. No change required." - rm temp.json - else - mv temp.json package.json - git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" - fi - - name: Perform the merge from next to main run: | git merge origin/next diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 0b6bfd4f..955fc2df 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -24,17 +24,21 @@ jobs: git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" - # Get the "next" version number - - name: Extract next version - id: extract_version - run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" - # Checkout "next-major" - name: Checkout next-major run: git checkout "next-major" - # Update "next-major" version to match "next" - - name: Update "next-major" version to match "next" + # Get the "next-major" version number + - name: Extract next-major version + id: extract_version + run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" + + # Checkout "next" + - name: Checkout next + run: git checkout "next" + + # Update "next" version to match "next-major" + - name: Update "next" version to match "next-major" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -46,10 +50,14 @@ jobs: git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" fi + # Checkout "next-major" + - name: Checkout next-major + run: git checkout "next-major" + # Attempt a dry-run merge - name: Attempt a dry-run merge run: | - git merge --no-commit --no-ff origin/${{github.ref_name}} + git merge --no-commit --no-ff ${{github.ref_name}} exit $? # Attempt to merge to next-major if our dry-run succeeded @@ -73,17 +81,21 @@ jobs: git config --global user.email "${{ secrets.GLOBAL_GITHUB_EMAIL }}" git config --global user.name "${{ secrets.GLOBAL_GITHUB_USER }}" - # Get the "next" version number - - name: Extract next version - id: extract_version - run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" - # Checkout "next-major" - name: Checkout next-major run: git checkout "next-major" - # Update "next-major" version to match "next" - - name: Update "next-major" version to match "next" + # Get the "next-major" version number + - name: Extract next-major version + id: extract_version + run: echo "::set-output name=version::$(node -e 'console.log(require("./package.json").version)')" + + # Checkout "next" + - name: Checkout next + run: git checkout "next" + + # Update "next" version to match "next-major" + - name: Update "next" version to match "next-major" run: | jq '.version = "${{ steps.extract_version.outputs.version }}"' package.json > temp.json @@ -97,7 +109,7 @@ jobs: - name: Perform the merge from next to next-major run: | - git merge origin/next + git merge next merge_status=$? git push origin "next-major" From 5ebcecc7fff14e1802e3135f9fd845aabd58f299 Mon Sep 17 00:00:00 2001 From: kschrief Date: Mon, 25 Mar 2024 10:51:43 -0400 Subject: [PATCH 34/44] Silly change --- .github/workflows/merge-to-main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge-to-main.yml b/.github/workflows/merge-to-main.yml index edbc5ea1..02f60a45 100644 --- a/.github/workflows/merge-to-main.yml +++ b/.github/workflows/merge-to-main.yml @@ -71,7 +71,7 @@ jobs: exit 1 fi - # If the merge cannot be performed, let stakeholders know + # If the merge cannot be performed, let stakeholders know process_merge_on_failure: name: Merge dry-run failure needs: check_merge From 2ca3e707f3c4277ca54536300c8fc5e6a4215fca Mon Sep 17 00:00:00 2001 From: kschrief Date: Mon, 25 Mar 2024 10:56:40 -0400 Subject: [PATCH 35/44] Forgot to checkout next-major --- .github/workflows/merge-to-next-major.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/merge-to-next-major.yml b/.github/workflows/merge-to-next-major.yml index 955fc2df..34d8ecea 100644 --- a/.github/workflows/merge-to-next-major.yml +++ b/.github/workflows/merge-to-next-major.yml @@ -107,6 +107,10 @@ jobs: git add package.json && git commit -m "Sync version to ${{ steps.extract_version.outputs.version }}" fi + # Checkout "next-major" + - name: Checkout next-major + run: git checkout "next-major" + - name: Perform the merge from next to next-major run: | git merge next From dd544f701f2d609076d3b157f745eb48e0163883 Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Thu, 9 May 2024 12:45:47 -0400 Subject: [PATCH 36/44] fix: Merge #186 --- src/validate/index.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/validate/index.mjs b/src/validate/index.mjs index 22e7e468..970b076e 100644 --- a/src/validate/index.mjs +++ b/src/validate/index.mjs @@ -74,10 +74,11 @@ const run = async ({ const jsonSchemaSpec = await (await fetch('https://meta.json-schema.tools')).json() // - OpenRPC uses `additionalItems` when `items` is not an array of schemas. This fails strict validate, so we remove it - // - OpenRPC uses raw.githubusercontent.com URLs for the json-schema spec, we replace this with the up to date spec on meta.json-schema.tools const openRpcSpec = await (await fetch('https://meta.open-rpc.org')).json() removeIgnoredAdditionalItems(openRpcSpec) - replaceUri('https://raw.githubusercontent.com/json-schema-tools/meta-schema/1.5.9/src/schema.json', 'https://meta.json-schema.tools/', openRpcSpec) + + //AJV doesn't like not having a slash at the end of the URL + replaceUri('https://meta.json-schema.tools', 'https://meta.json-schema.tools/', openRpcSpec) Object.values(sharedSchemas).forEach(schema => { try { From 76db0a471edc7b1e0edbb58f20bb8c7fd7da49df Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Thu, 9 May 2024 15:45:14 -0400 Subject: [PATCH 37/44] fix: Provider interface parameters are generic objects --- src/shared/json-schema.mjs | 43 +++++++++++++++++++++++++++ src/shared/modules.mjs | 59 +++++++++++++++++++++++++++----------- 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/src/shared/json-schema.mjs b/src/shared/json-schema.mjs index 5d1d3a27..aa1ad5dc 100644 --- a/src/shared/json-schema.mjs +++ b/src/shared/json-schema.mjs @@ -142,6 +142,48 @@ const getPath = (uri = '', moduleJson = {}) => { } } +const getPropertySchema = (json, dotPath, document) => { + const path = dotPath.split('.') + let node = json + + for (var i=0; i j >= i ).join('.') + if (node.type === 'object') { + if (node.properties && node.properties[property]) { + node = node.properties[property] + } + // todo: need to escape the regex? + else if (node.patternProperties && property.match(node.patternProperties)) { + node = node.patternProperties[property] + } + else if (node.additionalProperties && typeof node.additionalProperties === 'object') { + node = node.additionalProperties + } + } + else if (node.$ref) { + node = getPropertySchema(getPath(node.$ref, document), remainingPath, document) + } + else if (Array.isArray(node.allOf)) { + node = node.allOf.find(s => { + let schema + try { + schema = getPropertySchema(s, remainingPath, document) + } + catch (error) { + + } + return schema + }) + } + else { + throw `Cannot get property '${dotPath}' of non-object.` + } + } + + return node +} + function getSchemaConstraints(schema, module, options = { delimiter: '\n' }) { if (schema.schema) { schema = schema.schema @@ -441,6 +483,7 @@ export { getLocalSchemaPaths, getLinkedSchemaPaths, getPath, + getPropertySchema, isDefinitionReferencedBySchema, isNull, isSchema, diff --git a/src/shared/modules.mjs b/src/shared/modules.mjs index eae40fc2..5be1cafb 100644 --- a/src/shared/modules.mjs +++ b/src/shared/modules.mjs @@ -28,7 +28,7 @@ import isEmpty from 'crocks/core/isEmpty.js' const { and, not } = logic import isString from 'crocks/core/isString.js' import predicates from 'crocks/predicates/index.js' -import { getExternalSchemaPaths, isDefinitionReferencedBySchema, isNull, localizeDependencies, isSchema, getLocalSchemaPaths, replaceRef } from './json-schema.mjs' +import { getExternalSchemaPaths, isDefinitionReferencedBySchema, isNull, localizeDependencies, isSchema, getLocalSchemaPaths, replaceRef, getPropertySchema } from './json-schema.mjs' import { getPath as getRefDefinition } from './json-schema.mjs' const { isObject, isArray, propEq, pathSatisfies, hasProp, propSatisfies } = predicates @@ -87,20 +87,22 @@ const getProviderInterfaceMethods = (capability, json) => { function getProviderInterface(capability, module, extractProviderSchema = false) { module = JSON.parse(JSON.stringify(module)) - const iface = getProviderInterfaceMethods(capability, module).map(method => localizeDependencies(method, module, null, { mergeAllOfs: true })) + const iface = getProviderInterfaceMethods(capability, module)//.map(method => localizeDependencies(method, module, null, { mergeAllOfs: true })) iface.forEach(method => { - const payload = localizeDependencies(getPayloadFromEvent(method), module) + const payload = getPayloadFromEvent(method) const focusable = method.tags.find(t => t['x-allow-focus']) // remove `onRequest` method.name = method.name.charAt(9).toLowerCase() + method.name.substr(10) + const schema = getPropertySchema(payload, 'properties.parameters', module) + method.params = [ { "name": "parameters", "required": true, - "schema": payload.properties.parameters + "schema": schema// payload.properties.parameters } ] @@ -557,7 +559,7 @@ const createPullEventFromPush = (pusher, json) => { return event } -const createPullProvider = (pusher, json) => { +const createPullProvider = (pusher, params) => { const event = eventDefaults(JSON.parse(JSON.stringify(pusher))) // insert the method prefix on the last particle of the method name event.name = event.name.split('.').map((x, i, arr) => (i === arr.length-1) ? 'onRequest' + x.charAt(0).toUpperCase() + x.substr(1) : x).join('.') @@ -579,23 +581,13 @@ const createPullProvider = (pusher, json) => { "type": "string", }, "parameters": { - "type": "object", - "required": [], - "properties": { - } + "$ref": "#/components/schemas/" + params } }, "additionalProperties": false } } - event.params.forEach(p => { - event.result.schema.properties.parameters.properties[p.name] = p.schema - if (p.required) { - event.result.schema.properties.parameters.required.push(p.name) - } - }) - event.params = [] event.examples = event.examples.map(example => { @@ -623,6 +615,32 @@ const createPullProvider = (pusher, json) => { return event } +const createPullProviderParams = (pusher) => { + const copy = JSON.parse(JSON.stringify(pusher)) + + // drop the last param (it's the value) + copy.params.pop() + + const name = copy.name.split('.').pop() + const paramsSchema = { + "title": name.charAt(0).toUpperCase() + name.substr(1) + "ProviderParameters", + "type": "object", + "required": [], + "properties": { + }, + "additionalProperties": false + } + + copy.params.forEach(p => { + paramsSchema.properties[p.name] = p.schema + if (p.required) { + paramsSchema.required.push(p.name) + } + }) + + return paramsSchema +} + const createPullRequestor = (pusher, json) => { const module = pusher.tags.find(t => t.name === 'push-pull')['x-requesting-interface'] const requestor = JSON.parse(JSON.stringify(pusher)) @@ -1015,7 +1033,14 @@ const generatePushPullMethods = json => { const pushers = requestors.map(m => createPushFromRequestor(m, json)) pushers.forEach(m => json.methods.push(m)) - pushers.forEach(pusher => json.methods.push(createPullProvider(pusher))) + pushers.forEach(pusher => { + const schema = createPullProviderParams(pusher) + json.methods.push(createPullProvider(pusher, schema.title)) + + json.components = json.components || {} + json.components.schemas = json.components.schemas || {} + json.components.schemas[schema.title] = schema + }) requestors.forEach(requestor => json.methods.push(createPushEvent(requestor, json))) // pushers.forEach(property => json.methods.push(createPullRequestor(property, json))) From 3820cad9d0de87adc9055a4044aa1a6fa48bc103 Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Thu, 16 May 2024 10:41:01 -0400 Subject: [PATCH 38/44] fix: Handle cross-module x-provided-by --- src/shared/modules.mjs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/shared/modules.mjs b/src/shared/modules.mjs index 5be1cafb..51863b01 100644 --- a/src/shared/modules.mjs +++ b/src/shared/modules.mjs @@ -32,6 +32,10 @@ import { getExternalSchemaPaths, isDefinitionReferencedBySchema, isNull, localiz import { getPath as getRefDefinition } from './json-schema.mjs' const { isObject, isArray, propEq, pathSatisfies, hasProp, propSatisfies } = predicates +// TODO remove these when major/rpc branch is merged +const name = method => method.name.split('.').pop() +const rename = (method, renamer) => method.name.split('.').map((x, i, arr) => i === (arr.length-1) ? renamer(x) : x).join('.') + // util for visually debugging crocks ADTs const inspector = obj => { if (obj.inspect) { @@ -391,7 +395,6 @@ const createEventResultSchemaFromProperty = (property, type='') => { let name = caps['x-provided-by'] ? caps['x-provided-by'].split('.').pop().replace('onRequest', '') : property.name name = name.charAt(0).toUpperCase() + name.substring(1) - if ( subscriberType === 'global') { // wrap the existing result and the params in a new result object const schema = { @@ -426,7 +429,7 @@ const createEventFromProperty = (property, type='', alternative, json) => { event.name = event.name.split('.').map((x, i, arr) => (i === arr.length-1) ? 'on' + x.charAt(0).toUpperCase() + x.substr(1) : x).join('.') const subscriberFor = pusher || (json.info.title + '.' + property.name) - const old_tags = property.tags.concat() + const old_tags = JSON.parse(JSON.stringify(property.tags)) alternative && (event.tags[0]['x-alternative'] = alternative) @@ -524,7 +527,7 @@ const createPullEventFromPush = (pusher, json) => { const event = eventDefaults(JSON.parse(JSON.stringify(pusher))) event.params = [] event.name = 'onPull' + event.name.charAt(0).toUpperCase() + event.name.substr(1) - const old_tags = pusher.tags.concat() + const old_tags = JSON.parse(JSON.stringify(pusher.tags)) event.tags[0]['x-pulls-for'] = pusher.name event.tags.unshift({ @@ -563,7 +566,7 @@ const createPullProvider = (pusher, params) => { const event = eventDefaults(JSON.parse(JSON.stringify(pusher))) // insert the method prefix on the last particle of the method name event.name = event.name.split('.').map((x, i, arr) => (i === arr.length-1) ? 'onRequest' + x.charAt(0).toUpperCase() + x.substr(1) : x).join('.') - const old_tags = pusher.tags.concat() + const old_tags = JSON.parse(JSON.stringify(pusher.tags)) const value = event.params.pop() @@ -699,7 +702,7 @@ const createTemporalEventMethod = (method, json, name) => { const createEventFromMethod = (method, json, name, correlationExtension, tagsToRemove = []) => { const event = eventDefaults(JSON.parse(JSON.stringify(method))) event.name = 'on' + name - const old_tags = method.tags.concat() + const old_tags = JSON.parse(JSON.stringify(method.tags)) event.tags[0][correlationExtension] = method.name event.tags.unshift({ @@ -806,13 +809,13 @@ const createSetterFromProperty = property => { const createFocusFromProvider = provider => { - if (!provider.name.startsWith('onRequest')) { + if (!name(provider).startsWith('onRequest')) { throw "Methods with the `x-provider` tag extension MUST start with 'onRequest'." } const ready = JSON.parse(JSON.stringify(provider)) - ready.name = ready.name.charAt(9).toLowerCase() + ready.name.substr(10) + 'Focus' - ready.summary = `Internal API for ${provider.name.substr(9)} Provider to request focus for UX purposes.` + ready.name = rename(ready, n => n.charAt(9).toLowerCase() + n.substr(10) + 'Focus') + ready.summary = `Internal API for ${name(provider).substr(9)} Provider to request focus for UX purposes.` ready.tags = ready.tags.filter(t => t.name !== 'event') ready.tags.find(t => t.name === 'capabilities')['x-allow-focus-for'] = provider.name @@ -841,12 +844,12 @@ const createFocusFromProvider = provider => { // type = Response | Error const createResponseFromProvider = (provider, type, json) => { - if (!provider.name.startsWith('onRequest')) { + if (!name(provider).startsWith('onRequest')) { throw "Methods with the `x-provider` tag extension MUST start with 'onRequest'." } const response = JSON.parse(JSON.stringify(provider)) - response.name = response.name.charAt(9).toLowerCase() + response.name.substr(10) + type + response.name = rename(response, n => n.charAt(9).toLowerCase() + n.substr(10) + type) response.summary = `Internal API for ${provider.name.substr(9)} Provider to send back ${type.toLowerCase()}.` response.tags = response.tags.filter(t => t.name !== 'event') @@ -1068,7 +1071,7 @@ const generateTemporalSetMethods = json => { const generateProviderMethods = json => { - const providers = json.methods.filter( m => m.name.startsWith('onRequest') && m.tags && m.tags.find( t => t.name == 'capabilities' && t['x-provides'])) || [] + const providers = json.methods.filter( m => name(m).startsWith('onRequest') && m.tags && m.tags.find( t => t.name == 'capabilities' && t['x-provides'])) || [] providers.forEach(provider => { if (! isRPCOnlyMethod(provider)) { From 6d0ea39a20ee55d3534186f7095c3ae0a48ce3c4 Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Wed, 22 May 2024 16:37:59 -0400 Subject: [PATCH 39/44] fix: Simplify RPC method generation --- src/shared/modules.mjs | 92 +++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/src/shared/modules.mjs b/src/shared/modules.mjs index 51863b01..b5ed3165 100644 --- a/src/shared/modules.mjs +++ b/src/shared/modules.mjs @@ -469,7 +469,7 @@ const createEventFromProperty = (property, type='', alternative, json) => { } old_tags.forEach(t => { - if (t.name !== 'property' && !t.name.startsWith('property:') && t.name !== 'push-pull' & t.name !== 'requestor') + if (t.name !== 'property' && !t.name.startsWith('property:') && t.name !== 'push-pull') { event.tags.push(t) } @@ -480,23 +480,17 @@ const createEventFromProperty = (property, type='', alternative, json) => { return event } -const createPushFromRequestor = (requestor, json) => { - const push = JSON.parse(JSON.stringify(requestor)) - +// create foo() notifier from onFoo() event +const createNotifierFromEvent = (event, json) => { + const push = JSON.parse(JSON.stringify(event)) const caps = push.tags.find(t => t.name === 'capabilities') - push.name = caps['x-provided-by'].replace('onRequest', '') + push.name = caps['x-provided-by'] delete caps['x-provided-by'] - push.name = push.name.split('.').map( (x, i, arr) => (i === arr.length -1) ? x.charAt(0).toLowerCase() + x.substr(1) : x).join('.') caps['x-provides'] = caps['x-uses'].pop() delete caps['x-uses'] - push.tags = push.tags.filter(t => t.name !== 'push-pull') - push.tags.push({ - name: "push" - }) - - requestor.tags.find(t => t.name === 'push-pull').name = 'requestor' + push.tags = push.tags.filter(t => t.name !== 'event') push.result.required = true push.params.push(push.result) @@ -562,17 +556,15 @@ const createPullEventFromPush = (pusher, json) => { return event } -const createPullProvider = (pusher, params) => { - const event = eventDefaults(JSON.parse(JSON.stringify(pusher))) - // insert the method prefix on the last particle of the method name - event.name = event.name.split('.').map((x, i, arr) => (i === arr.length-1) ? 'onRequest' + x.charAt(0).toUpperCase() + x.substr(1) : x).join('.') - const old_tags = JSON.parse(JSON.stringify(pusher.tags)) +const createPullProvider = (requestor, params) => { + const event = eventDefaults(JSON.parse(JSON.stringify(requestor))) + event.name = requestor.tags.find(t => t['x-provided-by'])['x-provided-by'] + const old_tags = JSON.parse(JSON.stringify(requestor.tags)) - const value = event.params.pop() + const value = event.result - event.tags[0]['x-pulls-for'] = pusher.name event.tags[0]['x-response'] = value.schema - event.tags[0]['x-response'].examples = event.examples.map(e => e.params.pop().value) + event.tags[0]['x-response'].examples = event.examples.map(e => e.result.value) event.result = { "name": "request", @@ -615,16 +607,21 @@ const createPullProvider = (pusher, params) => { } }) + const caps = event.tags.find(t => t.name === 'capabilities') + caps['x-provides'] = caps['x-uses'].pop() || caps['x-manages'].pop() + caps['x-requestor'] = requestor.name + delete caps['x-uses'] + delete caps['x-manages'] + delete caps['x-provided-by'] + return event } -const createPullProviderParams = (pusher) => { - const copy = JSON.parse(JSON.stringify(pusher)) +const createPullProviderParams = (requestor) => { + const copy = JSON.parse(JSON.stringify(requestor)) - // drop the last param (it's the value) - copy.params.pop() - - const name = copy.name.split('.').pop() + // grab onRequest and turn into + const name = copy.tags.find(t => t['x-provided-by'])['x-provided-by'].split('.').pop().substring(9) const paramsSchema = { "title": name.charAt(0).toUpperCase() + name.substr(1) + "ProviderParameters", "type": "object", @@ -1033,27 +1030,36 @@ const generatePolymorphicPullEvents = json => { const generatePushPullMethods = json => { const requestors = json.methods.filter( m => m.tags && m.tags.find( t => t.name == 'push-pull')) || [] - const pushers = requestors.map(m => createPushFromRequestor(m, json)) - pushers.forEach(m => json.methods.push(m)) - - pushers.forEach(pusher => { - const schema = createPullProviderParams(pusher) - json.methods.push(createPullProvider(pusher, schema.title)) - - json.components = json.components || {} - json.components.schemas = json.components.schemas || {} - json.components.schemas[schema.title] = schema - }) - requestors.forEach(requestor => json.methods.push(createPushEvent(requestor, json))) - -// pushers.forEach(property => json.methods.push(createPullRequestor(property, json))) requestors.forEach(requestor => { + json.methods.push(createPushEvent(requestor, json)) + const schema = createEventResultSchemaFromProperty(requestor) if (schema) { json.components = json.components || {} json.components.schemas = json.components.schemas || {} json.components.schemas[schema.title] = schema - } + } + }) + + return json +} + +const generateProvidedByMethods = json => { + const requestors = json.methods.filter(m => !m.tags.find(t => t.name === 'event')).filter( m => m.tags && m.tags.find( t => t['x-provided-by'])) || [] + const events = json.methods .filter(m => m.tags.find(t => t.name === 'event')) + .filter( m => m.tags && m.tags.find( t => t['x-provided-by'])) + .filter(e => !json.methods.find(m => m.name === e.tags.find(t => t['x-provided-by'])['x-provided-by'])) + + const pushers = events.map(m => createNotifierFromEvent(m, json)) + pushers.forEach(m => json.methods.push(m)) + + requestors.forEach(requestor => { + const schema = createPullProviderParams(requestor) + json.methods.push(createPullProvider(requestor, schema.title)) + + json.components = json.components || {} + json.components.schemas = json.components.schemas || {} + json.components.schemas[schema.title] = schema }) return json @@ -1350,7 +1356,9 @@ const getPathFromModule = (module, path) => { const fireboltize = (json) => { json = generatePropertyEvents(json) json = generatePropertySetters(json) - json = generatePushPullMethods(json) + // TODO: we don't use this yet... consider removing? + // json = generatePushPullMethods(json) + // json = generateProvidedByMethods(json) json = generatePolymorphicPullEvents(json) json = generateProviderMethods(json) json = generateTemporalSetMethods(json) From 7dfdf7decad12197f940cdf96edcf018efa40d0d Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Thu, 23 May 2024 11:41:12 -0400 Subject: [PATCH 40/44] fix: Added validation to ensure x-provided-by methods have matching schemas per spec --- src/cli.mjs | 3 +- src/shared/json-schema.mjs | 35 +++++++++-- src/validate/index.mjs | 10 ++- src/validate/validator/index.mjs | 101 +++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 7 deletions(-) diff --git a/src/cli.mjs b/src/cli.mjs index 8e09f6c7..9cb60368 100755 --- a/src/cli.mjs +++ b/src/cli.mjs @@ -19,7 +19,8 @@ const knownOpts = { 'static-module': [String, Array], 'language': [path], 'examples': [path, Array], - 'as-path': [Boolean] + 'as-path': [Boolean], + 'pass-throughs': [Boolean] } const shortHands = { diff --git a/src/shared/json-schema.mjs b/src/shared/json-schema.mjs index aa1ad5dc..7fa54a8c 100644 --- a/src/shared/json-schema.mjs +++ b/src/shared/json-schema.mjs @@ -149,7 +149,13 @@ const getPropertySchema = (json, dotPath, document) => { for (var i=0; i j >= i ).join('.') - if (node.type === 'object') { + if (node.$ref) { + node = getPropertySchema(getPath(node.$ref, document), remainingPath, document) + } + else if (property === '') { + return node + } + else if (node.type === 'object') { if (node.properties && node.properties[property]) { node = node.properties[property] } @@ -161,9 +167,6 @@ const getPropertySchema = (json, dotPath, document) => { node = node.additionalProperties } } - else if (node.$ref) { - node = getPropertySchema(getPath(node.$ref, document), remainingPath, document) - } else if (Array.isArray(node.allOf)) { node = node.allOf.find(s => { let schema @@ -184,6 +187,29 @@ const getPropertySchema = (json, dotPath, document) => { return node } +const getPropertiesInSchema = (json, document) => { + let node = json + + while (node.$ref) { + node = getPath(node.$ref, document) + } + + if (node.type === 'object') { + const props = [] + if (node.properties) { + props.push(...Object.keys(node.properties)) + } + + if (node.propertyNames) { + props.push(...node.propertyNames) + } + + return props + } + + return null +} + function getSchemaConstraints(schema, module, options = { delimiter: '\n' }) { if (schema.schema) { schema = schema.schema @@ -484,6 +510,7 @@ export { getLinkedSchemaPaths, getPath, getPropertySchema, + getPropertiesInSchema, isDefinitionReferencedBySchema, isNull, isSchema, diff --git a/src/validate/index.mjs b/src/validate/index.mjs index 970b076e..9d59f1e9 100644 --- a/src/validate/index.mjs +++ b/src/validate/index.mjs @@ -19,7 +19,7 @@ import { readJson, readFiles, readDir } from "../shared/filesystem.mjs" import { addExternalMarkdown, addExternalSchemas, fireboltize } from "../shared/modules.mjs" import { removeIgnoredAdditionalItems, replaceUri } from "../shared/json-schema.mjs" -import { validate, displayError } from "./validator/index.mjs" +import { validate, displayError, validatePasshtroughs } from "./validator/index.mjs" import { logHeader, logSuccess, logError } from "../shared/io.mjs" import Ajv from 'ajv' @@ -33,7 +33,8 @@ const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) const run = async ({ input: input, schemas: schemas, - transformations = false + transformations = false, + 'pass-throughs': passThroughs }) => { logHeader(`Validating ${path.relative('.', input)} with${transformations ? '' : 'out'} Firebolt transformations.`) @@ -286,6 +287,11 @@ const run = async ({ // console.dir(exampleSpec, { depth: 100 }) } } + + if (passThroughs) { + const passthroughResult = validatePasshtroughs(json) + printResult(passthroughResult, "Firebolt App pass-through") + } } catch (error) { throw error diff --git a/src/validate/validator/index.mjs b/src/validate/validator/index.mjs index 8b0f76a1..2bf7e3b0 100644 --- a/src/validate/validator/index.mjs +++ b/src/validate/validator/index.mjs @@ -17,6 +17,8 @@ */ import groupBy from 'array.prototype.groupby' import util from 'util' +import { getPayloadFromEvent } from '../../shared/modules.mjs' +import { getPropertiesInSchema, getPropertySchema } from '../../shared/json-schema.mjs' const addPrettyPath = (error, json) => { const path = [] @@ -164,4 +166,103 @@ export const validate = (json = {}, schemas = {}, ajv, validator, additionalPack } return { valid: valid, title: json.title || json.info.title, errors: errors } +} + +const schemasMatch = (a, b) => { + const aKeys = Object.keys(a) + const bKeys = Object.keys(b) + const keysMatch = (aKeys.length == bKeys.length) && aKeys.every(key => bKeys.includes(key)) + if (keysMatch) { + const typesMatch = aKeys.every(key => typeof a[key] === typeof b[key]) + if (typesMatch) { + const valuesMatch = aKeys.every(key => typeof a[key] === 'object' || (a[key] === b[key])) + if (valuesMatch) { + const objectsMatch = aKeys.every(key => typeof a[key] !== 'object' || schemasMatch(a[key], b[key])) + if (objectsMatch) { + return true + } + } + } + } + + return false +} + +export const validatePasshtroughs = (json) => { + const providees = json.methods.filter(m => m.tags.find(t => t['x-provided-by'])) + + const result = { + valid: true, + title: 'Mapping of all x-provided-by methods', + errors: [] + } + + providees.forEach(method => { + const providerName = method.tags.find(t => t['x-provided-by'])['x-provided-by'] + const provider = json.methods.find(m => m.name === providerName) + let destination, examples1 + let source, examples2 + + if (!provider) { + result.errors.push({ + message: `The x-provided-by method '${providerName}' does not exist`, + instancePath: `/methods/${json.methods.indexOf(method)}` + }) + return + } + else if (method.tags.find(t => t.name === 'event')) { + destination = getPayloadFromEvent(method) + examples1 = method.examples.map(e => e.result.value) + source = provider.params[provider.params.length-1].schema + examples2 = provider.examples.map(e => e.params[e.params.length-1].value) + } + else { + destination = method.result.schema + examples1 = method.examples.map(e => e.result.value) + source = JSON.parse(JSON.stringify(provider.tags.find(t => t['x-response'])['x-response'])) + examples2 = provider.tags.find(t => t['x-response'])['x-response'].examples + delete source.examples + } + + if (!schemasMatch(source, destination)) { + const properties = getPropertiesInSchema(destination, json) + + // follow $refs so we can see the schemas + source = getPropertySchema(source, '.', json) + destination = getPropertySchema(destination, '.', json) + + if (properties && properties.length) { + const destinationProperty = properties.find(property => { + let candidate = getPropertySchema(destination, `properties.${property}`, json) + + candidate && (candidate = getPropertySchema(candidate, '.', json)) // follow $refs + + if (schemasMatch(candidate, source)) { + return true + } + }) + + if (!destinationProperty) { + result.errors.push({ + message: `The x-provided-by method '${providerName}' does not have a matching schema or sub-schema`, + instancePath: `/methods/${json.methods.indexOf(method)}` + }) + result.title = `Mismatched x-provided-by schemas in ${result.errors.length} methods.` + } + } + else { + result.errors.push({ + message: `The x-provided-by method '${providerName}' does not have a matching schema and has not candidate sub-schemas`, + instancePath: `/methods/${json.methods.indexOf(method)}` + }) + } + } + }) + if (result.errors.length) { + result.valid = false + result.errors.forEach(error => addPrettyPath(error, json)) + } + + return result + } \ No newline at end of file From 3cde3288a627e6f7a0f97f9b38e5c487da4ff2a1 Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Thu, 23 May 2024 13:42:57 -0400 Subject: [PATCH 41/44] fix: Use x-response-name to disambiguate pass-through schemas --- src/validate/validator/index.mjs | 35 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/validate/validator/index.mjs b/src/validate/validator/index.mjs index 2bf7e3b0..687aaada 100644 --- a/src/validate/validator/index.mjs +++ b/src/validate/validator/index.mjs @@ -202,6 +202,7 @@ export const validatePasshtroughs = (json) => { const provider = json.methods.find(m => m.name === providerName) let destination, examples1 let source, examples2 + let sourceName if (!provider) { result.errors.push({ @@ -214,12 +215,14 @@ export const validatePasshtroughs = (json) => { destination = getPayloadFromEvent(method) examples1 = method.examples.map(e => e.result.value) source = provider.params[provider.params.length-1].schema + sourceName = provider.params[provider.params.length-1].name examples2 = provider.examples.map(e => e.params[e.params.length-1].value) } else { destination = method.result.schema examples1 = method.examples.map(e => e.result.value) source = JSON.parse(JSON.stringify(provider.tags.find(t => t['x-response'])['x-response'])) + sourceName = provider.tags.find(t => t['x-response'])['x-response-name'] examples2 = provider.tags.find(t => t['x-response'])['x-response'].examples delete source.examples } @@ -231,24 +234,26 @@ export const validatePasshtroughs = (json) => { source = getPropertySchema(source, '.', json) destination = getPropertySchema(destination, '.', json) - if (properties && properties.length) { - const destinationProperty = properties.find(property => { - let candidate = getPropertySchema(destination, `properties.${property}`, json) - - candidate && (candidate = getPropertySchema(candidate, '.', json)) // follow $refs + if (properties && properties.length && sourceName) { + let candidate = getPropertySchema(getPropertySchema(destination, `properties.${sourceName}`, json), '.', json) - if (schemasMatch(candidate, source)) { - return true - } - }) - - if (!destinationProperty) { + if (!candidate) { + result.errors.push({ + message: `The x-provided-by method '${providerName}' does not have a matching result schema or ${sourceName} property`, + instancePath: `/methods/${json.methods.indexOf(method)}` + }) + } else if (!schemasMatch(candidate, source)) { result.errors.push({ - message: `The x-provided-by method '${providerName}' does not have a matching schema or sub-schema`, + message: `The x-provided-by method '${providerName}' does not have a matching result schema or ${sourceName} schema`, instancePath: `/methods/${json.methods.indexOf(method)}` - }) - result.title = `Mismatched x-provided-by schemas in ${result.errors.length} methods.` - } + }) + } + } + else if (!sourceName) { + result.errors.push({ + message: `The x-provided-by method '${providerName}' does not have a matching result schema and has no x-response-name property to inject into`, + instancePath: `/methods/${json.methods.indexOf(method)}` + }) } else { result.errors.push({ From ed4258c495c6c951aff52391381bc5d27478dcb8 Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Tue, 28 May 2024 15:51:21 -0400 Subject: [PATCH 42/44] fix: Documentation --- .../templates/codeblocks/interface.md | 3 ++ .../templates/declarations/default.md | 1 + .../markdown/templates/interfaces/default.mjs | 1 + .../templates/interfaces/focusable.mjs | 1 + languages/markdown/templates/types/default.md | 3 -- languages/markdown/templates/types/enum.md | 5 --- languages/markdown/templates/types/object.md | 3 -- src/docs/index.mjs | 1 + src/macrofier/engine.mjs | 33 +++++++++++++++---- src/macrofier/index.mjs | 21 +++++++++--- src/macrofier/types.mjs | 2 +- 11 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 languages/markdown/templates/codeblocks/interface.md create mode 100644 languages/markdown/templates/declarations/default.md create mode 100644 languages/markdown/templates/interfaces/default.mjs create mode 100644 languages/markdown/templates/interfaces/focusable.mjs delete mode 100644 languages/markdown/templates/types/default.md delete mode 100644 languages/markdown/templates/types/enum.md delete mode 100644 languages/markdown/templates/types/object.md diff --git a/languages/markdown/templates/codeblocks/interface.md b/languages/markdown/templates/codeblocks/interface.md new file mode 100644 index 00000000..8c69cda0 --- /dev/null +++ b/languages/markdown/templates/codeblocks/interface.md @@ -0,0 +1,3 @@ +interface ${name} { + ${methods} +} \ No newline at end of file diff --git a/languages/markdown/templates/declarations/default.md b/languages/markdown/templates/declarations/default.md new file mode 100644 index 00000000..27a3c4a7 --- /dev/null +++ b/languages/markdown/templates/declarations/default.md @@ -0,0 +1 @@ +function ${method.name}(${method.params}): Promise<${method.result.type}> \ No newline at end of file diff --git a/languages/markdown/templates/interfaces/default.mjs b/languages/markdown/templates/interfaces/default.mjs new file mode 100644 index 00000000..63f63093 --- /dev/null +++ b/languages/markdown/templates/interfaces/default.mjs @@ -0,0 +1 @@ + ${method.name}(${method.signature.params}, session: ProviderSession): Promise<${method.result.type}> diff --git a/languages/markdown/templates/interfaces/focusable.mjs b/languages/markdown/templates/interfaces/focusable.mjs new file mode 100644 index 00000000..b81737b1 --- /dev/null +++ b/languages/markdown/templates/interfaces/focusable.mjs @@ -0,0 +1 @@ + ${method.name}(${method.signature.params}, session: FocusableProviderSession): Promise<${method.result.type}> diff --git a/languages/markdown/templates/types/default.md b/languages/markdown/templates/types/default.md deleted file mode 100644 index f2a4644e..00000000 --- a/languages/markdown/templates/types/default.md +++ /dev/null @@ -1,3 +0,0 @@ -```typescript -${type} -``` \ No newline at end of file diff --git a/languages/markdown/templates/types/enum.md b/languages/markdown/templates/types/enum.md deleted file mode 100644 index 59861d52..00000000 --- a/languages/markdown/templates/types/enum.md +++ /dev/null @@ -1,5 +0,0 @@ -${name} Enumeration: - -| key | value | -|-----|-------| -| ${key} | ${value} | diff --git a/languages/markdown/templates/types/object.md b/languages/markdown/templates/types/object.md deleted file mode 100644 index 2b15f271..00000000 --- a/languages/markdown/templates/types/object.md +++ /dev/null @@ -1,3 +0,0 @@ -| Property | Type | Description | -|----------|------|-------------| -| `${property}` | [${type}](${type.link}) | ${description} | diff --git a/src/docs/index.mjs b/src/docs/index.mjs index 66dd4136..fdf71acd 100755 --- a/src/docs/index.mjs +++ b/src/docs/index.mjs @@ -59,6 +59,7 @@ const run = async ({ examples: examples, templatesPerModule: config.templatesPerModule, templatesPerSchema: config.templatesPerSchema, + operators: config.operators, libraryName: libraryName, hidePrivate: false }) diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index e2427125..fc6ecaec 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -573,7 +573,7 @@ const generateMacros = (obj, templates, languages, options = {}) => { const eventsEnum = generateEvents(obj, templates) const examples = generateExamples(obj, templates, languages) - const allMethodsArray = generateMethods(obj, examples, templates, options.type) + const allMethodsArray = generateMethods(obj, examples, templates, languages, options.type) Array.from(new Set(['methods'].concat(config.additionalMethodTemplates))).filter(dir => dir).forEach(dir => { @@ -1186,7 +1186,7 @@ function generateMethodResult(type, templates) { return result } -function generateMethods(json = {}, examples = {}, templates = {}, type = '') { +function generateMethods(json = {}, examples = {}, templates = {}, languages = [], type = '') { const methods = compose( option([]), getMethods @@ -1215,7 +1215,7 @@ function generateMethods(json = {}, examples = {}, templates = {}, type = '') { else if (dir.includes('methods') && (suffix && config.templateExtensionMap[dir] ? config.templateExtensionMap[dir].includes(suffix) : true)) { const template = getTemplateForMethod(methodObj, templates, dir) if (template && template.length) { - result.body[dir] = insertMethodMacros(template, methodObj, json, templates, type, examples) + result.body[dir] = insertMethodMacros(template, methodObj, json, templates, type, examples, languages) } } }) @@ -1242,7 +1242,7 @@ function generateMethods(json = {}, examples = {}, templates = {}, type = '') { } // TODO: this is called too many places... let's reduce that to just generateMethods -function insertMethodMacros(template, methodObj, json, templates, type = '', examples = {}) { +function insertMethodMacros(template, methodObj, json, templates, type = '', examples = {}, languages = {}) { const moduleName = getModuleName(json) const info = { @@ -1378,6 +1378,23 @@ function insertMethodMacros(template, methodObj, json, templates, type = '', exa itemType = types.getSchemaType(result.schema.items, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) } + let signature + + if (Object.keys(languages).length && template.indexOf('${method.signature}') >= 0) { + const lang = languages[Object.keys(languages)[0]] + signature = getTemplateForDeclaration(methodObj, templates, 'declarations') + types.setTemplates(lang) + const currentConfig = JSON.parse(JSON.stringify(config)) + config.operators = config.operators || {} + config.operators.paramDelimiter = ', ' + signature = insertMethodMacros(signature, methodObj, json, lang, type) + config = currentConfig + types.setTemplates(templates) + } + else { + signature = '' + } + template = insertExampleMacros(template, examples[methodObj.name] || [], methodObj, json, templates) template = template.replace(/\$\{method\.name\}/g, method.name) .replace(/\$\{method\.rpc\.name\}/g, methodObj.rpc_name || methodObj.name) @@ -1403,6 +1420,7 @@ function insertMethodMacros(template, methodObj, json, templates, type = '', exa .replace(/\$\{method\.params\.serialization\}/g, serializedParams) .replace(/\$\{method\.params\.serialization\.with\.indent\}/g, indent(serializedParams, ' ')) // Typed signature stuff + .replace(/\$\{method\.signature\}/g, signature) .replace(/\$\{method\.signature\.params\}/g, types.getMethodSignatureParams(methodObj, json, { destination: state.destination, section: state.section })) .replace(/\$\{method\.signature\.result\}/g, types.getMethodSignatureResult(methodObj, json, { destination: state.destination, section: state.section })) .replace(/\$\{method\.context\}/g, method.context.join(', ')) @@ -1691,7 +1709,7 @@ function insertParameterMacros(template, param, method, module) { constraints = '
' + constraints } - return template + template = template .replace(/\$\{method.param.name\}/g, param.name) .replace(/\$\{method.param.Name\}/g, param.name[0].toUpperCase() + param.name.substring(1)) .replace(/\$\{method.param.summary\}/g, param.summary || '') @@ -1700,7 +1718,10 @@ function insertParameterMacros(template, param, method, module) { .replace(/\$\{json.param.type\}/g, jsonType) .replace(/\$\{method.param.link\}/g, getLinkForSchema(param.schema, module)) //getType(param)) .replace(/\$\{method.param.constraints\}/g, constraints) //getType(param)) -} + + return template + + } function insertCapabilityMacros(template, capabilities, method, module) { const content = [] diff --git a/src/macrofier/index.mjs b/src/macrofier/index.mjs index 99a1a3e0..298241f6 100644 --- a/src/macrofier/index.mjs +++ b/src/macrofier/index.mjs @@ -110,11 +110,6 @@ const macrofy = async ( const templates = Object.assign(await readFiles(sharedTemplateList, sharedTemplates), await readFiles(sdkTemplateList, template)) // sdkTemplates are second so they win ties - typer.setTemplates && typer.setTemplates(templates) - typer.setPrimitives(primitives) - typer.setAllocatedPrimitiveProxies(allocatedPrimitiveProxies) - typer.setConvertTuples(convertTuplesToArraysOrObjects) - let templatesPermission = {} if (persistPermission) { templatesPermission = Object.assign(await readFilesPermissions(sharedTemplateList, sharedTemplates), @@ -133,6 +128,22 @@ const macrofy = async ( exampleTemplates[config.name]['__config'] = config } + // check if this is a "real" language or just documentation broiler-plate, e.g. markdown + if (Object.keys(templates).find(key => key.startsWith('/types/primitive'))) { + typer.setTemplates && typer.setTemplates(templates) + typer.setPrimitives(primitives) + } + else { + const lang = Object.entries(exampleTemplates)[0][1] + const prims = Object.entries(exampleTemplates)[0][1]['__config'].primitives + // add the templates from the first example language and the wrapper langauage + typer.setTemplates && typer.setTemplates(lang) + typer.setTemplates && typer.setTemplates(templates) + typer.setPrimitives(prims) + } + typer.setAllocatedPrimitiveProxies(allocatedPrimitiveProxies) + typer.setConvertTuples(convertTuplesToArraysOrObjects) + const staticCodeList = staticContent ? await readDir(staticContent, { recursive: true }) : [] const staticModules = staticModuleNames.map(name => ( { info: { title: name } } )) diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index 55ef7b7e..6e854d15 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -724,7 +724,7 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin const theTitle = insertSchemaMacros(namespaceStr + getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent: getXSchemaGroup(schema, module), recursive: false }) const allocatedProxy = event || result - const title = schema.type === "object" || Array.isArray(schema.type) && schema.type.includes("object") || schema.enum ? true : false + const title = schema.type === "object" || schema.anyOf || schema.oneOf || Array.isArray(schema.type) && schema.type.includes("object") || schema.enum ? true : false if (schema['$ref']) { if (schema['$ref'][0] === '#') { From feddfbd880ac465a48b7ecc44624201078726460 Mon Sep 17 00:00:00 2001 From: "Shah, Kevin" Date: Tue, 4 Jun 2024 10:29:09 -0400 Subject: [PATCH 43/44] chore: Corrected package-lock.json --- package-lock.json | 70 ++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4945e7c6..7828c65c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "3.0.0-next.3", "license": "Apache-2.0", "dependencies": { - "ajv": "^8.3.0", - "ajv-formats": "^2.1.0", + "ajv": "^8.12.0", + "ajv-formats": "^2.1.1", "array.prototype.groupby": "^1.1.0", "crocks": "^0.12.4", "deepmerge": "^4.2.2", @@ -2436,14 +2436,14 @@ } }, "node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.15.0.tgz", + "integrity": "sha512-15BTtQUOsSrmHCy+B4VnAiJAJxJ8IFgu6fcjFQF3jQYZ78nLSQthlFg4ehp+NLIyfvFgOlxNsjKIEhydtFPVHQ==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.3.0", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -2451,9 +2451,9 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", - "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dependencies": { "ajv": "^8.0.0" }, @@ -3795,6 +3795,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "node_modules/fast-uri": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", + "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==" + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -10349,6 +10354,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { "node": ">=6" } @@ -11521,14 +11527,6 @@ "node": ">= 4.0.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -13766,20 +13764,20 @@ } }, "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.15.0.tgz", + "integrity": "sha512-15BTtQUOsSrmHCy+B4VnAiJAJxJ8IFgu6fcjFQF3jQYZ78nLSQthlFg4ehp+NLIyfvFgOlxNsjKIEhydtFPVHQ==", "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.3.0", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" } }, "ajv-formats": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", - "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "requires": { "ajv": "^8.0.0" } @@ -14809,6 +14807,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-uri": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", + "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==" + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -19519,7 +19522,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "q": { "version": "1.5.1", @@ -20400,14 +20404,6 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, "url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", From e1380a5902333276f275a92cf2bbd1a960c2ccc2 Mon Sep 17 00:00:00 2001 From: Jeremy LaCivita Date: Thu, 6 Jun 2024 11:35:17 -0400 Subject: [PATCH 44/44] fix: Support type: [null, ...] in getPropertySchema --- src/shared/json-schema.mjs | 2 +- src/shared/modules.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/json-schema.mjs b/src/shared/json-schema.mjs index 7fa54a8c..98fdeaba 100644 --- a/src/shared/json-schema.mjs +++ b/src/shared/json-schema.mjs @@ -155,7 +155,7 @@ const getPropertySchema = (json, dotPath, document) => { else if (property === '') { return node } - else if (node.type === 'object') { + else if (node.type === 'object' || (node.type && node.type.includes && node.type.includes('object'))) { if (node.properties && node.properties[property]) { node = node.properties[property] } diff --git a/src/shared/modules.mjs b/src/shared/modules.mjs index 4c6a6231..5fa64c6a 100644 --- a/src/shared/modules.mjs +++ b/src/shared/modules.mjs @@ -106,7 +106,7 @@ function getProviderInterface(capability, module, extractProviderSchema = false) { "name": "parameters", "required": true, - "schema": schema// payload.properties.parameters + "schema": schema } ]