diff --git a/assets/create-template/templates/default/package.json b/assets/create-template/templates/default/package.json new file mode 100644 index 00000000000..3f62f87610c --- /dev/null +++ b/assets/create-template/templates/default/package.json @@ -0,0 +1,12 @@ +{ + "name": "myTemplate", + "generator": { + "renderer": "react", + "supportedProtocols": [ + "mqtt" + ] + }, + "dependencies": { + "@asyncapi/generator-react-sdk": "^0.2.25" + } +} diff --git a/assets/create-template/templates/default/readme.md b/assets/create-template/templates/default/readme.md new file mode 100644 index 00000000000..5eb70fdea5e --- /dev/null +++ b/assets/create-template/templates/default/readme.md @@ -0,0 +1,4 @@ +### First install all the dependencies for template using below command: +npm install +### Run the template using for a specific asyncapi document + asyncapi generate fromTemplate ../asyncapi-template \ No newline at end of file diff --git a/assets/create-template/templates/default/template/index.js b/assets/create-template/templates/default/template/index.js new file mode 100644 index 00000000000..caf30a6b1c2 --- /dev/null +++ b/assets/create-template/templates/default/template/index.js @@ -0,0 +1,10 @@ +import { File, Text } from '@asyncapi/generator-react-sdk'; + +export default function ({ asyncapi, params, originalAsyncAPI }) { + return ( + + My application's markdown file. + App name: **{asyncapi.info().title()}** + + ); +} diff --git a/assets/create-template/templates/default/template/package.json.js b/assets/create-template/templates/default/template/package.json.js new file mode 100644 index 00000000000..1db86f985ce --- /dev/null +++ b/assets/create-template/templates/default/template/package.json.js @@ -0,0 +1,21 @@ + +import { File } from '@asyncapi/generator-react-sdk'; +import fetch from 'node-fetch'; +export default async function ({ asyncapi }) { + const description = asyncapi.info().description(); + const packageName = '@asyncapi/generator-react-sdk'; + const npmRegistryUrl = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`; + const response = await fetch(npmRegistryUrl); + const data = await response.json(); + const generatorSDKversion = data['dist-tags'].latest; + return ( + {`{ + "name": "${asyncapi.info().title().toLowerCase().replace(/ /g, '-')}", + "version": "0.1.0", + "description": "${description ? asyncapi.info().description().split('\n')[0] : ''}", + "dependencies": { + "@asyncapi/generator-react-sdk": "^${generatorSDKversion}" + } +}`} + ); +} diff --git a/src/commands/new/template.ts b/src/commands/new/template.ts new file mode 100644 index 00000000000..7c50477a205 --- /dev/null +++ b/src/commands/new/template.ts @@ -0,0 +1,90 @@ +import { promises as fPromises } from 'fs'; +import Command from '../../core/base'; +import { resolve, join } from 'path'; +import {load } from '../../core/models/SpecificationFile'; +import fs from 'fs-extra'; +import { templateFlags } from '../../core/flags/new/template.flags'; +import { cyan, gray } from 'picocolors'; + +export const successMessage = (projectName: string) => + `🎉 Your template is succesfully created +⏩ Next steps: follow the instructions ${cyan('below')} to manage your project: + + cd ${projectName}\t\t ${gray('# Navigate to the project directory')} + npm install\t\t ${gray('# Install the project dependencies')} + asyncapi generate fromTemplate ../${projectName} \t\t ${gray('# Execute the template from anasyncapi document')} + +You can also open the project in your favourite editor and start tweaking it. +`; + +const errorMessages = { + alreadyExists: (projectName: string) => + `Unable to create the project because the directory "${cyan(projectName)}" already exists at "${process.cwd()}/${projectName}". +To specify a different name for the new project, please run the command below with a unique project name: + + ${gray('asyncapi new template --name ') + gray(projectName) + gray('-1')}`, +}; + +export default class template extends Command { + static description = 'Creates a new template'; + protected commandName = 'template'; + static readonly successMessage = successMessage; + static readonly errorMessages = errorMessages; + static flags = templateFlags(); + + async run() { + const { flags } = await this.parse(template); // NOSONA + + const { + name: projectName, + template: templateName, + file, + 'force-write': forceWrite, + } = flags; + + const PROJECT_DIRECTORY = join(process.cwd(), projectName); + + const templateDirectory = resolve( + __dirname, + '../../../assets/create-template/templates/', + templateName + ); + + { + try { + await fPromises.mkdir(PROJECT_DIRECTORY); + } catch (err: any) { + switch (err.code) { + case 'EEXIST': + this.error(errorMessages.alreadyExists(projectName)); + break; + case 'EACCES': + this.error( + `Unable to create the project. We tried to access the "${PROJECT_DIRECTORY}" directory but it was not possible due to file access permissions. Please check the write permissions of your current working directory ("${process.cwd()}").` + ); + break; + case 'EPERM': + this.error( + `Unable to create the project. We tried to create the "${PROJECT_DIRECTORY}" directory but the operation requires elevated privileges. Please check the privileges for your current user.` + ); + break; + default: + this.error( + `Unable to create the project. Please check the following message for further info about the error:\n\n${err}` + ); + } + } + + try { + await fs.copy(templateDirectory, PROJECT_DIRECTORY); + this.log(successMessage(projectName)); + } catch (err) { + this.error( + `Unable to create the project. Please check the following message for further info about the error:\n\n${err}` + ); + } + this.specFile = await load(`${templateDirectory}/asyncapi.yml`); + this.metricsMetadata.template = flags.template; + } + } +} diff --git a/src/core/flags/new/template.flags.ts b/src/core/flags/new/template.flags.ts new file mode 100644 index 00000000000..5aebde1866e --- /dev/null +++ b/src/core/flags/new/template.flags.ts @@ -0,0 +1,27 @@ +import { Flags } from '@oclif/core'; + +export const templateFlags = () => { + return { + help: Flags.help({ char: 'h' }), + name: Flags.string({ + char: 'n', + description: 'Name of the Project', + default: 'project', + }), + template: Flags.string({ + char: 't', + description: 'Name of the Template', + default: 'default', + }), + file: Flags.string({ + char: 'f', + description: + 'The path to the AsyncAPI file for generating a template.', + }), + 'force-write': Flags.boolean({ + default: false, + description: + 'Force writing of the generated files to given directory even if it is a git repo with unstaged files or not empty dir (defaults to false)', + }), + }; +};