Improve command-line handling
This commit is contained in:
parent
6a1a83eb62
commit
3892e149be
3 changed files with 150 additions and 11 deletions
73
package-lock.json
generated
73
package-lock.json
generated
|
@ -9,6 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"command-line-args": "^6.0.1",
|
||||
"find-up": "^7.0.0",
|
||||
"oracledb": "^6.8.0"
|
||||
},
|
||||
|
@ -16,6 +17,7 @@
|
|||
"node-oracledb-cli": "dist/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/command-line-args": "^5.2.3",
|
||||
"@types/oracledb": "^6.9.1",
|
||||
"tsx": "^4.20.4",
|
||||
"typescript": "^5.9.2"
|
||||
|
@ -463,6 +465,13 @@
|
|||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/command-line-args": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz",
|
||||
"integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
|
||||
|
@ -483,6 +492,38 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/array-back": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
|
||||
"integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/command-line-args": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz",
|
||||
"integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"array-back": "^6.2.2",
|
||||
"find-replace": "^5.0.2",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"typical": "^7.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.9",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
|
||||
|
@ -525,6 +566,23 @@
|
|||
"@esbuild/win32-x64": "0.25.9"
|
||||
}
|
||||
},
|
||||
"node_modules/find-replace": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz",
|
||||
"integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz",
|
||||
|
@ -585,6 +643,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/oracledb": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oracledb/-/oracledb-6.9.0.tgz",
|
||||
|
@ -678,6 +742,15 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/typical": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz",
|
||||
"integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"name": "node-oracledb-cli",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"author": "Jan Hamal Dvořák <mordae@anilinux.org>",
|
||||
"license": "MIT",
|
||||
"description": "Command-line Oracle Client",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js",
|
||||
|
@ -10,14 +12,14 @@
|
|||
"bin": {
|
||||
"node-oracledb-cli": "dist/index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/command-line-args": "^5.2.3",
|
||||
"@types/oracledb": "^6.9.1",
|
||||
"tsx": "^4.20.4",
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"command-line-args": "^6.0.1",
|
||||
"find-up": "^7.0.0",
|
||||
"oracledb": "^6.8.0"
|
||||
}
|
||||
|
|
80
src/index.ts
80
src/index.ts
|
@ -1,9 +1,11 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'node:fs'
|
||||
import os from 'node:os'
|
||||
import readline from 'node:readline'
|
||||
import oracledb from 'oracledb'
|
||||
import { findUpSync } from 'find-up'
|
||||
import commandLineArgs from 'command-line-args'
|
||||
|
||||
interface OraTable {
|
||||
OWNER: string
|
||||
|
@ -87,15 +89,73 @@ function getStringParts(str: string, offset: number) {
|
|||
return { init, word, rest }
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2)
|
||||
interface Options {
|
||||
host: string
|
||||
port: number
|
||||
dbname: string
|
||||
username: string
|
||||
help: boolean
|
||||
}
|
||||
|
||||
if (args.length < 3) {
|
||||
console.log('Usage: node oracle-client.js <user> <password> <connectString>')
|
||||
process.exit(1)
|
||||
async function main() {
|
||||
const { username } = os.userInfo()
|
||||
|
||||
const options = commandLineArgs([
|
||||
{ name: 'host', alias: 'h', type: String, defaultValue: 'localhost' },
|
||||
{ name: 'port', alias: 'p', type: parseInt, defaultValue: 1521 },
|
||||
{ name: 'dbname', alias: 'd', type: String, defaultValue: 'hr', defaultOption: true },
|
||||
{ name: 'username', alias: 'U', type: String, defaultValue: username },
|
||||
{ name: 'help', type: Boolean, defaultValue: false },
|
||||
]) as Options
|
||||
|
||||
if (options.help) {
|
||||
console.log('Usage: node-oracledb-cli -h dbhost -U username dbname')
|
||||
console.log('Command line client for Oracle SQL databases\n')
|
||||
console.log('Options:')
|
||||
console.log(' --help Show this help')
|
||||
console.log(' --host, -h HOST Address of the host to connect to')
|
||||
console.log(' --port, -p PORT Port of the host to connect to')
|
||||
console.log(' --dbname, -d NAME Name of the database/service to connect to')
|
||||
console.log(' --username, -u NAME Name of the user for login')
|
||||
console.log('\nAuthentication:')
|
||||
console.log(' You need to create .orapass file in this or a parent directory.')
|
||||
console.log(' The file shall contain "host:port:dbname:username:password" lines.')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const [user, password, connectString] = args
|
||||
const passFile = findUpSync([
|
||||
'.config/node-oracledb-cli/passwords',
|
||||
'.oracle_passwords',
|
||||
'.orapass',
|
||||
])
|
||||
const passLines = passFile ? fs.readFileSync(passFile, 'utf8') : ''
|
||||
const passwords = passLines
|
||||
.split('\n')
|
||||
.map((line) => line.trim().split(/:/g))
|
||||
.filter(([h, p, d, u]) => {
|
||||
if (
|
||||
h === options.host &&
|
||||
parseInt(p) === options.port &&
|
||||
d === options.dbname &&
|
||||
u === options.username
|
||||
) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
.map((row) => row[4])
|
||||
|
||||
if (process.env.ORACLE_PASSWORD !== undefined) {
|
||||
passwords.unshift(process.env.ORACLE_PASSWORD)
|
||||
}
|
||||
|
||||
if (!passwords.length) {
|
||||
console.error('Password not found. Please create .orapass entry like this:\n')
|
||||
console.error(
|
||||
`${options.host}:${options.port}:${options.dbname}:${options.username}:Passw0rd123\n`,
|
||||
)
|
||||
console.error('Or set ORACLE_PASSWORD environment variable and try again.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const historyFile = findUpSync(['.config/node-oracledb-cli/history', '.oracle_history'])
|
||||
const historyLines = historyFile ? fs.readFileSync(historyFile, 'utf8') : ''
|
||||
|
@ -107,7 +167,7 @@ async function main() {
|
|||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
prompt: `${user}@${connectString}> `,
|
||||
prompt: `${options.username}@${options.dbname}> `,
|
||||
removeHistoryDuplicates: true,
|
||||
history,
|
||||
completer(linePartial: string) {
|
||||
|
@ -160,7 +220,11 @@ async function main() {
|
|||
},
|
||||
})
|
||||
|
||||
const connection = await oracledb.getConnection({ user, password, connectString })
|
||||
const connection = await oracledb.getConnection({
|
||||
user: options.username,
|
||||
password: passwords[0],
|
||||
connectString: `${options.host}:${options.port}/${options.dbname}`,
|
||||
})
|
||||
|
||||
function execute<R>(query: string, args: any[] = [], maxRows?: number) {
|
||||
return connection.execute<R>(query, args, {
|
||||
|
|
Loading…
Reference in a new issue