From ab1755b3f611408fe9da48e0f2e243a745a4e497 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Thu, 11 Apr 2024 02:00:10 +0200 Subject: [PATCH] Improve a bit the project structure. --- src/api.ts | 330 ++---------------- src/app.ts | 17 +- src/constants.ts | 14 - src/controller/call.ts | 62 ++++ src/controller/delete.ts | 32 +- src/controller/deploy.ts | 92 +++++ .../errorHandler.ts => controller/error.ts} | 10 +- src/controller/logs.ts | 6 + src/controller/repository.ts | 116 ++++++ src/controller/static.ts | 36 ++ src/controller/upload.ts | 10 +- src/controller/validate.ts | 7 + src/server.ts | 12 +- src/utils/config.ts | 23 +- src/utils/responseTexts.ts | 13 - src/utils/utils.ts | 27 -- 16 files changed, 414 insertions(+), 393 deletions(-) create mode 100644 src/controller/call.ts create mode 100644 src/controller/deploy.ts rename src/{utils/errorHandler.ts => controller/error.ts} (74%) create mode 100644 src/controller/logs.ts create mode 100644 src/controller/repository.ts create mode 100644 src/controller/static.ts create mode 100644 src/controller/validate.ts delete mode 100644 src/utils/responseTexts.ts diff --git a/src/api.ts b/src/api.ts index d8e24fd..b347367 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,307 +1,27 @@ -import { spawn } from 'child_process'; -import colors from 'colors'; -import { NextFunction, Request, Response } from 'express'; -import { hostname } from 'os'; -import * as path from 'path'; - -import deployDeleteController from './controller/delete'; -import uploadController from './controller/upload'; - -import { - DeleteBody, - DeployBody, - Deployment, - FetchBranchListBody, - FetchFilesFromRepoBody, - ProtocolMessageType, - WorkerMessage, - WorkerMessageUnknown, - allApplications, - childProcesses, - deploymentMap -} from './constants'; - -import AppError from './utils/appError'; +import { callFunction } from './controller/call'; +import { deployDelete } from './controller/delete'; +import { deploy } from './controller/deploy'; +import { globalError } from './controller/error'; +import { logs } from './controller/logs'; import { - catchAsync, - deleteRepoFolderIfExist, - dirName, - ensureFolderExists, - execPromise, - exists, - installDependencies, - isIAllApps, - logProcessOutput -} from './utils/utils'; - -import { PackageError } from '@metacall/protocol/package'; -import { appsDirectory } from './utils/config'; - -const appsDir = appsDirectory(); - -colors.enable(); - -export const callFnByName = ( - req: Request, - res: Response, - next: NextFunction -): Response | void => { - if (!(req.params && req.params.name)) - next( - new AppError( - 'A function name is required in the path; i.e: /call/sum.', - 404 - ) - ); - - const { appName: app, name } = req.params; - const args = Object.values(req.body); - - if (!(app in childProcesses)) { - return res - .status(404) - .send( - `Oops! It looks like the application (${app}) hasn't been deployed yet. Please deploy it before you can call its functions.` - ); - } - - let responseSent = false; // Flag to track if response has been sent - let errorCame = false; - - childProcesses[app].send({ - type: ProtocolMessageType.Invoke, - data: { - name, - args - } - }); - - childProcesses[app].on('message', (message: WorkerMessageUnknown) => { - if (!responseSent) { - // Check if response has already been sent - if (message.type === ProtocolMessageType.InvokeResult) { - responseSent = true; // Set flag to true to indicate response has been sent - return res.send(JSON.stringify(message.data)); - } else { - errorCame = true; - } - } - }); - - // Default response in case the 'message' event is not triggered - if (!responseSent && errorCame) { - responseSent = true; // Set flag to true to indicate response has been sent - errorCame = false; - return res.send('Function calling error'); - } + fetchBranchList, + fetchFileList, + fetchFilesFromRepo +} from './controller/repository'; +import { serveStatic } from './controller/static'; +import { uploadPackage } from './controller/upload'; +import { validate } from './controller/validate'; + +export default { + callFunction, + deployDelete, + deploy, + globalError, + logs, + fetchFilesFromRepo, + fetchBranchList, + fetchFileList, + serveStatic, + uploadPackage, + validate }; - -export const serveStatic = catchAsync( - async (req: Request, res: Response, next: NextFunction): Promise => { - if (!req.params) next(new AppError('Invalid API endpoint', 404)); - - const { app, file } = req.params; - - const appLocation = path.join(appsDir, `${app}/${file}`); - - if (!(app in childProcesses)) { - next( - new AppError( - `Oops! It looks like the application (${app}) hasn't been deployed yet. Please deploy it before you can call its functions.`, - 404 - ) - ); - } - - if (!(await exists(appLocation))) - next( - new AppError( - "The file you're looking for might not be available or the application may not be deployed.", - 404 - ) - ); - - return res.status(200).sendFile(appLocation); - } -); - -export const fetchFiles = ( - req: Request, - res: Response, - next: NextFunction -): void => uploadController(req, res, next); - -export const fetchFilesFromRepo = catchAsync( - async ( - req: Omit & { body: FetchFilesFromRepoBody }, - res: Response, - next: NextFunction - ) => { - const { branch, url } = req.body; - - await ensureFolderExists(appsDir); - - try { - await deleteRepoFolderIfExist(appsDir, url); - } catch (err) { - next( - new AppError( - 'error occurred in deleting repository directory', - 500 - ) - ); - } - - await execPromise( - `cd ${appsDir}; git clone --single-branch --depth=1 --branch ${branch} ${url} ` - ); - - const id = dirName(req.body.url); - - // TODO: This method is wrong - // deployment.id = id; - // deployment.path = `${appsDir}/${id}`; - - return res.status(201).send({ id }); - } -); - -export const fetchBranchList = catchAsync( - async ( - req: Omit & { body: FetchBranchListBody }, - res: Response - ) => { - const { stdout } = await execPromise( - `git ls-remote --heads ${req.body.url}` - ); - - const branches: string[] = []; - - JSON.stringify(stdout.toString()) - .split('\\n') - .forEach(el => { - if (el.trim().length > 1) { - branches.push(el.split('refs/heads/')[1]); - } - }); - - return res.send({ branches }); - } -); - -export const fetchFileList = catchAsync( - async ( - req: Omit & { body: FetchFilesFromRepoBody }, - res: Response, - next: NextFunction - ) => { - await ensureFolderExists(appsDir); - - try { - await deleteRepoFolderIfExist(appsDir, req.body.url); - } catch (err) { - next( - new AppError( - 'error occurred in deleting repository directory', - 500 - ) - ); - } - await execPromise( - `cd ${appsDir} ; git clone ${req.body.url} --depth=1 --no-checkout` - ); - - const dirPath = `${appsDir}/${dirName(req.body.url)}`; - - const { stdout } = await execPromise( - `cd ${dirPath} ; git ls-tree -r ${req.body.branch} --name-only; cd .. ; rm -r ${dirPath}` - ); - - return res.send({ - files: JSON.stringify(stdout.toString()).split('\\n') - }); - } -); - -export const deploy = catchAsync( - async ( - req: Omit & { body: DeployBody }, - res: Response, - next: NextFunction - ) => { - try { - // TODO: Implement repository - // req.body.resourceType == 'Repository' && - // (await calculatePackages(next)); - - const deployment = deploymentMap[req.body.suffix]; - - if (deployment === undefined) { - return next( - new AppError( - `Invalid deployment id: ${req.body.suffix}`, - 400 - ) - ); - } - - await installDependencies(deployment); - - const desiredPath = path.join(__dirname, 'worker', 'index.js'); - - const proc = spawn('metacall', [desiredPath], { - stdio: ['pipe', 'pipe', 'pipe', 'ipc'] - }); - - proc.send({ - type: ProtocolMessageType.Load, - data: deployment - }); - - logProcessOutput(proc.stdout, proc.pid, deployment.id); - logProcessOutput(proc.stderr, proc.pid, deployment.id); - - proc.on('message', (payload: WorkerMessageUnknown) => { - if (payload.type === ProtocolMessageType.MetaData) { - const message = payload as WorkerMessage; - if (isIAllApps(message.data)) { - const appName = Object.keys(message.data)[0]; - childProcesses[appName] = proc; - allApplications[appName] = message.data[appName]; - } - } - }); - - return res.status(200).json({ - suffix: hostname(), - prefix: deployment.id, - version: 'v1' - }); - } catch (err) { - // Check if the error is PackageError.Empty - if (err === PackageError.Empty) { - return next(err); - } - return next(err); - } - } -); - -export const showLogs = (req: Request, res: Response): Response => { - return res.send('Demo Logs...'); -}; - -export const deployDelete = ( - req: Omit & { body: DeleteBody }, - res: Response, - next: NextFunction -): void => deployDeleteController(req, res, next); - -export const validateAndDeployEnabled = ( - req: Request, - res: Response -): Response => - res.status(200).json({ - status: 'success', - data: true - }); diff --git a/src/app.ts b/src/app.ts index c40d83e..740421a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,10 +2,9 @@ import { hostname } from 'os'; import express, { NextFunction, Request, Response } from 'express'; -import * as api from './api'; +import api from './api'; import { allApplications } from './constants'; import AppError from './utils/appError'; -import globalErrorHandler from './utils/errorHandler'; const app = express(); const host = hostname(); @@ -13,25 +12,25 @@ const host = hostname(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); -app.get('/validate', api.validateAndDeployEnabled); -app.get('/api/account/deploy-enabled', api.validateAndDeployEnabled); +app.get('/validate', api.validate); +app.get('/api/account/deploy-enabled', api.validate); -app.post(`/${host}/:appName/:version/call/:name`, api.callFnByName); +app.post(`/${host}/:appName/:version/call/:name`, api.callFunction); app.get( `/${host}/:appName/:version/static/.metacall/faas/apps/:app/:file`, api.serveStatic ); -app.post('/api/package/create', api.fetchFiles); +app.post('/api/package/create', api.uploadPackage); app.post('/api/repository/add', api.fetchFilesFromRepo); app.post('/api/repository/branchlist', api.fetchBranchList); app.post('/api/repository/filelist', api.fetchFileList); -app.post('/api/deploy/logs', api.showLogs); +app.post('/api/deploy/logs', api.logs); app.post('/api/deploy/create', api.deploy); -app.get('/api/inspect', (req, res) => { +app.get('/api/inspect', (_req, res) => { res.send(Object.values(allApplications)); }); @@ -42,6 +41,6 @@ app.all('*', (req: Request, res: Response, next: NextFunction) => { next(new AppError(`Can't find ${req.originalUrl} on this server!`, 404)); }); -app.use(globalErrorHandler); +app.use(api.globalError); export default app; diff --git a/src/constants.ts b/src/constants.ts index 9cce1ee..e31f3e5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,14 +25,6 @@ export const createInstallDependenciesScript = ( return installDependenciesScript[runner]; }; -export type FetchFilesFromRepoBody = { - branch: 'string'; - url: 'string'; -}; -export type FetchBranchListBody = { - url: 'string'; -}; - export type DeployBody = { suffix: string; // name of deployment resourceType: 'Package' | 'Repository'; @@ -42,12 +34,6 @@ export type DeployBody = { version: string; }; -export type DeleteBody = { - suffix: string; // name of deployment - prefix: string; - version: string; -}; - export type tpackages = Record; export interface IApp { diff --git a/src/controller/call.ts b/src/controller/call.ts new file mode 100644 index 0000000..fa80bdc --- /dev/null +++ b/src/controller/call.ts @@ -0,0 +1,62 @@ +import { NextFunction, Request, Response } from 'express'; +import { + ProtocolMessageType, + WorkerMessageUnknown, + childProcesses +} from '../constants'; +import AppError from '../utils/appError'; + +export const callFunction = ( + req: Request, + res: Response, + next: NextFunction +): Response | void => { + if (!(req.params && req.params.name)) + next( + new AppError( + 'A function name is required in the path; i.e: /call/sum.', + 404 + ) + ); + + const { appName: app, name } = req.params; + const args = Object.values(req.body); + + if (!(app in childProcesses)) { + return res + .status(404) + .send( + `Oops! It looks like the application (${app}) hasn't been deployed yet. Please deploy it before you can call its functions.` + ); + } + + let responseSent = false; // Flag to track if response has been sent + let errorCame = false; + + childProcesses[app].send({ + type: ProtocolMessageType.Invoke, + data: { + name, + args + } + }); + + childProcesses[app].on('message', (message: WorkerMessageUnknown) => { + if (!responseSent) { + // Check if response has already been sent + if (message.type === ProtocolMessageType.InvokeResult) { + responseSent = true; // Set flag to true to indicate response has been sent + return res.send(JSON.stringify(message.data)); + } else { + errorCame = true; + } + } + }); + + // Default response in case the 'message' event is not triggered + if (!responseSent && errorCame) { + responseSent = true; // Set flag to true to indicate response has been sent + errorCame = false; + return res.send('Function calling error'); + } +}; diff --git a/src/controller/delete.ts b/src/controller/delete.ts index f7e0d20..e9b211a 100644 --- a/src/controller/delete.ts +++ b/src/controller/delete.ts @@ -1,15 +1,35 @@ +import { NextFunction, Request, Response } from 'express'; + import { ChildProcess } from 'child_process'; import { rmSync } from 'fs'; import { join } from 'path'; -import { NextFunction, Request, Response } from 'express'; - -import { allApplications, childProcesses, DeleteBody } from '../constants'; +import { allApplications, childProcesses } from '../constants'; import { appsDirectory } from '../utils/config'; -import { deleteStatusMessage } from '../utils/responseTexts'; import { catchAsync, ensureFolderExists } from '../utils/utils'; -export default catchAsync( +const deleteStatusMessage = ( + app: string +): { + success: string; + error: string; + folderShouldntExist: string; + appShouldntExist: string; +} => ({ + success: 'Deploy Delete Succeed', + error: `Oops! It looks like the application (${app}) hasn't been deployed yet. Please deploy it before you delete it.`, + folderShouldntExist: `The folder shouldnt exist after deleting it.`, + appShouldntExist: `The application shouldnt exist after deleting it` +}); + +type DeleteBody = { + suffix: string; // name of deployment + prefix: string; + version: string; +}; + +// TODO: Refactor this, do not use sync methods +export const deployDelete = catchAsync( async ( req: Omit & { body: DeleteBody }, res: Response, @@ -41,7 +61,7 @@ export default catchAsync( } // Determine the location of the application - const appLocation = join(appsDirectory(), app); + const appLocation = join(appsDirectory, app); // Delete the directory of the application rmSync(appLocation, { recursive: true, force: true }); diff --git a/src/controller/deploy.ts b/src/controller/deploy.ts new file mode 100644 index 0000000..057e724 --- /dev/null +++ b/src/controller/deploy.ts @@ -0,0 +1,92 @@ +import { spawn } from 'child_process'; +import { NextFunction, Request, Response } from 'express'; +import { hostname } from 'os'; +import path from 'path'; + +import { + DeployBody, + ProtocolMessageType, + WorkerMessageUnknown, + allApplications, + childProcesses, + deploymentMap +} from '../constants'; + +import AppError from '../utils/appError'; + +import { + catchAsync, + installDependencies, + isIAllApps, + logProcessOutput +} from '../utils/utils'; + +import { PackageError } from '@metacall/protocol/package'; + +export const deploy = catchAsync( + async ( + req: Omit & { body: DeployBody }, + res: Response, + next: NextFunction + ) => { + try { + // TODO: Implement repository + // req.body.resourceType == 'Repository' && + // (await calculatePackages(next)); + + const deployment = deploymentMap[req.body.suffix]; + + if (deployment === undefined) { + return next( + new AppError( + `Invalid deployment id: ${req.body.suffix}`, + 400 + ) + ); + } + + await installDependencies(deployment); + + const desiredPath = path.join( + path.resolve(__dirname, '..'), + 'worker', + 'index.js' + ); + + const proc = spawn('metacall', [desiredPath], { + stdio: ['pipe', 'pipe', 'pipe', 'ipc'] + }); + + proc.send({ + type: ProtocolMessageType.Load, + data: deployment + }); + + logProcessOutput(proc.stdout, proc.pid, deployment.id); + logProcessOutput(proc.stderr, proc.pid, deployment.id); + + proc.on('message', (payload: WorkerMessageUnknown) => { + if (payload.type === ProtocolMessageType.MetaData) { + const message = payload; + if (isIAllApps(message.data)) { + const appName = Object.keys(message.data)[0]; + childProcesses[appName] = proc; + allApplications[appName] = message.data[appName]; + } + } + }); + + return res.status(200).json({ + suffix: hostname(), + prefix: deployment.id, + version: 'v1' + }); + } catch (err) { + // Check if the error is PackageError.Empty + if (err === PackageError.Empty) { + return next(err); + } + return next(err); + } + } +); diff --git a/src/utils/errorHandler.ts b/src/controller/error.ts similarity index 74% rename from src/utils/errorHandler.ts rename to src/controller/error.ts index 204869d..7e1d9a4 100644 --- a/src/utils/errorHandler.ts +++ b/src/controller/error.ts @@ -1,13 +1,11 @@ -/* eslint-disable */ - import { NextFunction, Request, Response } from 'express'; -import { IAppError } from './appError'; +import { IAppError } from '../utils/appError'; -const globalErroHandler = ( +export const globalError = ( err: IAppError, req: Request, res: Response, - next: NextFunction + _next: NextFunction ): Response => { err.statusCode = err.statusCode || 500; err.status = err.status || 'error'; @@ -22,5 +20,3 @@ const globalErroHandler = ( return res.status(err.statusCode).send(err.message); }; - -export default globalErroHandler; diff --git a/src/controller/logs.ts b/src/controller/logs.ts new file mode 100644 index 0000000..69f7953 --- /dev/null +++ b/src/controller/logs.ts @@ -0,0 +1,6 @@ +import { Request, Response } from 'express'; + +// TODO: Implement logs +export const logs = (req: Request, res: Response): Response => { + return res.send('TODO: Implement Logs...'); +}; diff --git a/src/controller/repository.ts b/src/controller/repository.ts new file mode 100644 index 0000000..a700ac7 --- /dev/null +++ b/src/controller/repository.ts @@ -0,0 +1,116 @@ +import { NextFunction, Request, Response } from 'express'; +import { promises as fs } from 'fs'; +import { join } from 'path'; +import AppError from '../utils/appError'; +import { appsDirectory } from '../utils/config'; +import { catchAsync, execPromise } from '../utils/utils'; + +type FetchFilesFromRepoBody = { + branch: 'string'; + url: 'string'; +}; + +type FetchBranchListBody = { + url: 'string'; +}; + +const dirName = (gitUrl: string): string => + String(gitUrl.split('/')[gitUrl.split('/').length - 1]).replace('.git', ''); + +const deleteRepoFolderIfExist = async ( + path: Path, + url: string +): Promise => { + const folder = dirName(url); + const repoFilePath = join(path, folder); + + await fs.rm(repoFilePath, { recursive: true, force: true }); +}; + +export const fetchFilesFromRepo = catchAsync( + async ( + req: Omit & { body: FetchFilesFromRepoBody }, + res: Response, + next: NextFunction + ) => { + const { branch, url } = req.body; + + try { + await deleteRepoFolderIfExist(appsDirectory, url); + } catch (err) { + next( + new AppError( + 'error occurred in deleting repository directory', + 500 + ) + ); + } + + await execPromise( + `cd ${appsDirectory} && git clone --single-branch --depth=1 --branch ${branch} ${url} ` + ); + + const id = dirName(req.body.url); + + // TODO: This method is wrong + // deployment.id = id; + // deployment.path = `${appsDir}/${id}`; + + return res.status(201).send({ id }); + } +); + +export const fetchBranchList = catchAsync( + async ( + req: Omit & { body: FetchBranchListBody }, + res: Response + ) => { + const { stdout } = await execPromise( + `git ls-remote --heads ${req.body.url}` + ); + + const branches: string[] = []; + + JSON.stringify(stdout.toString()) + .split('\\n') + .forEach(el => { + if (el.trim().length > 1) { + branches.push(el.split('refs/heads/')[1]); + } + }); + + return res.send({ branches }); + } +); + +export const fetchFileList = catchAsync( + async ( + req: Omit & { body: FetchFilesFromRepoBody }, + res: Response, + next: NextFunction + ) => { + try { + await deleteRepoFolderIfExist(appsDirectory, req.body.url); + } catch (err) { + next( + new AppError( + 'error occurred in deleting repository directory', + 500 + ) + ); + } + await execPromise( + `cd ${appsDirectory} ; git clone ${req.body.url} --depth=1 --no-checkout` + ); + + const dirPath = `${appsDirectory}/${dirName(req.body.url)}`; + + const { stdout } = await execPromise( + `cd ${dirPath} ; git ls-tree -r ${req.body.branch} --name-only; cd .. ; rm -r ${dirPath}` + ); + + return res.send({ + files: JSON.stringify(stdout.toString()).split('\\n') + }); + } +); diff --git a/src/controller/static.ts b/src/controller/static.ts new file mode 100644 index 0000000..7b31110 --- /dev/null +++ b/src/controller/static.ts @@ -0,0 +1,36 @@ +import { NextFunction, Request, Response } from 'express'; +import path from 'path'; + +import { childProcesses } from '../constants'; +import AppError from '../utils/appError'; +import { appsDirectory } from '../utils/config'; +import { catchAsync, exists } from '../utils/utils'; + +export const serveStatic = catchAsync( + async (req: Request, res: Response, next: NextFunction): Promise => { + if (!req.params) next(new AppError('Invalid API endpoint', 404)); + + const { app, file } = req.params; + + const appLocation = path.join(appsDirectory, `${app}/${file}`); + + if (!(app in childProcesses)) { + next( + new AppError( + `Oops! It looks like the application (${app}) hasn't been deployed yet. Please deploy it before you can call its functions.`, + 404 + ) + ); + } + + if (!(await exists(appLocation))) + next( + new AppError( + "The file you're looking for might not be available or the application may not be deployed.", + 404 + ) + ); + + return res.status(200).sendFile(appLocation); + } +); diff --git a/src/controller/upload.ts b/src/controller/upload.ts index 87831fd..4b530ad 100644 --- a/src/controller/upload.ts +++ b/src/controller/upload.ts @@ -13,8 +13,6 @@ import AppError from '../utils/appError'; import { appsDirectory } from '../utils/config'; import { ensureFolderExists } from '../utils/utils'; -const appsDir = appsDirectory(); - const getUploadError = ( on: keyof busboy.BusboyEvents, error: Error @@ -46,7 +44,11 @@ const getUploadError = ( return new AppError(appError.message, appError.code); }; -export default (req: Request, res: Response, next: NextFunction): void => { +export const uploadPackage = ( + req: Request, + res: Response, + next: NextFunction +): void => { const bb = busboy({ headers: req.headers }); const deployment: Deployment = { id: '', @@ -89,7 +91,7 @@ export default (req: Request, res: Response, next: NextFunction): void => { ); } - const appLocation = path.join(appsDir, deployment.id); + const appLocation = path.join(appsDirectory, deployment.id); deployment.path = appLocation; // Create temporary directory for the blob diff --git a/src/controller/validate.ts b/src/controller/validate.ts new file mode 100644 index 0000000..8d2db59 --- /dev/null +++ b/src/controller/validate.ts @@ -0,0 +1,7 @@ +import { Request, Response } from 'express'; + +export const validate = (req: Request, res: Response): Response => + res.status(200).json({ + status: 'success', + data: true + }); diff --git a/src/server.ts b/src/server.ts index b8ab54e..e58025e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,4 +1,5 @@ -import * as dotenv from 'dotenv'; +import colors from 'colors'; +import dotenv from 'dotenv'; import app from './app'; import { findJsonFilesRecursively } from './utils/autoDeploy'; @@ -9,14 +10,15 @@ import { ensureFolderExists } from './utils/utils'; void (async (): Promise => { try { dotenv.config(); + colors.enable(); - const appsDir = appsDirectory(); + await ensureFolderExists(appsDirectory); - await ensureFolderExists(appsDir); - - await findJsonFilesRecursively(appsDir); + // TODO: Refactor this + await findJsonFilesRecursively(appsDirectory); console.log('Previously deployed apllications deployed successfully'); + // END-TODO const port = process.env.PORT || 9000; diff --git a/src/utils/config.ts b/src/utils/config.ts index 03bcdc7..bae32f9 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,23 @@ +import { platform } from 'os'; import { join } from 'path'; -import { configDir } from './utils'; -export const defaultPath = configDir(join('metacall', 'faas')); +const missing = (name: string): Error => + new Error(`Missing ${name} environment variable! Unable to load config`); -export const appsDirectory = (path = defaultPath): string => join(path, 'apps'); +export const configDir = (name: string): string => { + if (platform() === 'win32') { + if (process.env.APPDATA === undefined) { + throw missing('APPDATA'); + } + return join(process.env.APPDATA, name); + } else { + if (process.env.HOME === undefined) { + throw missing('HOME'); + } + return join(process.env.HOME, `.${name}`); + } +}; + +export const basePath = configDir(join('metacall', 'faas')); + +export const appsDirectory = join(basePath, 'apps'); diff --git a/src/utils/responseTexts.ts b/src/utils/responseTexts.ts deleted file mode 100644 index c0e25af..0000000 --- a/src/utils/responseTexts.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const deleteStatusMessage = ( - app: string -): { - success: string; - error: string; - folderShouldntExist: string; - appShouldntExist: string; -} => ({ - success: 'Deploy Delete Succeed', - error: `Oops! It looks like the application (${app}) hasn't been deployed yet. Please deploy it before you delete it.`, - folderShouldntExist: `The folder shouldnt exist after deleting it.`, - appShouldntExist: `The application shouldnt exist after deleting it` -}); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 80c25fc..4183cbd 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,7 +1,5 @@ import { exec } from 'child_process'; import { promises as fs } from 'fs'; -import { platform } from 'os'; -import { join } from 'path'; import { LanguageId, MetaCallJSON } from '@metacall/protocol/deployment'; import { PackageError, generatePackage } from '@metacall/protocol/package'; @@ -19,9 +17,6 @@ import { } from '../constants'; import { logger } from './logger'; -export const dirName = (gitUrl: string): string => - String(gitUrl.split('/')[gitUrl.split('/').length - 1]).replace('.git', ''); - export const installDependencies = async ( deployment: Deployment ): Promise => { @@ -66,16 +61,6 @@ export const ensureFolderExists = async ( (await exists(path)) || (await fs.mkdir(path, { recursive: true })), path ); -export const deleteRepoFolderIfExist = async ( - path: Path, - url: string -): Promise => { - const folder = dirName(url); - const repoFilePath = join(path, folder); - - await fs.rm(repoFilePath, { recursive: true, force: true }); -}; - export const execPromise = ( command: string ): Promise<{ @@ -122,18 +107,6 @@ export const createMetacallJsonFile = async ( return acc; }; -const missing = (name: string): string => - `Missing ${name} environment variable! Unable to load config`; - -export const configDir = (name: string): string => - platform() === 'win32' - ? process.env.APPDATA - ? join(process.env.APPDATA, name) - : missing('APPDATA') - : process.env.HOME - ? join(process.env.HOME, `.${name}`) - : missing('HOME'); - export const getLangId = (input: string): LanguageId => { const parts = input.split('-'); const extension = parts[parts.length - 1].split('.')[0];