Skip to content

Latest commit

 

History

History
649 lines (441 loc) · 17.5 KB

File metadata and controls

649 lines (441 loc) · 17.5 KB

Utils Directory

This directory contains reusable utility modules that provide core functionality for the SAP HANA Developer CLI tool. These utilities handle database connections, CLI interactions, security, and various helper functions used throughout the application.

Table of Contents


Core Utilities

base.js

Module: base - Central functionality shared by all commands

The base module is the foundation of the CLI tool, providing shared functionality that is used across all commands.

Key Features:

  • Database connection management
  • Terminal UI components (spinners, progress bars, tables)
  • Color output support via chalk
  • Prompts handling and validation
  • Debugging utilities
  • Internationalization (i18n) support via text bundles
  • Command builder for yargs
  • File opening utilities

Key Exports:

export const dbClass           // sap-hdb-promisfied instance
export const colors            // Chalk color utilities
export const debug             // Debug logging function
export const terminal          // Terminal-kit instance
export const bundle            // Text bundle for i18n
export const sqlInjection      // SQL injection protection

export const tableOptions      // Default table rendering options

Important Functions:

  • createDBConnection(options) - Create and return a database connection
  • getBuilder(input, iConn, iDebug) - Initialize Yargs builder with connection and debug groups
  • setPrompts(newPrompts) / getPrompts() - Manage command prompts
  • startSpinnerInt() / stopSpinnerInt() - Control terminal spinner
  • clearConnection() - Clear the database connection
  • blankLine() - Output a blank line to console

Usage:

import * as base from './utils/base.js'
const db = await base.createDBConnection()
base.colors.green('Success!')

connections.js

Module: connections - Helper utility for making connections to HANA DB and determining connection settings

Manages database connectivity and configuration file discovery, supporting multiple connection methods and secure credential management.

Key Features:

  • Searches for configuration files in current and parent directories
  • Supports multiple connection file types (default-env.json, .env, .cdsrc-private.json)
  • Handles admin connection overrides
  • Integrates with SAP CAP/CDS projects
  • Supports secure credential lookup via cds bind

Key Functions:

  • getFileCheckParents(filename) - Search for a file in current and parent directories (up to 5 levels)
  • getPackageJSON() - Find package.json file
  • getMTA() - Find mta.yaml file
  • getDefaultEnv() - Find default-env.json file
  • getDefaultEnvAdmin() - Find default-env-admin.json file
  • getEnv() - Find .env file

Connection Resolution Order:

  1. Admin option: default-env-admin.json
  2. CDS bind: .cdsrc-private.json (most secure, cloud-based lookup)
  3. Local env: .env file with VCAP_SERVICES
  4. Custom file via --conn parameter
  5. Default: default-env.json
  6. Fallback: ${homedir}/.hana-cli/default.json

Usage:

import * as conn from './utils/connections.js'
const envFile = conn.getDefaultEnv()
const pkgJson = conn.getPackageJSON()

dbInspect.js

Module: dbInspect - Database Object Dynamic Inspection and Metadata processing

Provides utilities for inspecting and retrieving metadata about various SAP HANA database objects.

Key Features:

  • Retrieve HANA database version information
  • Inspect views, including calculation views
  • Get database object metadata
  • Handle different HANA versions (1.x and 2.x)
  • Support for column views, calculation views, and structured privileges

Key Functions:

  • getHANAVersion(db) - Return the HANA DB version and major version number
  • isCalculationView(db, schema, viewId) - Check if a view is a calculation view
  • getView(db, schema, viewId) - Get DB view details including metadata

Usage:

import * as dbInspect from './utils/dbInspect.js'
const version = await dbInspect.getHANAVersion(db)
const isCalcView = await dbInspect.isCalculationView(db, 'MYSCHEMA', 'MY_VIEW')
const viewDetails = await dbInspect.getView(db, 'MYSCHEMA', 'MY_VIEW')

locale.js

