Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/mdctl-cli/lib/package/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const publishPkg = require('./publish'),
installPkg = require('./install')

module.exports = {
publishPkg,
installPkg
}
37 changes: 37 additions & 0 deletions packages/mdctl-cli/lib/package/install.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const Package = require('../../../mdctl-packages'),
{ Cortex } = require('../package/source'),
installPkg = async(name, params) => {
let tmpName = name

if (name && name.startsWith('--')) {
// No package name specified after `mdctl package install`, but an option
// So assign name to an empty string to install a local package at the current
// working directory where the mdctl command is executed.
tmpName = ''
}

// If pkgName is empty, then this is a local package.
// Otherwise, it is a remote package.
const {
registryUrl, registryProjectId, registryToken, client
} = params,
options = { registryUrl, registryProjectId, registryToken },
[pkgName, pkgVersion] = tmpName.split('@'),
isLocalPkg = pkgName === '',
pkg = new Package(pkgName, isLocalPkg ? '.' : pkgVersion || 'latest', null, options)

await pkg.evaluate()

// eslint-disable-next-line one-var
const srcClient = new Cortex(pkg.name, pkg.version, {
client
})

try {
await srcClient.installPackage(pkg)
} catch (err) {
throw err
}
}

module.exports = installPkg
32 changes: 32 additions & 0 deletions packages/mdctl-cli/lib/package/publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const Package = require('../../../mdctl-packages'),
{ Registry, Cortex } = require('../package/source'),
publishPkg = async(name, params) => {
const {
source, registryUrl, registryProjectId, registryToken, client
} = params,
pkg = new Package(name, '.')

await pkg.evaluate()

let srcClient

if (source === 'registry') {
srcClient = new Registry(pkg.name, pkg.version, {
registryUrl,
registryProjectId,
registryToken
})
} else {
srcClient = new Cortex(pkg.name, pkg.version, {
client
})
}

try {
await srcClient.publishPackage(await pkg.getPackageStream())
} catch (err) {
throw err
}
}

module.exports = publishPkg
96 changes: 96 additions & 0 deletions packages/mdctl-cli/lib/package/source/cortex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const { URL } = require('url'),
FormData = require('form-data')


class Cortex {

constructor(name, version, options) {
this.name = name
this.version = version
this.client = options.client
this.publishPath = process.env.PACKAGE_PUBLISH_PATH || '/developer/packages/publish'
this.installPath = process.env.PACKAGE_INSTALL_PATH || '/developer/packages/install'
}

async installPackage(pkg) {
const url = new URL(this.installPath, this.client.environment.url),
dependencies = pkg.dependenciesPackages || [],
install = body => this.client.call(url.pathname, { method: 'POST', body })

dependencies.forEach(async(dependency) => {
try {
await install(await dependency.getPackageStream())
} catch (err) {
throw new Error('Failed to install one of the package dependencies. Please try it again!!!')
}
})

await install(await pkg.getPackageStream())
}

async publishPackage(zipStream) {
// Publishing a package to cortex has 2 phases
// 1. Create a facet
// 2. Upload the package
const url = new URL(this.publishPath, this.client.environment.url),
filename = `${this.name}_${this.version}.zip`,
facet = await this.client.call(url.pathname, {
method: 'PUT',
body: {
content: filename
}
}),
upload = facet.uploads[0],
{
uploadUrl, uploadKey, fields
} = upload,
form = new FormData(),
zipToBuffer = () => new Promise((resolve, reject) => {
const data = []

zipStream.on('data', (chunk) => {
data.push(chunk)
})

zipStream.on('end', () => {
resolve(Buffer.concat(data))
})

zipStream.on('error', (error) => {
reject(error)
})
}),
data = await zipToBuffer()

fields.forEach((field) => {
const { key, value } = field
form.append(key, value)
})

form.append(
uploadKey,
data,
{
filename
}
)

await new Promise((resolve, reject) => {
form.submit(uploadUrl, (err, response) => {
if (err) {
console.error(err)
reject(err)
} else if ([200, 201].includes(response.statusCode)) {
console.log(`Successfully published package ${this.name}@${this.version} to cortex`)
resolve()
} else {
console.error(`Publishing package failed with status code ${response.statusCode} and status message ${response.statusMessage}`)
reject()
}
})
})
}

}

module.exports = Cortex
7 changes: 7 additions & 0 deletions packages/mdctl-cli/lib/package/source/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const Registry = require('./registry'),
Cortex = require('./cortex')

