Comparing version 0.1.1 to 0.2.0
{ | ||
"name": "foxx-cli", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "CLI for ArangoDB Foxx.", | ||
@@ -40,2 +40,3 @@ "preferGlobal": true, | ||
"inquirer": "^4.0.0", | ||
"lodash": "^4.17.4", | ||
"minimatch": "^3.0.4", | ||
@@ -42,0 +43,0 @@ "semver": "^5.4.1", |
@@ -51,3 +51,2 @@ "use strict"; | ||
"Continue even if no manifest file is present in the source directory", | ||
alias: "s", | ||
type: "boolean", | ||
@@ -54,0 +53,0 @@ default: false |
"use strict"; | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { error, fatal, json } = require("../util/log"); | ||
@@ -6,3 +7,2 @@ | ||
const client = require("../util/client"); | ||
const { common } = require("../util/cli"); | ||
const { inline: il } = require("../util/text"); | ||
@@ -13,3 +13,3 @@ const parseOptions = require("../util/parseOptions"); | ||
const command = (exports.command = "config <path> [options..]"); | ||
const command = (exports.command = "config <mount> [options..]"); | ||
const description = (exports.description = | ||
@@ -22,3 +22,3 @@ "Manage the configuration of a mounted service"); | ||
const args = [ | ||
["path", "Database-relative path of the service"], | ||
["mount", "Mount path of the service"], | ||
[ | ||
@@ -35,2 +35,3 @@ "options", | ||
.options({ | ||
...serverArgs, | ||
force: { | ||
@@ -94,10 +95,10 @@ describe: il` | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
let result; | ||
if (!options) { | ||
result = await db.getServiceConfiguration(server.mount, argv.minimal); | ||
result = await db.getServiceConfiguration(argv.mount, argv.minimal); | ||
} else if (argv.force) { | ||
result = await db.replaceServiceConfiguration( | ||
server.mount, | ||
argv.mount, | ||
options, | ||
@@ -108,3 +109,3 @@ argv.minimal | ||
result = await db.updateServiceConfiguration( | ||
server.mount, | ||
argv.mount, | ||
options, | ||
@@ -111,0 +112,0 @@ argv.minimal |
"use strict"; | ||
const { json, fatal } = require("../util/log"); | ||
const { fatal, json } = require("../util/log"); | ||
const { bold } = require("chalk"); | ||
const client = require("../util/client"); | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { inline: il } = require("../util/text"); | ||
@@ -12,3 +12,3 @@ const parseOptions = require("../util/parseOptions"); | ||
const command = (exports.command = "deps <path> [options..]"); | ||
const command = (exports.command = "deps <mount> [options..]"); | ||
const description = (exports.description = | ||
@@ -21,3 +21,3 @@ "Manage the dependencies of a mounted service"); | ||
const args = [ | ||
["path", "Database-relative path of the service"], | ||
["mount", "Mount path of the service"], | ||
[ | ||
@@ -34,2 +34,3 @@ "options", | ||
.options({ | ||
...serverArgs, | ||
force: { | ||
@@ -93,10 +94,10 @@ describe: il` | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
let result; | ||
if (!options) { | ||
result = await db.getServiceDependencies(server.mount, argv.minimal); | ||
result = await db.getServiceDependencies(argv.mount, argv.minimal); | ||
} else if (argv.force) { | ||
result = await db.replaceServiceDependencies( | ||
server.mount, | ||
argv.mount, | ||
options, | ||
@@ -107,3 +108,3 @@ argv.minimal | ||
result = await db.updateServiceDependencies( | ||
server.mount, | ||
argv.mount, | ||
options, | ||
@@ -110,0 +111,0 @@ argv.minimal |
"use strict"; | ||
const { bold, white } = require("chalk"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { createWriteStream, existsSync } = require("fs"); | ||
@@ -7,3 +8,2 @@ const { fatal, info } = require("../util/log"); | ||
const { common } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
@@ -16,3 +16,3 @@ const { extractBuffer } = require("../util/zip"); | ||
const command = (exports.command = "download <path>"); | ||
const command = (exports.command = "download <mount>"); | ||
const description = (exports.description = "Download a mounted service"); | ||
@@ -23,3 +23,3 @@ const aliases = (exports.aliases = ["dl"]); | ||
const args = [["path", "Database-relative path of the service"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
@@ -29,2 +29,3 @@ exports.builder = yargs => | ||
.options({ | ||
...serverArgs, | ||
stdout: { | ||
@@ -126,5 +127,5 @@ describe: `Write to stdout no matter what stdout is`, | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
const bundle = await db.downloadService(server.mount); | ||
const bundle = await db.downloadService(argv.mount); | ||
if (!argv.extract) { | ||
@@ -131,0 +132,0 @@ out.write(bundle); |
"use strict"; | ||
const { common, parseServiceOptions, serverArgs } = require("../util/cli"); | ||
const { fatal, json } = require("../util/log"); | ||
const { bold } = require("chalk"); | ||
const { common, validateServiceArgs } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
const resolveServer = require("../resolveServer"); | ||
const { json, fatal } = require("../util/log"); | ||
const resolveToStream = require("../resolveToStream"); | ||
const command = (exports.command = "install <path> [source]"); | ||
const command = (exports.command = "install <mount> [source]"); | ||
const description = (exports.description = | ||
@@ -17,3 +18,3 @@ "Install a service at a given mount path"); | ||
const args = [ | ||
["path", "Database-relative path the service will be mounted on"], | ||
["mount", "Mount path of the service"], | ||
[ | ||
@@ -31,2 +32,3 @@ "source", | ||
.options({ | ||
...serverArgs, | ||
setup: { | ||
@@ -42,3 +44,3 @@ describe: `Run the setup script after installing the service. Use ${bold( | ||
"Install the service in development mode. You can edit the service's files on the server and changes will be reflected automatically", | ||
alias: "D", | ||
alias: "dev", | ||
type: "boolean", | ||
@@ -80,3 +82,11 @@ default: false | ||
.example( | ||
"$0 install dev:/hello", | ||
"$0 install --server http://localhost:8530 hello", | ||
"Use the server on port 8530 instead of the default" | ||
) | ||
.example( | ||
"$0 install --database mydb hello", | ||
'Use the database "mydb" instead of the default' | ||
) | ||
.example( | ||
"$0 install --server dev hello", | ||
'Use the "dev" server instead of the default. See the "server" command for details' | ||
@@ -119,5 +129,5 @@ ) | ||
exports.handler = async function handler(argv) { | ||
const opts = validateServiceArgs(argv); | ||
const opts = parseServiceOptions(argv); | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
return await install(argv, server, opts); | ||
@@ -132,3 +142,3 @@ } catch (e) { | ||
const db = client(server); | ||
const result = await db.installService(server.mount, source, { | ||
const result = await db.installService(argv.mount, source, { | ||
...opts, | ||
@@ -135,0 +145,0 @@ setup: argv.setup |
"use strict"; | ||
const { bold, gray } = require("chalk"); | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { detail, fatal, info, json } = require("../util/log"); | ||
const client = require("../util/client"); | ||
const { group } = require("../util/text"); | ||
const resolveServer = require("../resolveServer"); | ||
const { info, json, detail, fatal } = require("../util/log"); | ||
const { group } = require("../util/text"); | ||
const command = (exports.command = "list [path]"); | ||
const command = (exports.command = "list"); | ||
exports.description = "List mounted services"; | ||
@@ -15,6 +16,5 @@ const aliases = (exports.aliases = ["ls"]); | ||
const args = [["path", "Database-relative path of the service"]]; | ||
exports.builder = yargs => | ||
common(yargs, { command, aliases, describe, args }).options({ | ||
common(yargs, { command, aliases, describe }).options({ | ||
...serverArgs, | ||
all: { | ||
@@ -35,3 +35,3 @@ describe: "Include system services", | ||
try { | ||
const server = await resolveServer(argv.path, false); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
@@ -38,0 +38,0 @@ let services = await db.listServices(); |
"use strict"; | ||
const { bold } = require("chalk"); | ||
const { common, validateServiceArgs } = require("../util/cli"); | ||
const { common, serverArgs, parseServiceOptions } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
@@ -9,3 +9,3 @@ const resolveServer = require("../resolveServer"); | ||
const command = (exports.command = "replace <path> [source]"); | ||
const command = (exports.command = "replace <mount> [source]"); | ||
const description = (exports.description = "Replace a mounted service"); | ||
@@ -16,3 +16,3 @@ | ||
const args = [ | ||
["path", "Database-relative path the service is mounted on"], | ||
["mount", "Mount path of the service"], | ||
[ | ||
@@ -29,2 +29,3 @@ "source", | ||
common(yargs, { command, describe, args }).options({ | ||
...serverArgs, | ||
teardown: { | ||
@@ -47,3 +48,3 @@ describe: `Run the teardown script before replacing the service. Use ${bold( | ||
"Install the update in development mode. You can edit the service's files on the server and changes will be reflected automatically", | ||
alias: "D", | ||
alias: "dev", | ||
type: "boolean", | ||
@@ -81,6 +82,19 @@ default: false | ||
exports.handler = async function handler(argv) { | ||
const opts = validateServiceArgs(argv); | ||
const opts = parseServiceOptions(argv); | ||
try { | ||
const server = await resolveServer(argv.path); | ||
return await replace(argv, server, opts); | ||
const server = await resolveServer(argv); | ||
const source = argv.remote | ||
? argv.source | ||
: await resolveToStream(argv.source); | ||
const db = client(server); | ||
const result = await db.replaceService(argv.mount, source, { | ||
...opts, | ||
setup: argv.setup, | ||
teardown: argv.teardown | ||
}); | ||
if (argv.raw) { | ||
json(result); | ||
} else { | ||
console.log(result); // TODO pretty-print | ||
} | ||
} catch (e) { | ||
@@ -90,16 +104,1 @@ fatal(e); | ||
}; | ||
async function replace(argv, server, opts) { | ||
const source = argv.remote ? argv.source : await resolveToStream(argv.source); | ||
const db = client(server); | ||
const result = await db.replaceService(server.mount, source, { | ||
...opts, | ||
setup: argv.setup, | ||
teardown: argv.teardown | ||
}); | ||
if (argv.raw) { | ||
json(result); | ||
} else { | ||
console.log(result); // TODO pretty-print | ||
} | ||
} |
@@ -5,3 +5,3 @@ "use strict"; | ||
const client = require("../util/client"); | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const parseOptions = require("../util/parseOptions"); | ||
@@ -11,3 +11,3 @@ const resolveServer = require("../resolveServer"); | ||
const command = (exports.command = "run <path> <name> [options..]"); | ||
const command = (exports.command = "run <mount> <name> [options..]"); | ||
const description = (exports.description = | ||
@@ -20,3 +20,3 @@ "Run a script for a mounted service"); | ||
const args = [ | ||
["path", "Database-relative path of the service"], | ||
["mount", "Mount path of the service"], | ||
["name", "Name of the script to execute"], | ||
@@ -28,2 +28,3 @@ ["options", "Arguments that will be passed to the script"] | ||
common(yargs, { command, aliases, describe, args }).options({ | ||
...serverArgs, | ||
raw: { | ||
@@ -55,5 +56,5 @@ describe: "Output raw JSON response", | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
const result = await db.runServiceScript(server.mount, argv.name, options); | ||
const result = await db.runServiceScript(argv.mount, argv.name, options); | ||
if (argv.raw) { | ||
@@ -60,0 +61,0 @@ json(result); |
"use strict"; | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { detail, fatal, info, json } = require("../util/log"); | ||
const client = require("../util/client"); | ||
const { group } = require("../util/text"); | ||
const resolveServer = require("../resolveServer"); | ||
const { info, detail, json, fatal } = require("../util/log"); | ||
const { group } = require("../util/text"); | ||
const command = (exports.command = "scripts <path>"); | ||
const command = (exports.command = "scripts <mount>"); | ||
const description = (exports.description = | ||
@@ -14,6 +15,7 @@ "List available scripts for a mounted service"); | ||
const args = [["path", "Database-relative path of the service"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
exports.builder = yargs => | ||
common(yargs, { command, describe, args }).options({ | ||
...serverArgs, | ||
raw: { | ||
@@ -28,5 +30,5 @@ describe: "Output raw JSON response", | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
const scripts = await db.listServiceScripts(server.mount); | ||
const scripts = await db.listServiceScripts(argv.mount); | ||
const names = Object.keys(scripts); | ||
@@ -33,0 +35,0 @@ if (argv.raw) { |
"use strict"; | ||
const { common } = require("../util/cli"); | ||
const { group, inline: il } = require("../util/text"); | ||
@@ -9,26 +8,4 @@ const command = (exports.command = "server <command>"); | ||
const describe = | ||
il` | ||
The server commands allow defining server names that can be used with | ||
other commands or as part of service mount paths to avoid passing the | ||
same credentials to every command. | ||
const describe = `The server commands allow defining server aliases that can be used instead of URLs to avoid passing the same credentials to every command.`; | ||
It is also possible to invoke commands with the following environment | ||
variables to override the default server without explicitly defining | ||
credentials: | ||
` + | ||
"\n\n" + | ||
group( | ||
[ | ||
"FOXX_ARANGODB_SERVER_URL", | ||
"Fully qualified URL of the ArangoDB database" | ||
], | ||
["FOXX_ARANGODB_SERVER_USERNAME", "Username to authenticate with"], | ||
["FOXX_ARANGODB_SERVER_PASSWORD", "Password to authenticate with"], | ||
[ | ||
"FOXX_ARANGODB_SERVER_TOKEN", | ||
"Bearer token to authenticate with (overrides username/password)" | ||
] | ||
); | ||
exports.builder = yargs => | ||
@@ -35,0 +12,0 @@ common(yargs, { command, aliases, describe }) |
"use strict"; | ||
const { bold, white } = require("chalk"); | ||
const { prompt } = require("inquirer"); | ||
const { validRange } = require("semver"); | ||
const { unsplat } = require("../../util/array"); | ||
const { common } = require("../../util/cli"); | ||
const { fatal } = require("../../util/log"); | ||
const { inline: il } = require("../../util/text"); | ||
const { common, serverArgs } = require("../../util/cli"); | ||
const { load: loadIni, save: saveIni } = require("../../ini"); | ||
const parseServerUrl = require("../../util/parseServerUrl"); | ||
const command = (exports.command = "set <name> <url>"); | ||
const { fatal } = require("../../util/log"); | ||
const { omit } = require("lodash"); | ||
const resolveServer = require("../../resolveServer"); | ||
const { white } = require("chalk"); | ||
const command = (exports.command = "set <name> <server>"); | ||
const description = (exports.description = "Define server"); | ||
@@ -20,3 +18,3 @@ const aliases = (exports.aliases = ["add"]); | ||
["name", "Server name to define"], | ||
["url", "Fully qualified URL of the ArangoDB database"] | ||
["server", "URL of the ArangoDB server"] | ||
]; | ||
@@ -27,77 +25,55 @@ | ||
.options({ | ||
"arango-version": { | ||
describe: "ArangoDB server version", | ||
alias: "V", | ||
type: "string" | ||
}, | ||
username: { | ||
describe: "Username to authenticate with", | ||
alias: "u", | ||
type: "string", | ||
default: "root" | ||
}, | ||
password: { | ||
describe: "Use password to authenticate", | ||
alias: "P", | ||
type: "boolean", | ||
default: false | ||
}, | ||
token: { | ||
describe: "Use bearer token to authenticate", | ||
alias: "T", | ||
type: "boolean", | ||
default: false | ||
} | ||
...omit(serverArgs, ["server"]) | ||
}) | ||
.example( | ||
"$0 server set dev http://localhost:8529/_db/_system", | ||
'Set the "dev" server to the ArangoDB instance at "http://localhost:8529/_db/_system" with user "root" and empty password' | ||
"$0 server set dev http://localhost:8529", | ||
'Set the "dev" server to the ArangoDB instance at "http://localhost:8529" with the default username and password' | ||
) | ||
.example( | ||
"$0 server set staging https://proxy.local", | ||
'Set the "staging" server to the ArangoDB instance at "https://proxy.local" with user "root" and empty password' | ||
"$0 server set dev http://localhost:8529 -D mydb", | ||
'Use the database "mydb" instead of "_system"' | ||
) | ||
.example( | ||
"$0 server set staging https://proxy.local -u devel", | ||
'Set the "staging" server to the ArangoDB instance at "https://proxy.local" with user "devel" and empty password' | ||
"$0 server set dev http://localhost:8529 -u devel", | ||
'Authenticate with user "devel" and an empty password' | ||
) | ||
.example( | ||
"$0 server set staging https://devel:@proxy.local", | ||
'Set the "staging" server to the ArangoDB instance at "https://proxy.local" with user "devel" and empty password' | ||
"$0 server set dev http://localhost:8529 -u devel -P", | ||
'Authenticate with user "devel" and a password read from stdin' | ||
) | ||
.example( | ||
"$0 server set staging https://proxy.local -u devel -P", | ||
'Set the "staging" server to the ArangoDB instance at "https://proxy.local" with user "devel" and a password read from stdin' | ||
"$0 server set dev http://localhost:8529 -T", | ||
"Authenticate with a bearer token read from stdin" | ||
) | ||
.example( | ||
"$0 server set staging https://proxy.local -T", | ||
'Set the "staging" server to the ArangoDB instance at "https://proxy.local" with a bearer token read from stdin' | ||
"$0 server set dev http://devel:@mydbserver.example:8529", | ||
"Username and password can be passed via the URL (in this case the password is empty)" | ||
) | ||
.example( | ||
"$0 server set staging https://proxy.local#token=1234", | ||
'Set the "staging" server to the ArangoDB instance at "https://proxy.local" with bearer token "1234"' | ||
"$0 server set dev tls://localhost:8529", | ||
'The protocol "tls" can be used as an alias for "http"' | ||
) | ||
.example( | ||
"$0 server set dev ssl://localhost:8529", | ||
'The protocol "ssl" can be used as an alias for "https"' | ||
) | ||
.example( | ||
"$0 server set dev //localhost:8529", | ||
'If omitted the protocol defaults to "http"' | ||
) | ||
.example( | ||
"$0 server set dev http://localhost:8529 -V 3.2.0", | ||
"Explicitly setting the expected ArangoDB version can be useful when using servers running different versions" | ||
); | ||
exports.handler = async function handler(argv) { | ||
if (argv.password && argv.token) { | ||
fatal(il` | ||
Can not use both ${bold("password")} and ${bold( | ||
"token" | ||
)} authentication for the same server. | ||
`); | ||
} | ||
if (argv.arangoVersion && !validRange(argv.arangoVersion)) { | ||
fatal(il` | ||
Not a valid semver version: "${white(argv.arangoVersion)}". | ||
`); | ||
} | ||
if (argv.name.startsWith("/")) { | ||
fatal(il` | ||
The server name must not start with a slash: "${white(argv.name)}". | ||
`); | ||
fatal( | ||
`The server name must not start with a slash: "${white(argv.name)}".` | ||
); | ||
} | ||
try { | ||
const server = await buildServer(argv); | ||
const server = await resolveServer(argv); | ||
const ini = await loadIni(); | ||
ini.server[argv.name] = server; | ||
ini.server[argv.name] = omit(server, ["name"]); | ||
return await saveIni(ini); | ||
@@ -108,34 +84,1 @@ } catch (e) { | ||
}; | ||
async function buildServer(argv) { | ||
const server = parseServerUrl(argv.url); | ||
if (argv.arangoVersion) { | ||
server.version = unsplat(argv.arangoVersion); | ||
} | ||
if (argv.username) { | ||
server.username = unsplat(argv.username); | ||
server.password = ""; | ||
} | ||
if (argv.password) { | ||
const { password } = await prompt([ | ||
{ | ||
message: "Password", | ||
name: "password", | ||
type: "password" | ||
} | ||
]); | ||
server.password = password; | ||
} | ||
if (argv.token) { | ||
const { token } = await prompt([ | ||
{ | ||
message: "Token", | ||
name: "token", | ||
type: "password", | ||
validate: Boolean | ||
} | ||
]); | ||
server.token = token; | ||
} | ||
return server; | ||
} |
"use strict"; | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
const { fatal } = require("../util/log"); | ||
const resolveServer = require("../resolveServer"); | ||
const { fatal } = require("../util/log"); | ||
const command = (exports.command = "set-dev <path>"); | ||
const command = (exports.command = "set-dev <mount>"); | ||
const description = (exports.description = | ||
@@ -14,11 +15,12 @@ "Activate development mode for a mounted service"); | ||
const args = [["path", "Database-relative path of the service"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
exports.builder = yargs => common(yargs, { command, aliases, describe, args }); | ||
exports.builder = yargs => | ||
common(yargs, { command, aliases, describe, args }).options(serverArgs); | ||
exports.handler = async function handler(argv) { | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
return await db.enableServiceDevelopmentMode(server.mount); | ||
return await db.enableServiceDevelopmentMode(argv.mount); | ||
} catch (e) { | ||
@@ -25,0 +27,0 @@ fatal(e); |
"use strict"; | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
const { fatal } = require("../util/log"); | ||
const resolveServer = require("../resolveServer"); | ||
const { fatal } = require("../util/log"); | ||
const command = (exports.command = "set-prod <path>"); | ||
const command = (exports.command = "set-prod <mount>"); | ||
const description = (exports.description = | ||
@@ -14,11 +15,12 @@ "Disable development for a mounted service"); | ||
const args = [["path", "Database-relative path of the service"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
exports.builder = yargs => common(yargs, { command, aliases, describe, args }); | ||
exports.builder = yargs => | ||
common(yargs, { command, aliases, describe, args }).options(serverArgs); | ||
exports.handler = async function handler(argv) { | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
return await db.disableServiceDevelopmentMode(server.mount); | ||
return await db.disableServiceDevelopmentMode(argv.mount); | ||
} catch (e) { | ||
@@ -25,0 +27,0 @@ fatal(e); |
"use strict"; | ||
const { bold, white } = require("chalk"); | ||
const { common } = require("../util/cli"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { fatal, json } = require("../util/log"); | ||
const client = require("../util/client"); | ||
const { ERROR_SERVICE_NOT_FOUND } = require("../errors"); | ||
const resolveServer = require("../resolveServer"); | ||
const { json, fatal } = require("../util/log"); | ||
const { inline: il } = require("../util/text"); | ||
const { ERROR_SERVICE_NOT_FOUND } = require("../errors"); | ||
const command = (exports.command = "show <path>"); | ||
const command = (exports.command = "show <mount>"); | ||
exports.description = "Show mounted service information"; | ||
const aliases = (exports.aliases = ["info"]); | ||
const describe = il` | ||
Shows detailed information about the service installed at the | ||
given ${bold("path")}. | ||
`; | ||
const describe = `Shows detailed information about the service installed at the given ${bold( | ||
"mount" | ||
)}.`; | ||
const args = [["path", "Database-relative path of the service"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
exports.builder = yargs => | ||
common(yargs, { command, aliases, describe, args }).options({ | ||
...serverArgs, | ||
raw: { | ||
@@ -32,6 +32,6 @@ describe: "Output raw JSON response", | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
try { | ||
const result = await db.getService(server.mount); | ||
const result = await db.getService(argv.mount); | ||
if (argv.raw) { | ||
@@ -44,3 +44,3 @@ json(result); | ||
if (e.isArangoError && e.errorNum === ERROR_SERVICE_NOT_FOUND) { | ||
fatal(`No service found at "${white(server.mount)}".`); | ||
fatal(`No service found at "${white(argv.mount)}".`); | ||
} | ||
@@ -47,0 +47,0 @@ throw e; |
"use strict"; | ||
const { white, bold } = require("chalk"); | ||
const { common } = require("../util/cli"); | ||
const { bold, white } = require("chalk"); | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { error, fatal, info, json } = require("../util/log"); | ||
const { group, inline: il } = require("../util/text"); | ||
const client = require("../util/client"); | ||
const errors = require("../errors"); | ||
const reporters = require("../reporters"); | ||
const client = require("../util/client"); | ||
const resolveServer = require("../resolveServer"); | ||
const { info, json, error, fatal } = require("../util/log"); | ||
const { group, inline: il } = require("../util/text"); | ||
const command = (exports.command = "test <path>"); | ||
const command = (exports.command = "test <mount>"); | ||
exports.description = "Run the tests of a mounted service"; | ||
@@ -35,6 +36,7 @@ const aliases = (exports.aliases = ["tests", "run-tests"]); | ||
const args = [["path", "Database-relative path of the service"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
exports.builder = yargs => | ||
common(yargs, { command, aliases, describe, args }).options({ | ||
...serverArgs, | ||
reporter: { | ||
@@ -50,5 +52,5 @@ describe: "Reporter to use for result data", | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
return await runTests(db, server.mount, argv.reporter); | ||
return await runTests(db, argv.mount, argv.reporter); | ||
} catch (e) { | ||
@@ -55,0 +57,0 @@ fatal(e); |
"use strict"; | ||
const { common, serverArgs } = require("../util/cli"); | ||
const { detail, fatal } = require("../util/log"); | ||
const { bold } = require("chalk"); | ||
const { common } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
const { ERROR_SERVICE_NOT_FOUND } = require("../errors"); | ||
const resolveServer = require("../resolveServer"); | ||
const { detail, fatal } = require("../util/log"); | ||
const { ERROR_SERVICE_NOT_FOUND } = require("../errors"); | ||
const command = (exports.command = "uninstall <path>"); | ||
const command = (exports.command = "uninstall <mount>"); | ||
const description = (exports.description = "Uninstall a mounted service"); | ||
@@ -15,6 +16,7 @@ const aliases = (exports.aliases = ["remove", "purge"]); | ||
const args = [["path", "Database-relative path the service is mounted on"]]; | ||
const args = [["mount", "Mount path of the service"]]; | ||
exports.builder = yargs => | ||
common(yargs, { command, aliases, describe, args }).options({ | ||
...serverArgs, | ||
teardown: { | ||
@@ -31,10 +33,10 @@ describe: `Run the teardown script before uninstalling the service. Use ${bold( | ||
try { | ||
const server = await resolveServer(argv.path); | ||
const server = await resolveServer(argv); | ||
const db = client(server); | ||
try { | ||
await db.uninstallService(server.mount, { teardown: argv.teardown }); | ||
await db.uninstallService(argv.mount, { teardown: argv.teardown }); | ||
} catch (e) { | ||
if (e.isArangoError && e.errorNum === ERROR_SERVICE_NOT_FOUND) { | ||
if (argv.verbose) { | ||
detail(`Service "${server.mount}" not found.\nNothing to uninstall.`); | ||
detail(`Service "${argv.mount}" not found.\nNothing to uninstall.`); | ||
} | ||
@@ -46,3 +48,3 @@ process.exit(0); | ||
if (argv.verbose) { | ||
detail(`Service "${server.mount}" successfully removed.`); | ||
detail(`Service "${argv.mount}" successfully removed.`); | ||
} | ||
@@ -49,0 +51,0 @@ } catch (e) { |
"use strict"; | ||
const { common, parseServiceOptions, serverArgs } = require("../util/cli"); | ||
const { fatal, json } = require("../util/log"); | ||
const { bold } = require("chalk"); | ||
const { common, validateServiceArgs } = require("../util/cli"); | ||
const client = require("../util/client"); | ||
const resolveServer = require("../resolveServer"); | ||
const { json, fatal } = require("../util/log"); | ||
const resolveToStream = require("../resolveToStream"); | ||
const command = (exports.command = "upgrade <path> [source]"); | ||
const command = (exports.command = "upgrade <mount> [source]"); | ||
const description = (exports.description = "Upgrade a mounted service"); | ||
@@ -15,3 +16,3 @@ | ||
const args = [ | ||
["path", "Database-relative path the service is mounted on"], | ||
["mount", "Mount path of the service"], | ||
[ | ||
@@ -28,2 +29,3 @@ "source", | ||
common(yargs, { command, describe, args }).options({ | ||
...serverArgs, | ||
teardown: { | ||
@@ -44,3 +46,3 @@ describe: "Run the teardown script before upgrading the service", | ||
"Install the replacement in development mode. You can edit the service's files on the server and changes will be reflected automatically", | ||
alias: "D", | ||
alias: "dev", | ||
type: "boolean", | ||
@@ -78,6 +80,19 @@ default: false | ||
exports.handler = async function handler(argv) { | ||
const opts = validateServiceArgs(argv); | ||
const opts = parseServiceOptions(argv); | ||
try { | ||
const server = await resolveServer(argv.path); | ||
return await upgrade(argv, server, opts); | ||
const server = await resolveServer(argv); | ||
const source = argv.remote | ||
? argv.source | ||
: await resolveToStream(argv.source); | ||
const db = client(server); | ||
const result = await db.upgradeService(argv.mount, source, { | ||
...opts, | ||
setup: argv.setup, | ||
teardown: argv.teardown | ||
}); | ||
if (argv.raw) { | ||
json(result); | ||
} else { | ||
console.log(result); // TODO pretty-print | ||
} | ||
} catch (e) { | ||
@@ -87,16 +102,1 @@ fatal(e); | ||
}; | ||
async function upgrade(argv, server, opts) { | ||
const source = argv.remote ? argv.source : await resolveToStream(argv.source); | ||
const db = client(server); | ||
const result = await db.upgradeService(server.mount, source, { | ||
...opts, | ||
setup: argv.setup, | ||
teardown: argv.teardown | ||
}); | ||
if (argv.raw) { | ||
json(result); | ||
} else { | ||
console.log(result); // TODO pretty-print | ||
} | ||
} |
"use strict"; | ||
const dd = require("dedent"); | ||
const { white, bold } = require("chalk"); | ||
const { bold, white } = require("chalk"); | ||
const { fatal } = require("./util/log"); | ||
const { load: loadIni } = require("./ini"); | ||
const parseServerUrl = require("./util/parseServerUrl"); | ||
const { prompt } = require("inquirer"); | ||
const { unsplat } = require("./util/array"); | ||
const { validRange } = require("semver"); | ||
function applyDefaults(server) { | ||
const defaultToken = process.env.FOXX_ARANGODB_SERVER_TOKEN; | ||
if (server.url === undefined) { | ||
server.url = | ||
process.env.FOXX_ARANGODB_SERVER_URL || | ||
"http://localhost:8529/_db/_system"; | ||
async function resolve(endpointOrName = "default") { | ||
if (endpointOrName.match(/^((https?|tcp|ssl):)?\/\//)) { | ||
return parseServerUrl(endpointOrName); | ||
} | ||
if (server.version === undefined) { | ||
server.version = process.env.FOXX_ARANGODB_SERVER_VERSION; | ||
const ini = await loadIni(); | ||
if (ini.server[endpointOrName]) { | ||
return { | ||
...ini.server[endpointOrName], | ||
name: endpointOrName | ||
}; | ||
} | ||
if (server.token === undefined) { | ||
if ( | ||
server.username === undefined && | ||
server.password === undefined && | ||
defaultToken | ||
) { | ||
server.token = defaultToken; | ||
} else { | ||
if (server.username === undefined) { | ||
server.username = process.env.FOXX_ARANGODB_SERVER_USERNAME || "root"; | ||
} | ||
if (server.password === undefined) { | ||
server.password = process.env.FOXX_ARANGODB_SERVER_PASSWORD || ""; | ||
} | ||
} | ||
if (endpointOrName === "default") { | ||
return { name: endpointOrName }; | ||
} | ||
if (server.mount && server.mount.charAt(0) !== "/") { | ||
server.mount = `/${server.mount}`; | ||
} | ||
return server; | ||
return null; | ||
} | ||
async function resolve(mount) { | ||
if (!mount) return applyDefaults({}); | ||
if (mount.match(/^(https?|tcp|ssl):\/\//)) { | ||
const server = parseServerUrl(mount); | ||
return applyDefaults(server); | ||
module.exports = async function resolveServer(argv) { | ||
if (argv.password && argv.token) { | ||
fatal( | ||
`Can not use both ${bold("password")} and ${bold( | ||
"token" | ||
)} as authentication for the same server.` | ||
); | ||
} | ||
let name = "default"; | ||
if (mount && !mount.startsWith("/")) { | ||
let [head, ...tail] = mount.split(":"); | ||
name = head; | ||
mount = tail.join(":"); | ||
if (argv.username && argv.token) { | ||
fatal( | ||
`Can not use both ${bold("username")} and ${bold( | ||
"token" | ||
)} as authentication for the same server.` | ||
); | ||
} | ||
const ini = await loadIni(); | ||
if (hasOwnProperty.call(ini.server, name)) { | ||
return applyDefaults({ ...ini.server[name], name, mount }); | ||
const server = await resolve(unsplat(argv.server)); | ||
if (!server) { | ||
fatal(`Not a valid server: "${white(argv.server)}".`); | ||
} | ||
if (name !== "default") { | ||
return { name, mount }; | ||
if (argv.arangoVersion) { | ||
if (!validRange(argv.arangoVersion)) { | ||
fatal(`Not a valid semver version: "${white(argv.arangoVersion)}".`); | ||
} | ||
server.version = unsplat(argv.arangoVersion); | ||
} | ||
return applyDefaults({ name, mount }); | ||
} | ||
module.exports = async function resolveServer(path = "", requireMount = true) { | ||
const server = await resolve(path); | ||
if (!server.mount && requireMount) { | ||
let extra; | ||
if (!server.name) { | ||
extra = dd` | ||
When passing URLs make sure to include the mount path using the following format: | ||
${bold( | ||
"http://server.example/database-path#mount=/service-mount-path" | ||
)} | ||
`; | ||
} else if (server.name === path && !server.url) { | ||
extra = dd` | ||
When passing a bare mount path make sure that it starts with a slash: | ||
${bold(`/${path}`)} | ||
`; | ||
} else if (server.name === path || server.name !== "default") { | ||
extra = dd` | ||
When using a named server make sure to pass the mount path using the following format: | ||
${bold("server-name:service-mount-path")} | ||
`; | ||
if (server.url === undefined) { | ||
server.url = "http://localhost:8529"; | ||
} | ||
if (argv.database) { | ||
server.database = unsplat(argv.database); | ||
} else if (server.database === undefined) { | ||
server.database = "_system"; | ||
} | ||
if (argv.username) { | ||
delete server.token; | ||
server.username = unsplat(argv.username); | ||
server.password = ""; | ||
} | ||
if (argv.password) { | ||
delete server.token; | ||
const { password } = await prompt([ | ||
{ | ||
message: "Password", | ||
name: "password", | ||
type: "password" | ||
} | ||
]); | ||
server.password = password; | ||
} | ||
if (argv.token) { | ||
delete server.username; | ||
delete server.password; | ||
const { token } = await prompt([ | ||
{ | ||
message: "Token", | ||
name: "token", | ||
type: "password", | ||
validate: Boolean | ||
} | ||
]); | ||
server.token = token; | ||
} | ||
if (server.token === undefined) { | ||
if (server.username === undefined) { | ||
server.username = "root"; | ||
} | ||
fatal( | ||
`Not a valid mount path: "${white(path)}".${extra ? `\n\n${extra}` : ""}` | ||
); | ||
if (server.password === undefined) { | ||
server.password = ""; | ||
} | ||
} | ||
if (!server.url) { | ||
fatal(`Not a valid server: "${white(server.name || path)}".`); | ||
} | ||
return server; | ||
}; |
@@ -25,3 +25,39 @@ "use strict"; | ||
exports.validateServiceArgs = function validateServiceArgs(argv) { | ||
exports.serverArgs = { | ||
server: { | ||
describe: "ArangoDB server URL or alias", | ||
alias: "H", | ||
type: "string", | ||
default: "default" | ||
}, | ||
username: { | ||
describe: "Username to authenticate with", | ||
alias: "u", | ||
type: "string" | ||
}, | ||
password: { | ||
describe: "Use password to authenticate", | ||
alias: "P", | ||
type: "boolean", | ||
default: false | ||
}, | ||
token: { | ||
describe: "Use bearer token to authenticate", | ||
alias: "T", | ||
type: "boolean", | ||
default: false | ||
}, | ||
database: { | ||
describe: "ArangoDB database name", | ||
alias: "D", | ||
type: "string" | ||
}, | ||
"arango-version": { | ||
describe: "ArangoDB server version", | ||
alias: "V", | ||
type: "string" | ||
} | ||
}; | ||
exports.parseServiceOptions = function parseServiceOptions(argv) { | ||
if (argv.source) argv.source = unsplat(argv.source); | ||
@@ -28,0 +64,0 @@ if (argv.cfg) argv.cfg = splat(argv.cfg); |
@@ -5,6 +5,6 @@ "use strict"; | ||
module.exports = function(server) { | ||
const db = new Database({ | ||
url: server.url, | ||
databaseName: false | ||
}); | ||
const db = new Database({ url: server.url }); | ||
if (server.database !== "_system") { | ||
db.useDatabase(server.database); | ||
} | ||
if (server.token) { | ||
@@ -11,0 +11,0 @@ db.useBearerAuth(server.token); |
@@ -51,2 +51,8 @@ /*eslint-disable no-console */ | ||
exports.error(err); | ||
} else if (err.code === "ENETUNREACH") { | ||
exports.error( | ||
`Network unreachable: ${red.bold(err.address)}:${red.bold( | ||
err.port | ||
)}\nAre you offline?` | ||
); | ||
} else if (err.code === "ECONNREFUSED") { | ||
@@ -56,3 +62,3 @@ exports.error( | ||
err.port | ||
)}\nAre you offline?` | ||
)}\nIs the server down?` | ||
); | ||
@@ -59,0 +65,0 @@ } else if (err.isArangoError) { |
"use strict"; | ||
const { parse: parseUrl } = require("url"); | ||
const { parse: parseQuery } = require("querystring"); | ||
@@ -15,8 +14,2 @@ module.exports = function parseServerUrl(input) { | ||
} | ||
if (url.hash) { | ||
const query = parseQuery(url.hash.slice(1)); | ||
if (query.version !== undefined) server.version = query.version; | ||
if (query.mount !== undefined) server.mount = query.mount; | ||
if (query.token !== undefined) server.token = query.token; | ||
} | ||
const protocol = | ||
@@ -26,4 +19,8 @@ url.protocol === "tcp:" | ||
: url.protocol === "ssl:" ? "https:" : url.protocol; | ||
server.url = `${protocol}//${url.host}${url.pathname}`; | ||
if (protocol && url.host) { | ||
server.url = `${protocol}//${url.host}`; | ||
} else if (url.href.startsWith("//")) { | ||
server.url = `http:${url.href}`; | ||
} | ||
return server; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
8
118099
17
2921
+ Addedlodash@^4.17.4