Module: Simple locale detection utility

Detects the user's locale from environment variables for internationalization support.

Key Functions:

  • getLocale(env) - Get the locale from environment variables (LC_ALL, LC_MESSAGES, LANG, or LANGUAGE)

Usage:

import * as locale from './utils/locale.js'
const userLocale = locale.getLocale()

sqlInjection.js

Module: sqlInjection - SQL Injection Protection Utilities

Provides security utilities to protect against SQL injection attacks by validating SQL parameters.

Key Features:

  • Whitespace character validation
  • SQL separator character detection
  • Quoted parameter validation
  • Token-based parameter validation
  • Protection against malicious SQL input

Key Exports:

export const whitespaceTable   // Table of valid whitespace characters
export const separatorTable    // Table of SQL separator characters

Key Functions:

  • isAcceptableParameter(value, maxToken) - Check if a parameter is safe (default: 1 token max)
  • isAcceptableQuotedParameter(value) - Check if a quoted parameter contains no unescaped quotes

Usage:

import * as sqlInjection from './utils/sqlInjection.js'
if (sqlInjection.isAcceptableParameter(userInput, 1)) {
    // Safe to use in SQL query
}

versionCheck.js

Module: Node.js version validation utility

Validates that the current Node.js version meets the requirements specified in package.json.

Key Functions:

  • checkVersion() - Check if the current Node.js version meets the required version

Usage:

import * as versionCheck from './utils/versionCheck.js'
await versionCheck.checkVersion()

CLI Integration Utilities

btp.js

Module: btp - Library for calling BTP APIs via CLI

Provides utilities for interacting with SAP Business Technology Platform (BTP) via the btp CLI.

Key Features:

  • BTP CLI version detection
  • Configuration file parsing
  • Service instance management
  • Global account and subaccount targeting

Key Constants:

  • globalAccount, subAccount, hanaCloudTools, applicationStudio, hanaPlanName

Key Functions:

  • getVersion() - Get btp CLI version
  • getInfo() - Get btp CLI info (configuration, server URL, user)
  • getBTPConfig() - Read central configuration file for BTP CLI

Usage:

import * as btp from './utils/btp.js'
const version = await btp.getVersion()
const info = await btp.getInfo()
const config = await btp.getBTPConfig()

cf.js

Module: cf - Library for calling CF APIs via CLI

Provides utilities for interacting with Cloud Foundry via the cf CLI.

Key Features:

  • CF CLI version detection
  • Organization and space management
  • Configuration file parsing (~/.cf/config.json)
  • Target information retrieval

Key Functions:

  • getVersion() - Get cf CLI version
  • getCFConfig() - Read central configuration file for CF CLI
  • getCFOrg() / getCFOrgName() / getCFOrgGUID() - Get target organization details
  • getCFSpace() / getCFSpaceName() / getCFSpaceGUID() - Get target space details

Usage:

import * as cf from './utils/cf.js'
const version = await cf.getVersion()
const orgName = await cf.getCFOrgName()
const spaceName = await cf.getCFSpaceName()

xs.js

Module: xs - Library for calling XSA APIs via CLI

Provides utilities for interacting with SAP XS Advanced (XSA) via the xs CLI.

Key Features:

  • XSA configuration file parsing (~/.xsconfig)
  • Organization and space management for XSA
  • Similar API to cf.js for consistency

Key Functions:

  • getCFConfig() - Read central configuration file for XSA CLI
  • getCFOrg() / getCFOrgName() / getCFOrgGUID() - Get target organization details
  • getCFSpace() / getCFSpaceName() / getCFSpaceGUID() - Get target space details

Usage:

import * as xs from './utils/xs.js'
const config = await xs.getCFConfig()
const orgName = await xs.getCFOrgName()

Database Utilities

massConvert.js

Module: Mass conversion utilities for database objects

Provides functionality for bulk conversion and export of database objects (tables, views) to various formats.

