From fdb9d43db85db5d0f3ab16b57f32195ec991f1aa Mon Sep 17 00:00:00 2001 From: Rohith Pariki Date: Sat, 29 Aug 2026 06:55:55 +0530 Subject: [PATCH] fix(build): skip redundant AsyncAPI examples fetching when cached --- scripts/fetch-asyncapi-example.js | 64 ++++++++++++- .../scripts/fetch-asyncapi-example.test.ts | 94 +++++++++++++++++++ 2 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 test/unit/scripts/fetch-asyncapi-example.test.ts diff --git a/scripts/fetch-asyncapi-example.js b/scripts/fetch-asyncapi-example.js index a354b9d6d..fd1776f26 100644 --- a/scripts/fetch-asyncapi-example.js +++ b/scripts/fetch-asyncapi-example.js @@ -25,6 +25,38 @@ const SPEC_EXAMPLES_ZIP_URL = 'https://github.com/asyncapi/spec/archive/refs/hea const EXAMPLE_DIRECTORY = path.join(__dirname, '../assets/examples'); const TEMP_ZIP_NAME = 'spec-examples.zip'; +const shouldSkipFetching = (options = {}) => { + const force = options.force ?? ( + process.argv.includes('--force') || + process.argv.includes('-f') || + process.env.FORCE_FETCH_EXAMPLES === 'true' + ); + if (force) { + return false; + } + + const exampleDirectory = options.exampleDirectory || EXAMPLE_DIRECTORY; + const examplesJsonPath = options.examplesJsonPath || path.join(exampleDirectory, 'examples.json'); + + if (!fs.existsSync(examplesJsonPath) || !fs.existsSync(exampleDirectory)) { + return false; + } + + try { + const content = fs.readFileSync(examplesJsonPath, { encoding: 'utf-8' }); + const examples = JSON.parse(content); + if (!Array.isArray(examples) || examples.length === 0) { + return false; + } + + const files = fs.readdirSync(exampleDirectory); + const hasYamlFiles = files.some(file => file.endsWith('.yml') || file.endsWith('.yaml')); + return hasYamlFiles; + } catch (error) { + return false; + } +}; + const fetchAsyncAPIExamplesFromExternalURL = () => { try { return new Promise((resolve, reject) => { @@ -115,12 +147,38 @@ const listAllProtocolsForFile = (document) => { }; const tidyUp = async () => { - fs.unlinkSync(TEMP_ZIP_NAME); + if (fs.existsSync(TEMP_ZIP_NAME)) { + fs.unlinkSync(TEMP_ZIP_NAME); + } }; -(async () => { +const main = async (options = {}) => { + if (shouldSkipFetching(options)) { + console.log('AsyncAPI examples already exist. Skipping fetch (use --force or -f to re-fetch).'); + return; + } + await fetchAsyncAPIExamplesFromExternalURL(); await unzipAsyncAPIExamples(); await buildCLIListFromExamples(); await tidyUp(); -})(); +}; + +if (require.main === module) { + main().catch((error) => { + console.error(error); + process.exit(1); + }); +} + +module.exports = { + shouldSkipFetching, + main, + fetchAsyncAPIExamplesFromExternalURL, + unzipAsyncAPIExamples, + buildCLIListFromExamples, + listAllProtocolsForFile, + tidyUp, + EXAMPLE_DIRECTORY, + SPEC_EXAMPLES_ZIP_URL, +}; diff --git a/test/unit/scripts/fetch-asyncapi-example.test.ts b/test/unit/scripts/fetch-asyncapi-example.test.ts new file mode 100644 index 000000000..fb452f0c7 --- /dev/null +++ b/test/unit/scripts/fetch-asyncapi-example.test.ts @@ -0,0 +1,94 @@ +import { expect } from 'chai'; +import fs from 'fs'; +import path from 'path'; +import os from 'os'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { shouldSkipFetching } = require('../../../scripts/fetch-asyncapi-example'); + +describe('fetch-asyncapi-example script', () => { + let tempDir: string; + let examplesJsonPath: string; + + beforeEach(() => { + tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'asyncapi-examples-test-')); + examplesJsonPath = path.join(tempDir, 'examples.json'); + }); + + afterEach(() => { + if (fs.existsSync(tempDir)) { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it('should return false if examples.json does not exist', () => { + const shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: false, + }); + expect(shouldSkip).to.equal(false); + }); + + it('should return false if examples.json is empty or invalid JSON', () => { + fs.writeFileSync(examplesJsonPath, ''); + let shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: false, + }); + expect(shouldSkip).to.equal(false); + + fs.writeFileSync(examplesJsonPath, 'invalid json'); + shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: false, + }); + expect(shouldSkip).to.equal(false); + }); + + it('should return false if examples.json is an empty array', () => { + fs.writeFileSync(examplesJsonPath, JSON.stringify([])); + const shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: false, + }); + expect(shouldSkip).to.equal(false); + }); + + it('should return false if examples.json exists but no YAML spec files exist in directory', () => { + fs.writeFileSync(examplesJsonPath, JSON.stringify([{ name: 'test', value: 'test.yml' }])); + const shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: false, + }); + expect(shouldSkip).to.equal(false); + }); + + it('should return true if examples.json exists with entries and YAML spec files are present', () => { + fs.writeFileSync(examplesJsonPath, JSON.stringify([{ name: 'test', value: 'test.yml' }])); + fs.writeFileSync(path.join(tempDir, 'test.yml'), 'asyncapi: 2.6.0'); + + const shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: false, + }); + expect(shouldSkip).to.equal(true); + }); + + it('should return false when force is true even if cached files exist', () => { + fs.writeFileSync(examplesJsonPath, JSON.stringify([{ name: 'test', value: 'test.yml' }])); + fs.writeFileSync(path.join(tempDir, 'test.yml'), 'asyncapi: 2.6.0'); + + const shouldSkip = shouldSkipFetching({ + exampleDirectory: tempDir, + examplesJsonPath, + force: true, + }); + expect(shouldSkip).to.equal(false); + }); +});