import prompts from 'prompts' import colors from 'colors' import semver from 'semver' import { authOrNoAuthFiles, copyExistingEndpoint, createNewEndpointFromTemplate, getFunctionVersions, updateFileFunctionNames, updateIndexFile, validatePascalCase, } from './helpers' import { CreateFunctionState } from './types' import { checkIfInitShouldRun, getDirectories, getNamespaceDirectories, } from '../helpers' export const CreateFunction = async () => { const state: CreateFunctionState = { namespace: '', functionName: '', authenticated: false, external: false, version: '1.0.0', versionCopy: false, latestVersion: '', endpointPath: '', publicAPI: false, } let directories: any[] = [] if (checkIfInitShouldRun()) { directories = await getDirectories() } const namespace = await prompts({ type: 'select', name: 'answer', message: 'Create a new function in one of the following namespaces', choices: [ ...directories, { title: 'Create a new Namespace', value: 'new Namespace' }, ], }) if (namespace.answer !== 'new Namespace') { console.info('New Namespace', namespace.answer) state.namespace = namespace.answer let functionNames = [] if (checkIfInitShouldRun()) { functionNames = await getNamespaceDirectories(namespace.answer) } const functionName = await prompts([ { type: 'select', name: 'answer', message: 'Select one of the following functions:', choices: [ ...functionNames, { title: 'Create a New Function', value: 'New Function' }, ], }, { type: (prev) => (prev === 'New Function' ? 'text' : null), name: 'newFunctionName', message: 'FunctionName:', validate: (value) => validatePascalCase(value), }, ]) if (functionName.answer === 'New Function') { state.functionName = functionName.newFunctionName } else { state.functionName = functionName.answer // Create a new version const currentVersions = getFunctionVersions(state.namespace, state.functionName) console.info('Current Versions') currentVersions.forEach((version: string) => { console.info(version) }) const latestVersion = currentVersions[currentVersions.length - 1] state.latestVersion = latestVersion console.info('latestVersion', latestVersion) const nextMajorVersion = semver.inc(latestVersion, 'major') const nextMinorVersion = semver.inc(latestVersion, 'minor') const nextPatchVersion = semver.inc(latestVersion, 'patch') const version = await prompts([ { type: 'select', name: 'answer', message: 'Select the type of version you need to create', choices: [ { title: `New Major Version: ${nextMajorVersion}`, value: nextMajorVersion }, { title: `New Minor Version: ${nextMinorVersion}`, value: nextMinorVersion }, { title: `New Patch: ${nextPatchVersion}`, value: nextPatchVersion }, ], }, { type: 'confirm', name: 'copy', message: 'Would you like to copy the contents of the previous version?', initial: true, }, ]) state.version = version.answer state.versionCopy = version.copy } } else { const newFunction = await prompts([ { type: 'text', name: 'namespace', message: 'Namespace:', validate: (value) => validatePascalCase(value), }, { type: 'text', name: 'functionName', message: 'FunctionName:', validate: (value) => validatePascalCase(value), }, ]) state.namespace = newFunction.namespace state.functionName = newFunction.functionName } const boolQuestions: Array = [ { type: 'confirm', name: 'authenticated', message: 'Does this function require a user to have authenticated JWT to access it?', initial: true, }, { type: 'confirm', name: 'external', message: 'Will this be an external endpoint?', initial: true, }, { type: 'confirm', name: 'publicAPI', message: 'Will this endpoint be in the public OpenAPI documentation?', initial: false, }, ] const boolResponse = await prompts(boolQuestions) state.authenticated = boolResponse.authenticated state.external = boolResponse.external state.publicAPI = boolResponse.publicAPI const copy = state.version !== '1.0.0' ? ` ${colors.grey.underline('Copy Existing Version: ')}${colors.green(`${state.authenticated}`)}` : '' console.info(`\n ${colors.yellow.bold('Check The Information Below')}`) console.info(`\n ${colors.grey.underline('Namespace: ')}${colors.green(state.namespace)} ${colors.grey.underline('FunctionName: ')}${colors.green(state.functionName)} ${colors.grey.underline('Version: ')}${colors.green(state.version)}${copy} ${colors.grey.underline('Authentication: ')}${colors.green(`${state.authenticated}`)} ${colors.grey.underline('External Endpoint: ')}${colors.green(`${state.external}`)} ${colors.grey.underline('Public API Endpoint: ')}${colors.green(`${state.publicAPI}`)} \n`) state.endpointPath = `./API/${state.namespace}/${state.functionName}/${state.version}` const confirmation = await prompts({ type: 'confirm', name: 'answer', message: 'Is this correct? (Press enter to continue...)', initial: true, }) if (!confirmation.answer) { console.info(colors.red('Exiting... Nothing Created!')) process.exit(1) } console.info(colors.grey('Building your endpoint...')) if (state.versionCopy) { console.info(colors.green(`Copying file from version: ${state.latestVersion} >> ${state.version}`)) await copyExistingEndpoint(state) } else { await createNewEndpointFromTemplate(state) await authOrNoAuthFiles(state) } await updateFileFunctionNames(state) await updateIndexFile(state) console.info(colors.green(`\nSUCCESS \nAPI/${state.namespace}/${state.functionName}/${state.version} Created\n`)) return confirmation } export default CreateFunction