Key Features:

  • Convert multiple tables to HDI artifact formats (.hdbtable)
  • Convert views to HDI formats
  • Progress bar visualization
  • ZIP file generation for exports
  • Error logging and handling
  • Support for SQL-based and CDS-based outputs

Notes:

  • limit values are validated as positive integers when provided.
  • View exports in hdbtable output are written as .hdbview artifacts in the ZIP.
  • Output folders are created automatically if they do not exist.

Key Functions:

  • hdbtableTablesSQL(prompts, results, wss, db, schema, replacer, zip, logOutput) - Convert tables to .hdbtable SQL format
  • hdbtableViewsSQL(prompts, viewResults, wss, db, schema, replacer, zip, logOutput) - Convert views to .hdbtable SQL format
  • getProcessBarTableOptions(prompts, length) - Build progress bar options for tables
  • getProcessBarViewOptions(prompts, length) - Build progress bar options for views

Usage:

import * as massConvert from './utils/massConvert.js'
// Used internally by mass conversion commands

database/ Subfolder

The database/ subfolder contains database-specific client implementations that provide abstraction over different database types.

index.js

Module: Abstract database client super class

Base class that provides a common interface for all database-specific implementations.

Key Features:

  • Factory pattern for database client instantiation
  • Supports HANA (CDS and direct), PostgreSQL, and SQLite
  • Connection management (connect/disconnect)
  • Schema targeting
  • Profile-based configuration
  • Credential management

Key Class: dbClientClass

Key Methods:

  • static async getNewClient(prompts) - Factory method to create the appropriate database client based on profile
  • async connect() - Connect to the target database
  • async disconnect() - Disconnect from the target database
  • async connectTargetSchema(schema) - Connect to a specific schema
  • async listTables() - Abstract method implemented by subclasses
  • getDB() / setDB(db) - Getter/setter for database connection
  • getPrompts() - Get current prompts
  • schemaCalculation(prompts, optionsCDS) - Calculate schema name from options

Supported Database Kinds:

  • hana - SAP HANA via CDS
  • postgres - PostgreSQL via CDS
  • sqlite - SQLite via CDS
  • hybrid / no profile - SAP HANA direct connection (non-CDS)

hanaCDS.js

Module: Database Client for HANA via CDS

Extends dbClientClass to provide HANA-specific functionality using SAP CAP/CDS.

Key Features:

  • CDS-based querying
  • Schema calculation and filtering
  • Table listing with metadata

Key Methods:

  • async listTables() - Get list of tables from HANA database using CDS query builder

hanaDirect.js

Module: Database Client for HANA Direct Connection (non-CDS)

Extends dbClientClass to provide direct HANA connectivity without CDS.

Key Features:

  • Direct HANA connection using sap-hdb-promisfied
  • Raw SQL execution
  • Independent of CAP/CDS project structure

Key Methods:

  • async connect() - Connect to HANA database directly
  • async disconnect() - Disconnect from HANA database
  • async listTables() - Get list of tables using direct SQL queries
  • async execSQL(query) - Execute SQL query directly on HANA

Usage: Automatically selected when no CDS profile is specified.


postgres.js

Module: Database Client for PostgreSQL via CDS

Extends dbClientClass to provide PostgreSQL-specific functionality using SAP CAP/CDS.

Key Features:

  • PostgreSQL schema management (search_path)
  • CDS query builder for PostgreSQL
  • Information schema integration

Key Methods:

  • async listTables() - Get list of tables from PostgreSQL database using CDS

sqlite.js

Module: Database Client for SQLite via CDS

Extends dbClientClass to provide SQLite-specific functionality using SAP CAP/CDS.

Key Features:

  • SQLite schema introspection
  • Lightweight database support
  • Ideal for local development and testing

Key Methods:

  • async listTables() - Get list of tables from SQLite database using sqlite_schema

Usage Examples

Establishing a Database Connection

import * as base from './utils/base.js'

