Skip to content

Commit

Permalink
Merge pull request #159 from line-o/feat/install-rest
Browse files Browse the repository at this point in the history
  • Loading branch information
windauer authored Oct 18, 2023
2 parents 8c54d36 + ec8477c commit 24cb0cc
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 18 deletions.
56 changes: 47 additions & 9 deletions commands/package/install.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { connect } from '@existdb/node-exist'
import { connect, getRestClient } from '@existdb/node-exist'

import { readFileSync } from 'node:fs'
import { basename } from 'node:path'

const AdminGroup = 'dba'

async function putPackage (db, restClient, content, fileName) {
const dbPath = db.app.packageCollection + '/' + fileName
const res = await restClient.put(content, dbPath)
return { success: res.statusCode === 201, error: res.body }
}

async function getUserInfo (db) {
const { user } = db.client.options.basic_auth
return await db.users.getUserInfo(user)
Expand All @@ -26,13 +34,13 @@ async function removeTemporaryCollection (db) {
return await db.collections.remove(db.app.packageCollection)
}

async function install (db, localFilePath) {
async function install (db, upload, localFilePath) {
const xarName = basename(localFilePath)
const contents = readFileSync(localFilePath)

console.log(`Install ${xarName} on ${serverName(db)}`)

const uploadResult = await db.app.upload(contents, xarName)
const uploadResult = await upload(contents, xarName)
if (!uploadResult.success) {
throw new Error(uploadResult.error)
}
Expand All @@ -51,34 +59,64 @@ async function install (db, localFilePath) {
return 0
}

export const command = ['install [options] <packages..>', 'i']
export const command = ['install <packages..>', 'i']
export const describe = 'Install XAR packages'
const options = {
rest: {
describe: 'force upload over REST API',
type: 'boolean'
},
xmlrpc: {
alias: 'rpc',
describe: 'force upload over XML-RPC API',
type: 'boolean'
}
}

export const builder = yargs => {
return yargs.options(options)
.conflicts('xmlrpc', 'rest')
}

export async function handler (argv) {
if (argv.help) {
return 0
}

// main
const { packages } = argv
const { packages, connectionOptions, rest, xmlrpc } = argv
packages.forEach(packagePath => {
if (!packagePath.match(/\.xar$/i)) {
throw Error('Packages must have the file extension .xar! Got: "' + packagePath + '"')
}
})

// check permissions (and therefore implicitly the connection)
const db = connect(argv.connectionOptions)
const db = connect(connectionOptions)
const accountInfo = await getUserInfo(db)
const isAdmin = accountInfo.groups.includes('dba')
const isAdmin = accountInfo.groups.includes(AdminGroup)
if (!isAdmin) {
throw Error(`Package installation failed. User "${accountInfo.name}" is not a member of the "dba" group.`)
throw Error(`Package installation failed. User "${accountInfo.name}" is not a member of the "${AdminGroup}" group.`)
}

let upload
if (xmlrpc) {
upload = db.app.upload
} else {
const restClient = await getRestClient(connectionOptions)
const boundUpload = putPackage.bind(null, db, restClient)
if (rest) {
upload = boundUpload
} else {
const test = await restClient.get('db')
upload = test.statusCode === 200 ? boundUpload : db.app.upload
}
}

try {
for (const i in packages) {
const packagePath = packages[i]
await install(db, packagePath)
await install(db, upload, packagePath)
}
} finally {
await removeTemporaryCollection(db)
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"maintainers": [],
"license": "MIT",
"dependencies": {
"@existdb/node-exist": "^5.4.0",
"@existdb/node-exist": "^5.4.1",
"bottleneck": "^2.19.5",
"chalk": "^5.2.0",
"dotenv": "^16.0.3",
Expand Down
25 changes: 24 additions & 1 deletion spec/tests/package/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ test('shows help', async function (t) {
if (stderr) { return t.fail(stderr) }
t.ok(stdout, 'got output')
const firstLine = stdout.split('\n')[0]
t.equal(firstLine, 'xst package install [options] <packages..>', firstLine)
t.equal(firstLine, 'xst package install <packages..>', firstLine)
})

test('fails when dependency is not met', async function (t) {
Expand Down Expand Up @@ -155,6 +155,29 @@ test('multiple valid packages', async function (t) {
t.teardown(cleanup)
})

test('using rest for upload', async function (t) {
t.test('installs lib first', async function (st) {
const { stderr, stdout } = await run('xst', ['package', 'install', '--rest', 'spec/fixtures/test-lib.xar'], asAdmin)
if (stderr) {
// console.error(stderr)
st.fail(stderr)
return st.end()
}
st.ok(stdout)
})
t.test('installs app', async function (st) {
const { stderr, stdout } = await run('xst', ['package', 'install', '--rest', 'spec/fixtures/test-app.xar'], asAdmin)
if (stderr) {
// console.error(stderr)
st.fail(stderr)
return st.end()
}
st.ok(stdout)
})

t.teardown(cleanup)
})

test('multiple packages', async function (t) {
t.test('first is broken', async function (st) {
const { stderr, stdout } = await run('xst', ['package', 'install', 'spec/fixtures/broken-test-app.xar', 'spec/fixtures/test-app.xar'], asAdmin)
Expand Down
1 change: 1 addition & 0 deletions utility/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function compileConnectionOptions (server, user, pass) {
connectionOptions.secure = protocol === 'https:'
connectionOptions.host = hostname
connectionOptions.port = port
connectionOptions.protocol = protocol
}

return { connectionOptions }
Expand Down

0 comments on commit 24cb0cc

Please sign in to comment.