diff --git a/scripts/fetch-asyncapi-example.js b/scripts/fetch-asyncapi-example.js index a354b9d6d..2d319daaf 100644 --- a/scripts/fetch-asyncapi-example.js +++ b/scripts/fetch-asyncapi-example.js @@ -24,6 +24,26 @@ const parser = new Parser({ const SPEC_EXAMPLES_ZIP_URL = 'https://github.com/asyncapi/spec/archive/refs/heads/master.zip'; const EXAMPLE_DIRECTORY = path.join(__dirname, '../assets/examples'); const TEMP_ZIP_NAME = 'spec-examples.zip'; +const EXAMPLES_JSON_PATH = path.join(EXAMPLE_DIRECTORY, 'examples.json'); + +const shouldFetchExamples = (force = false) => { + if (force) { + console.log('Force flag detected, fetching examples...'); + return true; + } + if (!fs.existsSync(EXAMPLE_DIRECTORY)) { + return true; + } + if (!fs.existsSync(EXAMPLES_JSON_PATH)) { + return true; + } + const content = fs.readFileSync(EXAMPLES_JSON_PATH, { encoding: 'utf-8' }); + if (!content || content.trim() === '') { + return true; + } + console.log('Examples already exist, skipping fetch. Use --force to refresh.'); + return false; +}; const fetchAsyncAPIExamplesFromExternalURL = () => { try { @@ -119,6 +139,13 @@ const tidyUp = async () => { }; (async () => { + const args = process.argv.slice(2); + const force = args.includes('--force') || args.includes('-f'); + + if (!shouldFetchExamples(force)) { + return; + } + await fetchAsyncAPIExamplesFromExternalURL(); await unzipAsyncAPIExamples(); await buildCLIListFromExamples(); diff --git a/src/apps/cli/commands/generate/fromTemplate.ts b/src/apps/cli/commands/generate/fromTemplate.ts index 32ed32f97..87fd04b2a 100644 --- a/src/apps/cli/commands/generate/fromTemplate.ts +++ b/src/apps/cli/commands/generate/fromTemplate.ts @@ -1,7 +1,6 @@ import { Args } from '@oclif/core'; import { BaseGeneratorCommand } from '@cli/internal/base/BaseGeneratorCommand'; import { load, Specification } from '@models/SpecificationFile'; -import { ValidationError } from '@errors/validation-error'; import { GeneratorError } from '@errors/generator-error'; import { intro } from '@clack/prompts'; import { inverse } from 'picocolors'; @@ -65,19 +64,7 @@ export default class Template extends BaseGeneratorCommand { const watchTemplate = flags['watch']; const genOption = this.buildGenOption(flags, parsedFlags); - let specification: Specification; - try { - specification = await load(asyncapi); - } catch { - return this.error( - new ValidationError({ - - type: 'invalid-file', - filepath: asyncapi, - }), - { exit: 1 }, - ); - } + const specification = asyncapiInput; const result = await this.generatorService.generate( specification, diff --git a/src/utils/generate/registry.ts b/src/utils/generate/registry.ts index 16fdda2e5..47de8ae81 100644 --- a/src/utils/generate/registry.ts +++ b/src/utils/generate/registry.ts @@ -8,12 +8,26 @@ export function registryURLParser(input?: string) { export async function registryValidation(registryUrl?: string, registryAuth?: string, registryToken?: string) { if (!registryUrl) { return; } + const TIMEOUT_MS = 5000; + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS); + try { - const response = await fetch(registryUrl as string); + const response = await fetch(registryUrl as string, { + method: 'HEAD', + signal: controller.signal, + }); + clearTimeout(timeoutId); + if (response.status === 401 && !registryAuth && !registryToken) { throw new Error('You Need to pass either registryAuth in username:password encoded in Base64 or need to pass registryToken'); } - } catch { - throw new Error(`Can't fetch registryURL: ${registryUrl}`); + } catch (err: any) { + clearTimeout(timeoutId); + if (err.name === 'AbortError') { + throw new Error(`Registry URL timed out after ${TIMEOUT_MS}ms: ${registryUrl}`); + } + const cause = err.cause ? `\nCaused by: ${err.cause}` : ''; + throw new Error(`Can't fetch registryURL: ${registryUrl}${cause}`); } }