// Set prompts
const prompts = {
    admin: false,
    schema: 'MYSCHEMA',
    table: '*',
    limit: 100
}
base.setPrompts(prompts)

// Create connection
const db = await base.createDBConnection()

// Use database connection
const version = await dbInspect.getHANAVersion(db)
console.log(`HANA Version: ${version.VERSION}`)

Using Database Client Factory

import DBClientClass from './utils/database/index.js'

// Get appropriate database client based on prompts
const prompts = { 
    profile: 'development',  // or 'production', 'hybrid', etc.
    table: 'MY_TABLE',
    limit: 50
}

const dbClient = await DBClientClass.getNewClient(prompts)
await dbClient.connect()

// List tables
const tables = await dbClient.listTables()
console.log(tables)

// Cleanup
await dbClient.disconnect()

Security: Validating User Input

import * as sqlInjection from './utils/sqlInjection.js'

function executeQuery(userTableName) {
    // Validate input before using in SQL
    if (!sqlInjection.isAcceptableParameter(userTableName, 1)) {
        throw new Error('Invalid table name: possible SQL injection attempt')
    }
    
    // Safe to use in query
    const query = `SELECT * FROM ${userTableName}`
    // ... execute query
}

Finding Configuration Files

import * as conn from './utils/connections.js'

// Search for configuration files
const defaultEnv = conn.getDefaultEnv()
const packageJson = conn.getPackageJSON()
const mtaYaml = conn.getMTA()

if (defaultEnv) {
    console.log(`Found default-env.json at: ${defaultEnv}`)
}

Using Terminal UI Components

import * as base from './utils/base.js'

// Start spinner
base.startSpinnerInt()
// ... perform long operation
base.stopSpinnerInt()

// Display colored output
console.log(base.colors.green('Success!'))
console.log(base.colors.red('Error!'))

// Display data as table
const data = [
    { name: 'Table1', rows: 100 },
    { name: 'Table2', rows: 200 }
]
base.terminal.table(data, base.tableOptions)

Checking BTP/CF Configuration

import * as btp from './utils/btp.js'
import * as cf from './utils/cf.js'

// Check BTP CLI
try {
    const btpVersion = await btp.getVersion()
    const btpInfo = await btp.getInfo()
    console.log(`BTP CLI Version: ${btpVersion}`)
    console.log(`Server URL: ${btpInfo.serverURL}`)
} catch (error) {
    console.log('BTP CLI not configured')
}

// Check CF CLI
try {
    const cfVersion = await cf.getVersion()
    const orgName = await cf.getCFOrgName()
    const spaceName = await cf.getCFSpaceName()
    console.log(`CF CLI Version: ${cfVersion}`)
    console.log(`Org: ${orgName}, Space: ${spaceName}`)
} catch (error) {
    console.log('CF CLI not configured')
}

Architecture Notes

Modular Design

The utilities are designed to be modular and reusable across the CLI tool. Each module has a specific responsibility and can be used independently or in combination with others.

Database Abstraction

The database/ subfolder implements a factory pattern with a common abstract base class, allowing the CLI to work with multiple database types (HANA, PostgreSQL, SQLite) through a unified interface.

Security First

SQL injection protection is built into the core utilities and should be used whenever constructing SQL queries with user input.

Internationalization

The base module integrates with SAP's text bundle system for i18n support, allowing the CLI to be localized to different languages.

Connection Flexibility

The connection utilities support multiple methods of providing credentials, from local files to secure cloud-based lookups, giving users flexibility in how they manage sensitive information.


Contributing

When adding new utilities to this folder:

  1. Follow the module pattern: Export modules with ES6 export syntax
  2. Document your functions: Use JSDoc comments for all exported functions
  3. Add to this README: Update this document with your new utility's description and usage examples
  4. Handle errors gracefully: Use try-catch blocks and provide meaningful error messages
  5. Security first: Always validate user input, especially for SQL operations
  6. Test your code: Ensure your utilities work with different database types and configurations

See Also