diff --git a/packages/zcli-apps/src/lib/package.test.ts b/packages/zcli-apps/src/lib/package.test.ts index 68ee0dd5..d6fab452 100644 --- a/packages/zcli-apps/src/lib/package.test.ts +++ b/packages/zcli-apps/src/lib/package.test.ts @@ -7,6 +7,7 @@ describe('package', () => { describe('validatePkg', () => { test .stub(fs, 'pathExistsSync', () => true) + .stub(fs, 'readFile', () => Promise.resolve('file content')) .stub(request, 'requestAPI', () => Promise.resolve({ status: 200 })) .it('should return true if package is valid', async () => { expect(await validatePkg('./app-path')).to.equal(true) @@ -14,19 +15,25 @@ describe('package', () => { test .stub(fs, 'pathExistsSync', () => true) + .stub(fs, 'readFile', () => Promise.resolve('file content')) .stub(request, 'requestAPI', () => Promise.resolve({ status: 400, data: { description: 'invalid location' } })) - .do(async () => { - await validatePkg('./app-path') + .it('should throw if package has validation errors', async () => { + try { + await validatePkg('./app-path') + } catch (error: any) { + expect(error.message).to.equal('invalid location') + } }) - .catch('invalid location') - .it('should throw if package has validation errors') test .stub(fs, 'pathExistsSync', () => false) - .do(async () => { - await validatePkg('./bad-path') + .stub(fs, 'readFile', () => Promise.reject()) + .it('should throw if app path is invalid', async () => { + try { + await validatePkg('./bad-path') + } catch (error: any) { + expect(error.message).to.equal('Package not found at ./bad-path') + } }) - .catch('Package not found at ./bad-path') - .it('should throw if app path is invalid') }) }) diff --git a/packages/zcli-apps/src/lib/package.ts b/packages/zcli-apps/src/lib/package.ts index 8243fc89..bd0d087e 100644 --- a/packages/zcli-apps/src/lib/package.ts +++ b/packages/zcli-apps/src/lib/package.ts @@ -1,49 +1,56 @@ import * as path from 'path' import * as fs from 'fs-extra' -import * as FormData from 'form-data' import { request } from '@zendesk/zcli-core' import { CLIError } from '@oclif/core/lib/errors' import * as archiver from 'archiver' import { validateAppPath } from './appPath' +import * as FormData from 'form-data' const getDateTimeFileName = () => (new Date()).toISOString().replace(/[^0-9]/g, '') -export const createAppPkg = async ( +export const createAppPkg = ( relativeAppPath: string, pkgDir = 'tmp' -) => { - const appPath = path.resolve(relativeAppPath) - validateAppPath(appPath) +): Promise => { + return new Promise((resolve, reject) => { + const appPath = path.resolve(relativeAppPath) + validateAppPath(appPath) - const pkgName = `app-${getDateTimeFileName()}` - const pkgPath = `${appPath}/${pkgDir}/${pkgName}.zip` + const pkgName = `app-${getDateTimeFileName()}` + const pkgPath = `${appPath}/${pkgDir}/${pkgName}.zip` - await fs.ensureDir(`${appPath}/${pkgDir}`) - const output = fs.createWriteStream(pkgPath) - const archive = archiver('zip') + fs.ensureDirSync(`${appPath}/${pkgDir}`) + const output = fs.createWriteStream(pkgPath) - archive.pipe(output) + output.on('close', () => { + resolve(pkgPath) + }) - let archiveIgnore = ['tmp/**'] + output.on('error', (err) => { + reject(err) + }) - if (fs.pathExistsSync(`${appPath}/.zcliignore`)) { - archiveIgnore = archiveIgnore.concat(fs.readFileSync(`${appPath}/.zcliignore`).toString().replace(/\r\n/g, '\n').split('\n').filter((item) => { - return (item.trim().startsWith('#') ? null : item.trim()) - })) - } + const archive = archiver('zip') - archive.glob('**', { - cwd: appPath, - ignore: archiveIgnore - }) + let archiveIgnore = ['tmp/**'] - await archive.finalize() + if (fs.pathExistsSync(`${appPath}/.zcliignore`)) { + archiveIgnore = archiveIgnore.concat(fs.readFileSync(`${appPath}/.zcliignore`).toString().replace(/\r\n/g, '\n').split('\n').filter((item) => { + return (item.trim().startsWith('#') ? null : item.trim()) + })) + } - if (!fs.pathExistsSync(pkgPath)) { - throw new CLIError(`Failed to create package at ${pkgPath}`) - } + archive.glob('**', { + cwd: appPath, + ignore: archiveIgnore + }) - return pkgPath + archive.pipe(output) + + archive.finalize() + + return pkgPath + }) } export const validatePkg = async (pkgPath: string) => { @@ -51,16 +58,21 @@ export const validatePkg = async (pkgPath: string) => { throw new CLIError(`Package not found at ${pkgPath}`) } + const file = await fs.readFile(pkgPath) + const form = new FormData() - form.append('file', fs.createReadStream(pkgPath)) + form.append('file', file, { + filename: path.basename(pkgPath) + }) + const res = await request.requestAPI('api/v2/apps/validate', { method: 'POST', - data: form + data: form.getBuffer(), + headers: form.getHeaders() }) if (res.status !== 200) { - const { description } = await res.data - throw new CLIError(description) + throw new CLIError(res.data?.description) } return true