module.exports = {
Registry,
Cortex
}
19 changes: 19 additions & 0 deletions packages/mdctl-cli/lib/package/source/registry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { RegistrySource } = require('../../../../mdctl-packages/lib')

class Registry {

constructor(name, version, options) {

this.source = new RegistrySource(name, version, options)

}

async publishPackage(zipStream) {

await this.source.publishPackage(zipStream)

}

}

module.exports = Registry
4 changes: 3 additions & 1 deletion packages/mdctl-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"test:watch": "npm run test:only -- --watch",
"test:examples": "node examples/",
"cover": "istanbul cover ../../node_modules/mocha/bin/_mocha -- --recursive --timeout 10000",
"lint": "eslint . --ext .js"
"lint": "eslint . --ext .js",
"test:package": "mocha --timeout 1200000 ./test/lib/package"
},
"dependencies": {
"@medable/mdctl-api": "^1.0.62",
Expand All @@ -43,6 +44,7 @@
"async": "^2.6.3",
"cli-table": "^0.3.1",
"clone": "^2.1.2",
"form-data": "^4.0.0",
"globby": "^9.1.0",
"inflection": "^1.12.0",
"inquirer": "^6.5.2",
Expand Down
60 changes: 32 additions & 28 deletions packages/mdctl-cli/tasks/package.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
/* eslint-disable class-methods-use-this */

const fs = require('fs'),
_ = require('lodash'),
pump = require('pump'),
ndjson = require('ndjson'),
{ isSet, parseString, rString } = require('@medable/mdctl-core-utils/values'),
Packages = require('packages/mdctl-packages'),
ImportStream = require('@medable/mdctl-core/streams/import_stream'),
ImportFileTreeAdapter = require('@medable/mdctl-import-adapter'),
{
createConfig, loadDefaults
} = require('../lib/config'),
Task = require('../lib/task')
const _ = require('lodash'),
{ isSet } = require('@medable/mdctl-core-utils/values'),
Task = require('../lib/task'),
{ publishPkg, installPkg } = require('../lib/package')


class Package extends Task {
Expand Down Expand Up @@ -51,33 +43,45 @@ class Package extends Task {
throw new Error('Invalid command')
}

const config = createConfig()
config.update(await loadDefaults())
return this[handler](cli)

}

async 'package@get'(cli) {
throw Error('Not Implemented')
}

async 'package@list'(cli) {
const result = await this.registry.getPackages()
console.log(result)
// const result = await this.registry.getPackages()
// console.log(result)
throw Error('Not Implemented')
}

async 'package@publish'(cli) {
// this will build package artifact
const params = await cli.getArguments(this.optionKeys),
inputDir = params.dir || process.cwd(),
packageJson = parseString(fs.readFileSync(`${inputDir}/package.json`)),
pkg = this.args('2') || `${packageJson.name}@${packageJson.version}`,
fileAdapter = new ImportFileTreeAdapter(`${inputDir}/${packageJson.mdEnvPath || 'configuration'}`, 'json'),
importStream = new ImportStream(fileAdapter),
ndjsonStream = ndjson.stringify(),
streamList = [importStream, ndjsonStream],
[name, version] = pkg.split('@')
await this.registry.publishPackage(name, version, pump(streamList), packageJson.mdDependencies)
console.log(`${name}@${version} has been published!`)
// Determine where to publish the package i.e either cortex or registry (default)
const name = this.args('name') || '',
source = this.args('source') || 'registry',
registryUrl = this.args('registryUrl') || process.env.REGISTRY_URL,
registryProjectId = this.args('registryProjectId') || process.env.REGISTRY_PROJECT_ID,
registryToken = this.args('registryToken') || process.env.REGISTRY_TOKEN,
client = source === 'cortex' ? await cli.getApiClient({ credentials: await cli.getAuthOptions() }) : null

await publishPkg(name, {
source, registryUrl, registryProjectId, registryToken, client
})
}

async 'package@install'(cli) {
// this will install a package in target organization
const name = this.args('2') || '',
registryUrl = this.args('registryUrl') || process.env.REGISTRY_URL,
registryProjectId = this.args('registryProjectId') || process.env.REGISTRY_PROJECT_ID,
registryToken = this.args('registryToken') || process.env.REGISTRY_TOKEN,
client = await cli.getApiClient({ credentials: await cli.getAuthOptions() })

await installPkg(name, {
registryUrl, registryProjectId, registryToken, client
})
}

// ----------------------------------------------------------------------------------------------
Expand Down
Loading