| import { CLIOptions, Inquirerer } from 'inquirerer'; | ||
| declare const _default: (argv: Partial<Record<string, any>>, _prompter: Inquirerer, _options: CLIOptions) => Promise<void>; | ||
| export default _default; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| const child_process_1 = require("child_process"); | ||
| const pg_env_1 = require("pg-env"); | ||
| const doctor_1 = require("../utils/doctor"); | ||
| const doctorUsageText = ` | ||
| Doctor Command: | ||
| pgpm doctor [OPTIONS] | ||
| Check that your machine has the dependencies pgpm needs | ||
| (Node.js, Docker, psql) and report OS-specific installation | ||
| guidance for anything that is missing. | ||
| Options: | ||
| --db Also check PostgreSQL connectivity using the current environment | ||
| --json Output results as JSON | ||
| --help, -h Show this help message | ||
| Exit Codes: | ||
| 0 All checks passed (warnings allowed) | ||
| 1 One or more checks failed | ||
| Examples: | ||
| pgpm doctor Check node, docker, docker compose, and psql | ||
| pgpm doctor --db Also verify a PostgreSQL connection | ||
| pgpm doctor --json Machine-readable output (for CI) | ||
| `; | ||
| const STATUS_ICONS = { | ||
| pass: 'â ', | ||
| warn: 'â ī¸ ', | ||
| fail: 'â' | ||
| }; | ||
| async function checkDatabaseConnectivity() { | ||
| const pg = (0, pg_env_1.getPgEnvOptions)(); | ||
| const target = `${pg.host}:${pg.port}/${pg.database} (user: ${pg.user})`; | ||
| const result = await new Promise((resolve) => { | ||
| const child = (0, child_process_1.spawn)('psql', ['-X', '-A', '-t', '-c', 'SELECT 1'], { | ||
| stdio: 'pipe', | ||
| env: (0, pg_env_1.getSpawnEnvWithPg)(pg) | ||
| }); | ||
| let stderr = ''; | ||
| child.stderr?.on('data', (d) => { stderr += d.toString(); }); | ||
| child.on('error', () => resolve({ code: 127, stderr: 'psql: command not found' })); | ||
| child.on('close', (code) => resolve({ code: code ?? 0, stderr: stderr.trim() })); | ||
| }); | ||
| if (result.code === 0) { | ||
| return { | ||
| name: 'database', | ||
| status: 'pass', | ||
| message: `connected to PostgreSQL at ${target}` | ||
| }; | ||
| } | ||
| return { | ||
| name: 'database', | ||
| status: 'fail', | ||
| message: `could not connect to PostgreSQL at ${target}: ${result.stderr}`, | ||
| remediation: 'Start a local PostgreSQL with `pgpm docker start`, or point PGHOST/PGPORT/PGUSER/PGPASSWORD at a running server (see `pgpm env`).' | ||
| }; | ||
| } | ||
| function printResults(results) { | ||
| console.log(''); | ||
| for (const result of results) { | ||
| console.log(` ${STATUS_ICONS[result.status]} ${result.name.padEnd(16)} ${result.message}`); | ||
| if (result.remediation && result.status !== 'pass') { | ||
| console.log(` âŗ ${result.remediation}`); | ||
| } | ||
| } | ||
| const { failed, warned, passed } = (0, doctor_1.summarizeChecks)(results); | ||
| console.log(''); | ||
| console.log(` ${passed} passed, ${warned} warning(s), ${failed} failed`); | ||
| console.log(''); | ||
| } | ||
| exports.default = async (argv, _prompter, _options) => { | ||
| if (argv.help || argv.h) { | ||
| console.log(doctorUsageText); | ||
| process.exit(0); | ||
| } | ||
| const platformInfo = (0, doctor_1.detectPlatform)(); | ||
| const results = [ | ||
| (0, doctor_1.checkNode)(), | ||
| await (0, doctor_1.checkDocker)(platformInfo, doctor_1.runCommand), | ||
| await (0, doctor_1.checkDockerCompose)(platformInfo, doctor_1.runCommand), | ||
| await (0, doctor_1.checkPsql)(platformInfo, doctor_1.runCommand) | ||
| ]; | ||
| if (argv.db === true) { | ||
| results.push(await checkDatabaseConnectivity()); | ||
| } | ||
| if (argv.json === true) { | ||
| const { failed, warned, passed } = (0, doctor_1.summarizeChecks)(results); | ||
| console.log(JSON.stringify({ | ||
| platform: platformInfo, | ||
| checks: results, | ||
| summary: { passed, warned, failed } | ||
| }, null, 2)); | ||
| } | ||
| else { | ||
| printResults(results); | ||
| } | ||
| const { failed } = (0, doctor_1.summarizeChecks)(results); | ||
| if (failed > 0) { | ||
| process.exit(1); | ||
| } | ||
| }; |
| import { spawn } from 'child_process'; | ||
| import { getPgEnvOptions, getSpawnEnvWithPg } from 'pg-env'; | ||
| import { checkDocker, checkDockerCompose, checkNode, checkPsql, detectPlatform, runCommand, summarizeChecks } from '../utils/doctor'; | ||
| const doctorUsageText = ` | ||
| Doctor Command: | ||
| pgpm doctor [OPTIONS] | ||
| Check that your machine has the dependencies pgpm needs | ||
| (Node.js, Docker, psql) and report OS-specific installation | ||
| guidance for anything that is missing. | ||
| Options: | ||
| --db Also check PostgreSQL connectivity using the current environment | ||
| --json Output results as JSON | ||
| --help, -h Show this help message | ||
| Exit Codes: | ||
| 0 All checks passed (warnings allowed) | ||
| 1 One or more checks failed | ||
| Examples: | ||
| pgpm doctor Check node, docker, docker compose, and psql | ||
| pgpm doctor --db Also verify a PostgreSQL connection | ||
| pgpm doctor --json Machine-readable output (for CI) | ||
| `; | ||
| const STATUS_ICONS = { | ||
| pass: 'â ', | ||
| warn: 'â ī¸ ', | ||
| fail: 'â' | ||
| }; | ||
| async function checkDatabaseConnectivity() { | ||
| const pg = getPgEnvOptions(); | ||
| const target = `${pg.host}:${pg.port}/${pg.database} (user: ${pg.user})`; | ||
| const result = await new Promise((resolve) => { | ||
| const child = spawn('psql', ['-X', '-A', '-t', '-c', 'SELECT 1'], { | ||
| stdio: 'pipe', | ||
| env: getSpawnEnvWithPg(pg) | ||
| }); | ||
| let stderr = ''; | ||
| child.stderr?.on('data', (d) => { stderr += d.toString(); }); | ||
| child.on('error', () => resolve({ code: 127, stderr: 'psql: command not found' })); | ||
| child.on('close', (code) => resolve({ code: code ?? 0, stderr: stderr.trim() })); | ||
| }); | ||
| if (result.code === 0) { | ||
| return { | ||
| name: 'database', | ||
| status: 'pass', | ||
| message: `connected to PostgreSQL at ${target}` | ||
| }; | ||
| } | ||
| return { | ||
| name: 'database', | ||
| status: 'fail', | ||
| message: `could not connect to PostgreSQL at ${target}: ${result.stderr}`, | ||
| remediation: 'Start a local PostgreSQL with `pgpm docker start`, or point PGHOST/PGPORT/PGUSER/PGPASSWORD at a running server (see `pgpm env`).' | ||
| }; | ||
| } | ||
| function printResults(results) { | ||
| console.log(''); | ||
| for (const result of results) { | ||
| console.log(` ${STATUS_ICONS[result.status]} ${result.name.padEnd(16)} ${result.message}`); | ||
| if (result.remediation && result.status !== 'pass') { | ||
| console.log(` âŗ ${result.remediation}`); | ||
| } | ||
| } | ||
| const { failed, warned, passed } = summarizeChecks(results); | ||
| console.log(''); | ||
| console.log(` ${passed} passed, ${warned} warning(s), ${failed} failed`); | ||
| console.log(''); | ||
| } | ||
| export default async (argv, _prompter, _options) => { | ||
| if (argv.help || argv.h) { | ||
| console.log(doctorUsageText); | ||
| process.exit(0); | ||
| } | ||
| const platformInfo = detectPlatform(); | ||
| const results = [ | ||
| checkNode(), | ||
| await checkDocker(platformInfo, runCommand), | ||
| await checkDockerCompose(platformInfo, runCommand), | ||
| await checkPsql(platformInfo, runCommand) | ||
| ]; | ||
| if (argv.db === true) { | ||
| results.push(await checkDatabaseConnectivity()); | ||
| } | ||
| if (argv.json === true) { | ||
| const { failed, warned, passed } = summarizeChecks(results); | ||
| console.log(JSON.stringify({ | ||
| platform: platformInfo, | ||
| checks: results, | ||
| summary: { passed, warned, failed } | ||
| }, null, 2)); | ||
| } | ||
| else { | ||
| printResults(results); | ||
| } | ||
| const { failed } = summarizeChecks(results); | ||
| if (failed > 0) { | ||
| process.exit(1); | ||
| } | ||
| }; |
| import { spawn } from 'child_process'; | ||
| import { readFileSync } from 'fs'; | ||
| export const runCommand = (command, args) => { | ||
| return new Promise((resolve) => { | ||
| const child = spawn(command, args, { stdio: 'pipe' }); | ||
| let stdout = ''; | ||
| let stderr = ''; | ||
| child.stdout?.on('data', (data) => { | ||
| stdout += data.toString(); | ||
| }); | ||
| child.stderr?.on('data', (data) => { | ||
| stderr += data.toString(); | ||
| }); | ||
| child.on('error', () => { | ||
| resolve({ code: 127, stdout: '', stderr: `${command}: command not found` }); | ||
| }); | ||
| child.on('close', (code) => { | ||
| resolve({ code: code ?? 0, stdout: stdout.trim(), stderr: stderr.trim() }); | ||
| }); | ||
| }); | ||
| }; | ||
| export function detectPlatform(platform = process.platform, readFile = (p) => readFileSync(p, 'utf-8')) { | ||
| if (platform === 'darwin') { | ||
| return { platform: 'macos' }; | ||
| } | ||
| if (platform === 'win32') { | ||
| return { platform: 'windows' }; | ||
| } | ||
| if (platform === 'linux') { | ||
| let distro; | ||
| try { | ||
| const release = readFile('/etc/os-release'); | ||
| const match = release.match(/^ID=("?)([^"\n]*)\1$/m); | ||
| if (match) { | ||
| distro = match[2]; | ||
| } | ||
| } | ||
| catch { | ||
| // ignore | ||
| } | ||
| try { | ||
| const version = readFile('/proc/version'); | ||
| if (/microsoft/i.test(version)) { | ||
| return { platform: 'wsl', distro }; | ||
| } | ||
| } | ||
| catch { | ||
| // ignore | ||
| } | ||
| return { platform: 'linux', distro }; | ||
| } | ||
| return { platform: 'unknown' }; | ||
| } | ||
| const DEBIAN_LIKE = ['ubuntu', 'debian', 'pop', 'linuxmint', 'elementary']; | ||
| const RHEL_LIKE = ['fedora', 'rhel', 'centos', 'rocky', 'almalinux', 'amzn']; | ||
| function isDebianLike(distro) { | ||
| return !!distro && DEBIAN_LIKE.includes(distro); | ||
| } | ||
| function isRhelLike(distro) { | ||
| return !!distro && RHEL_LIKE.includes(distro); | ||
| } | ||
| export function dockerInstallGuidance(info) { | ||
| switch (info.platform) { | ||
| case 'macos': | ||
| return 'Install Docker Desktop for Mac: https://www.docker.com/products/docker-desktop/ (or `brew install --cask docker`)'; | ||
| case 'windows': | ||
| return 'Install Docker Desktop for Windows: https://www.docker.com/products/docker-desktop/'; | ||
| case 'wsl': | ||
| return 'Install Docker Desktop for Windows with the WSL 2 backend enabled: https://docs.docker.com/desktop/wsl/'; | ||
| case 'linux': | ||
| if (isDebianLike(info.distro)) { | ||
| return 'Install Docker Engine: https://docs.docker.com/engine/install/ubuntu/ (e.g. `sudo apt-get install docker.io` or the official docker-ce packages)'; | ||
| } | ||
| if (isRhelLike(info.distro)) { | ||
| return 'Install Docker Engine: https://docs.docker.com/engine/install/fedora/ (e.g. `sudo dnf install docker-ce`)'; | ||
| } | ||
| return 'Install Docker Engine for your distribution: https://docs.docker.com/engine/install/'; | ||
| default: | ||
| return 'Install Docker: https://docs.docker.com/get-docker/'; | ||
| } | ||
| } | ||
| export function dockerDaemonGuidance(info) { | ||
| switch (info.platform) { | ||
| case 'macos': | ||
| case 'windows': | ||
| return 'Docker is installed but the daemon is not running. Open the Docker Desktop application and wait for it to finish starting.'; | ||
| case 'wsl': | ||
| return 'Docker is installed but the daemon is not reachable. Start Docker Desktop on Windows and make sure WSL integration is enabled for this distro.'; | ||
| case 'linux': | ||
| return 'Docker is installed but the daemon is not running. Start it with `sudo systemctl start docker` (and `sudo systemctl enable docker` to start on boot). If you get a permission error, add your user to the docker group: `sudo usermod -aG docker $USER` and re-login.'; | ||
| default: | ||
| return 'Docker is installed but the daemon is not reachable. Start the Docker daemon and try again.'; | ||
| } | ||
| } | ||
| export function psqlInstallGuidance(info) { | ||
| switch (info.platform) { | ||
| case 'macos': | ||
| return 'Install the PostgreSQL client via Homebrew: `brew install libpq && brew link --force libpq`'; | ||
| case 'windows': | ||
| return 'Install the PostgreSQL client tools: `winget install PostgreSQL.PostgreSQL` or download from https://www.postgresql.org/download/windows/'; | ||
| case 'wsl': | ||
| case 'linux': | ||
| if (isRhelLike(info.distro)) { | ||
| return 'Install the PostgreSQL client: `sudo dnf install postgresql`'; | ||
| } | ||
| return 'Install the PostgreSQL client: `sudo apt-get install postgresql-client`'; | ||
| default: | ||
| return 'Install the PostgreSQL client tools (psql): https://www.postgresql.org/download/'; | ||
| } | ||
| } | ||
| export async function checkDockerBinary(exec = runCommand) { | ||
| const result = await exec('docker', ['--version']); | ||
| return result.code === 0; | ||
| } | ||
| export async function checkDockerDaemon(exec = runCommand) { | ||
| const result = await exec('docker', ['info']); | ||
| return result.code === 0; | ||
| } | ||
| export async function getDockerStatus(exec = runCommand) { | ||
| const binary = await checkDockerBinary(exec); | ||
| if (!binary) { | ||
| return { binary: false, daemon: false }; | ||
| } | ||
| const daemon = await checkDockerDaemon(exec); | ||
| return { binary, daemon }; | ||
| } | ||
| export async function checkDocker(info, exec = runCommand) { | ||
| const status = await getDockerStatus(exec); | ||
| if (!status.binary) { | ||
| return { | ||
| name: 'docker', | ||
| status: 'fail', | ||
| message: 'docker is not installed or not on PATH', | ||
| remediation: dockerInstallGuidance(info) | ||
| }; | ||
| } | ||
| if (!status.daemon) { | ||
| return { | ||
| name: 'docker', | ||
| status: 'fail', | ||
| message: 'docker is installed but the daemon is not reachable', | ||
| remediation: dockerDaemonGuidance(info) | ||
| }; | ||
| } | ||
| return { | ||
| name: 'docker', | ||
| status: 'pass', | ||
| message: 'docker is installed and the daemon is running' | ||
| }; | ||
| } | ||
| export async function checkDockerCompose(info, exec = runCommand) { | ||
| const plugin = await exec('docker', ['compose', 'version']); | ||
| if (plugin.code === 0) { | ||
| return { | ||
| name: 'docker-compose', | ||
| status: 'pass', | ||
| message: 'docker compose plugin is available' | ||
| }; | ||
| } | ||
| const standalone = await exec('docker-compose', ['--version']); | ||
| if (standalone.code === 0) { | ||
| return { | ||
| name: 'docker-compose', | ||
| status: 'pass', | ||
| message: 'docker-compose (standalone) is available' | ||
| }; | ||
| } | ||
| return { | ||
| name: 'docker-compose', | ||
| status: 'warn', | ||
| message: 'docker compose is not available (only needed for docker-compose based workflows)', | ||
| remediation: info.platform === 'linux' || info.platform === 'wsl' | ||
| ? 'Install the compose plugin: https://docs.docker.com/compose/install/linux/' | ||
| : 'Docker Desktop ships with compose; install or update Docker Desktop: https://www.docker.com/products/docker-desktop/' | ||
| }; | ||
| } | ||
| export const MIN_PSQL_MAJOR = 17; | ||
| export function parsePsqlMajor(versionOutput) { | ||
| const match = versionOutput.match(/\(PostgreSQL\)\s+(\d+)/) || versionOutput.match(/psql[^\d]*(\d+)/); | ||
| if (!match) | ||
| return null; | ||
| const major = parseInt(match[1], 10); | ||
| return Number.isNaN(major) ? null : major; | ||
| } | ||
| export async function checkPsql(info, exec = runCommand) { | ||
| const result = await exec('psql', ['--version']); | ||
| if (result.code !== 0) { | ||
| return { | ||
| name: 'psql', | ||
| status: 'fail', | ||
| message: 'psql (PostgreSQL client) is not installed or not on PATH', | ||
| remediation: psqlInstallGuidance(info) | ||
| }; | ||
| } | ||
| const major = parsePsqlMajor(result.stdout); | ||
| if (major === null) { | ||
| return { | ||
| name: 'psql', | ||
| status: 'warn', | ||
| message: `could not determine psql version from: ${result.stdout}` | ||
| }; | ||
| } | ||
| if (major < MIN_PSQL_MAJOR) { | ||
| return { | ||
| name: 'psql', | ||
| status: 'warn', | ||
| message: `psql ${major} found; PostgreSQL ${MIN_PSQL_MAJOR}+ client is recommended`, | ||
| remediation: psqlInstallGuidance(info) | ||
| }; | ||
| } | ||
| return { | ||
| name: 'psql', | ||
| status: 'pass', | ||
| message: `psql ${major} is installed` | ||
| }; | ||
| } | ||
| export const MIN_NODE_MAJOR = 18; | ||
| export const RECOMMENDED_NODE_MAJOR = 20; | ||
| export function checkNode(version = process.version) { | ||
| const major = parseInt(version.replace(/^v/, '').split('.')[0], 10); | ||
| if (Number.isNaN(major)) { | ||
| return { name: 'node', status: 'warn', message: `could not parse Node.js version: ${version}` }; | ||
| } | ||
| if (major < MIN_NODE_MAJOR) { | ||
| return { | ||
| name: 'node', | ||
| status: 'fail', | ||
| message: `Node.js ${version} is not supported; Node.js ${MIN_NODE_MAJOR}+ is required`, | ||
| remediation: 'Upgrade Node.js (e.g. via nvm: `nvm install --lts`): https://nodejs.org/' | ||
| }; | ||
| } | ||
| if (major < RECOMMENDED_NODE_MAJOR) { | ||
| return { | ||
| name: 'node', | ||
| status: 'warn', | ||
| message: `Node.js ${version} works but ${RECOMMENDED_NODE_MAJOR}+ is recommended`, | ||
| remediation: 'Upgrade Node.js (e.g. via nvm: `nvm install --lts`): https://nodejs.org/' | ||
| }; | ||
| } | ||
| return { name: 'node', status: 'pass', message: `Node.js ${version} is installed` }; | ||
| } | ||
| export function summarizeChecks(results) { | ||
| return { | ||
| failed: results.filter((r) => r.status === 'fail').length, | ||
| warned: results.filter((r) => r.status === 'warn').length, | ||
| passed: results.filter((r) => r.status === 'pass').length | ||
| }; | ||
| } |
| export type Platform = 'macos' | 'linux' | 'wsl' | 'windows' | 'unknown'; | ||
| export interface PlatformInfo { | ||
| platform: Platform; | ||
| distro?: string; | ||
| } | ||
| export interface ExecResult { | ||
| code: number; | ||
| stdout: string; | ||
| stderr: string; | ||
| } | ||
| export type CommandRunner = (command: string, args: string[]) => Promise<ExecResult>; | ||
| export type CheckStatus = 'pass' | 'warn' | 'fail'; | ||
| export interface CheckResult { | ||
| name: string; | ||
| status: CheckStatus; | ||
| message: string; | ||
| remediation?: string; | ||
| } | ||
| export declare const runCommand: CommandRunner; | ||
| export declare function detectPlatform(platform?: NodeJS.Platform, readFile?: (path: string) => string): PlatformInfo; | ||
| export declare function dockerInstallGuidance(info: PlatformInfo): string; | ||
| export declare function dockerDaemonGuidance(info: PlatformInfo): string; | ||
| export declare function psqlInstallGuidance(info: PlatformInfo): string; | ||
| export declare function checkDockerBinary(exec?: CommandRunner): Promise<boolean>; | ||
| export declare function checkDockerDaemon(exec?: CommandRunner): Promise<boolean>; | ||
| export interface DockerStatus { | ||
| binary: boolean; | ||
| daemon: boolean; | ||
| } | ||
| export declare function getDockerStatus(exec?: CommandRunner): Promise<DockerStatus>; | ||
| export declare function checkDocker(info: PlatformInfo, exec?: CommandRunner): Promise<CheckResult>; | ||
| export declare function checkDockerCompose(info: PlatformInfo, exec?: CommandRunner): Promise<CheckResult>; | ||
| export declare const MIN_PSQL_MAJOR = 17; | ||
| export declare function parsePsqlMajor(versionOutput: string): number | null; | ||
| export declare function checkPsql(info: PlatformInfo, exec?: CommandRunner): Promise<CheckResult>; | ||
| export declare const MIN_NODE_MAJOR = 18; | ||
| export declare const RECOMMENDED_NODE_MAJOR = 20; | ||
| export declare function checkNode(version?: string): CheckResult; | ||
| export declare function summarizeChecks(results: CheckResult[]): { | ||
| failed: number; | ||
| warned: number; | ||
| passed: number; | ||
| }; |
+265
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.RECOMMENDED_NODE_MAJOR = exports.MIN_NODE_MAJOR = exports.MIN_PSQL_MAJOR = exports.runCommand = void 0; | ||
| exports.detectPlatform = detectPlatform; | ||
| exports.dockerInstallGuidance = dockerInstallGuidance; | ||
| exports.dockerDaemonGuidance = dockerDaemonGuidance; | ||
| exports.psqlInstallGuidance = psqlInstallGuidance; | ||
| exports.checkDockerBinary = checkDockerBinary; | ||
| exports.checkDockerDaemon = checkDockerDaemon; | ||
| exports.getDockerStatus = getDockerStatus; | ||
| exports.checkDocker = checkDocker; | ||
| exports.checkDockerCompose = checkDockerCompose; | ||
| exports.parsePsqlMajor = parsePsqlMajor; | ||
| exports.checkPsql = checkPsql; | ||
| exports.checkNode = checkNode; | ||
| exports.summarizeChecks = summarizeChecks; | ||
| const child_process_1 = require("child_process"); | ||
| const fs_1 = require("fs"); | ||
| const runCommand = (command, args) => { | ||
| return new Promise((resolve) => { | ||
| const child = (0, child_process_1.spawn)(command, args, { stdio: 'pipe' }); | ||
| let stdout = ''; | ||
| let stderr = ''; | ||
| child.stdout?.on('data', (data) => { | ||
| stdout += data.toString(); | ||
| }); | ||
| child.stderr?.on('data', (data) => { | ||
| stderr += data.toString(); | ||
| }); | ||
| child.on('error', () => { | ||
| resolve({ code: 127, stdout: '', stderr: `${command}: command not found` }); | ||
| }); | ||
| child.on('close', (code) => { | ||
| resolve({ code: code ?? 0, stdout: stdout.trim(), stderr: stderr.trim() }); | ||
| }); | ||
| }); | ||
| }; | ||
| exports.runCommand = runCommand; | ||
| function detectPlatform(platform = process.platform, readFile = (p) => (0, fs_1.readFileSync)(p, 'utf-8')) { | ||
| if (platform === 'darwin') { | ||
| return { platform: 'macos' }; | ||
| } | ||
| if (platform === 'win32') { | ||
| return { platform: 'windows' }; | ||
| } | ||
| if (platform === 'linux') { | ||
| let distro; | ||
| try { | ||
| const release = readFile('/etc/os-release'); | ||
| const match = release.match(/^ID=("?)([^"\n]*)\1$/m); | ||
| if (match) { | ||
| distro = match[2]; | ||
| } | ||
| } | ||
| catch { | ||
| // ignore | ||
| } | ||
| try { | ||
| const version = readFile('/proc/version'); | ||
| if (/microsoft/i.test(version)) { | ||
| return { platform: 'wsl', distro }; | ||
| } | ||
| } | ||
| catch { | ||
| // ignore | ||
| } | ||
| return { platform: 'linux', distro }; | ||
| } | ||
| return { platform: 'unknown' }; | ||
| } | ||
| const DEBIAN_LIKE = ['ubuntu', 'debian', 'pop', 'linuxmint', 'elementary']; | ||
| const RHEL_LIKE = ['fedora', 'rhel', 'centos', 'rocky', 'almalinux', 'amzn']; | ||
| function isDebianLike(distro) { | ||
| return !!distro && DEBIAN_LIKE.includes(distro); | ||
| } | ||
| function isRhelLike(distro) { | ||
| return !!distro && RHEL_LIKE.includes(distro); | ||
| } | ||
| function dockerInstallGuidance(info) { | ||
| switch (info.platform) { | ||
| case 'macos': | ||
| return 'Install Docker Desktop for Mac: https://www.docker.com/products/docker-desktop/ (or `brew install --cask docker`)'; | ||
| case 'windows': | ||
| return 'Install Docker Desktop for Windows: https://www.docker.com/products/docker-desktop/'; | ||
| case 'wsl': | ||
| return 'Install Docker Desktop for Windows with the WSL 2 backend enabled: https://docs.docker.com/desktop/wsl/'; | ||
| case 'linux': | ||
| if (isDebianLike(info.distro)) { | ||
| return 'Install Docker Engine: https://docs.docker.com/engine/install/ubuntu/ (e.g. `sudo apt-get install docker.io` or the official docker-ce packages)'; | ||
| } | ||
| if (isRhelLike(info.distro)) { | ||
| return 'Install Docker Engine: https://docs.docker.com/engine/install/fedora/ (e.g. `sudo dnf install docker-ce`)'; | ||
| } | ||
| return 'Install Docker Engine for your distribution: https://docs.docker.com/engine/install/'; | ||
| default: | ||
| return 'Install Docker: https://docs.docker.com/get-docker/'; | ||
| } | ||
| } | ||
| function dockerDaemonGuidance(info) { | ||
| switch (info.platform) { | ||
| case 'macos': | ||
| case 'windows': | ||
| return 'Docker is installed but the daemon is not running. Open the Docker Desktop application and wait for it to finish starting.'; | ||
| case 'wsl': | ||
| return 'Docker is installed but the daemon is not reachable. Start Docker Desktop on Windows and make sure WSL integration is enabled for this distro.'; | ||
| case 'linux': | ||
| return 'Docker is installed but the daemon is not running. Start it with `sudo systemctl start docker` (and `sudo systemctl enable docker` to start on boot). If you get a permission error, add your user to the docker group: `sudo usermod -aG docker $USER` and re-login.'; | ||
| default: | ||
| return 'Docker is installed but the daemon is not reachable. Start the Docker daemon and try again.'; | ||
| } | ||
| } | ||
| function psqlInstallGuidance(info) { | ||
| switch (info.platform) { | ||
| case 'macos': | ||
| return 'Install the PostgreSQL client via Homebrew: `brew install libpq && brew link --force libpq`'; | ||
| case 'windows': | ||
| return 'Install the PostgreSQL client tools: `winget install PostgreSQL.PostgreSQL` or download from https://www.postgresql.org/download/windows/'; | ||
| case 'wsl': | ||
| case 'linux': | ||
| if (isRhelLike(info.distro)) { | ||
| return 'Install the PostgreSQL client: `sudo dnf install postgresql`'; | ||
| } | ||
| return 'Install the PostgreSQL client: `sudo apt-get install postgresql-client`'; | ||
| default: | ||
| return 'Install the PostgreSQL client tools (psql): https://www.postgresql.org/download/'; | ||
| } | ||
| } | ||
| async function checkDockerBinary(exec = exports.runCommand) { | ||
| const result = await exec('docker', ['--version']); | ||
| return result.code === 0; | ||
| } | ||
| async function checkDockerDaemon(exec = exports.runCommand) { | ||
| const result = await exec('docker', ['info']); | ||
| return result.code === 0; | ||
| } | ||
| async function getDockerStatus(exec = exports.runCommand) { | ||
| const binary = await checkDockerBinary(exec); | ||
| if (!binary) { | ||
| return { binary: false, daemon: false }; | ||
| } | ||
| const daemon = await checkDockerDaemon(exec); | ||
| return { binary, daemon }; | ||
| } | ||
| async function checkDocker(info, exec = exports.runCommand) { | ||
| const status = await getDockerStatus(exec); | ||
| if (!status.binary) { | ||
| return { | ||
| name: 'docker', | ||
| status: 'fail', | ||
| message: 'docker is not installed or not on PATH', | ||
| remediation: dockerInstallGuidance(info) | ||
| }; | ||
| } | ||
| if (!status.daemon) { | ||
| return { | ||
| name: 'docker', | ||
| status: 'fail', | ||
| message: 'docker is installed but the daemon is not reachable', | ||
| remediation: dockerDaemonGuidance(info) | ||
| }; | ||
| } | ||
| return { | ||
| name: 'docker', | ||
| status: 'pass', | ||
| message: 'docker is installed and the daemon is running' | ||
| }; | ||
| } | ||
| async function checkDockerCompose(info, exec = exports.runCommand) { | ||
| const plugin = await exec('docker', ['compose', 'version']); | ||
| if (plugin.code === 0) { | ||
| return { | ||
| name: 'docker-compose', | ||
| status: 'pass', | ||
| message: 'docker compose plugin is available' | ||
| }; | ||
| } | ||
| const standalone = await exec('docker-compose', ['--version']); | ||
| if (standalone.code === 0) { | ||
| return { | ||
| name: 'docker-compose', | ||
| status: 'pass', | ||
| message: 'docker-compose (standalone) is available' | ||
| }; | ||
| } | ||
| return { | ||
| name: 'docker-compose', | ||
| status: 'warn', | ||
| message: 'docker compose is not available (only needed for docker-compose based workflows)', | ||
| remediation: info.platform === 'linux' || info.platform === 'wsl' | ||
| ? 'Install the compose plugin: https://docs.docker.com/compose/install/linux/' | ||
| : 'Docker Desktop ships with compose; install or update Docker Desktop: https://www.docker.com/products/docker-desktop/' | ||
| }; | ||
| } | ||
| exports.MIN_PSQL_MAJOR = 17; | ||
| function parsePsqlMajor(versionOutput) { | ||
| const match = versionOutput.match(/\(PostgreSQL\)\s+(\d+)/) || versionOutput.match(/psql[^\d]*(\d+)/); | ||
| if (!match) | ||
| return null; | ||
| const major = parseInt(match[1], 10); | ||
| return Number.isNaN(major) ? null : major; | ||
| } | ||
| async function checkPsql(info, exec = exports.runCommand) { | ||
| const result = await exec('psql', ['--version']); | ||
| if (result.code !== 0) { | ||
| return { | ||
| name: 'psql', | ||
| status: 'fail', | ||
| message: 'psql (PostgreSQL client) is not installed or not on PATH', | ||
| remediation: psqlInstallGuidance(info) | ||
| }; | ||
| } | ||
| const major = parsePsqlMajor(result.stdout); | ||
| if (major === null) { | ||
| return { | ||
| name: 'psql', | ||
| status: 'warn', | ||
| message: `could not determine psql version from: ${result.stdout}` | ||
| }; | ||
| } | ||
| if (major < exports.MIN_PSQL_MAJOR) { | ||
| return { | ||
| name: 'psql', | ||
| status: 'warn', | ||
| message: `psql ${major} found; PostgreSQL ${exports.MIN_PSQL_MAJOR}+ client is recommended`, | ||
| remediation: psqlInstallGuidance(info) | ||
| }; | ||
| } | ||
| return { | ||
| name: 'psql', | ||
| status: 'pass', | ||
| message: `psql ${major} is installed` | ||
| }; | ||
| } | ||
| exports.MIN_NODE_MAJOR = 18; | ||
| exports.RECOMMENDED_NODE_MAJOR = 20; | ||
| function checkNode(version = process.version) { | ||
| const major = parseInt(version.replace(/^v/, '').split('.')[0], 10); | ||
| if (Number.isNaN(major)) { | ||
| return { name: 'node', status: 'warn', message: `could not parse Node.js version: ${version}` }; | ||
| } | ||
| if (major < exports.MIN_NODE_MAJOR) { | ||
| return { | ||
| name: 'node', | ||
| status: 'fail', | ||
| message: `Node.js ${version} is not supported; Node.js ${exports.MIN_NODE_MAJOR}+ is required`, | ||
| remediation: 'Upgrade Node.js (e.g. via nvm: `nvm install --lts`): https://nodejs.org/' | ||
| }; | ||
| } | ||
| if (major < exports.RECOMMENDED_NODE_MAJOR) { | ||
| return { | ||
| name: 'node', | ||
| status: 'warn', | ||
| message: `Node.js ${version} works but ${exports.RECOMMENDED_NODE_MAJOR}+ is recommended`, | ||
| remediation: 'Upgrade Node.js (e.g. via nvm: `nvm install --lts`): https://nodejs.org/' | ||
| }; | ||
| } | ||
| return { name: 'node', status: 'pass', message: `Node.js ${version} is installed` }; | ||
| } | ||
| function summarizeChecks(results) { | ||
| return { | ||
| failed: results.filter((r) => r.status === 'fail').length, | ||
| warned: results.filter((r) => r.status === 'warn').length, | ||
| passed: results.filter((r) => r.status === 'pass').length | ||
| }; | ||
| } |
+5
-3
@@ -17,2 +17,3 @@ "use strict"; | ||
| const docker_1 = __importDefault(require("./commands/docker")); | ||
| const doctor_1 = __importDefault(require("./commands/doctor")); | ||
| const dump_1 = __importDefault(require("./commands/dump")); | ||
@@ -28,4 +29,2 @@ const env_1 = __importDefault(require("./commands/env")); | ||
| const plan_1 = __importDefault(require("./commands/plan")); | ||
| const update_1 = __importDefault(require("./commands/update")); | ||
| const upgrade_1 = __importDefault(require("./commands/upgrade")); | ||
| const remove_1 = __importDefault(require("./commands/remove")); | ||
@@ -38,2 +37,4 @@ const rename_1 = __importDefault(require("./commands/rename")); | ||
| const tune_1 = __importDefault(require("./commands/tune")); | ||
| const update_1 = __importDefault(require("./commands/update")); | ||
| const upgrade_1 = __importDefault(require("./commands/upgrade")); | ||
| const verify_1 = __importDefault(require("./commands/verify")); | ||
@@ -59,2 +60,3 @@ const utils_2 = require("./utils"); | ||
| docker: docker_1.default, | ||
| doctor: doctor_1.default, | ||
| dump: pgt(dump_1.default), | ||
@@ -121,3 +123,3 @@ env: env_1.default, | ||
| pkgVersion: pkg.version, | ||
| toolName: 'pgpm', | ||
| toolName: 'pgpm' | ||
| }); | ||
@@ -124,0 +126,0 @@ if (updateResult.hasUpdate && updateResult.message) { |
+23
-20
@@ -5,2 +5,3 @@ "use strict"; | ||
| const inquirerer_1 = require("inquirerer"); | ||
| const doctor_1 = require("../utils/doctor"); | ||
| const dockerUsageText = ` | ||
@@ -56,10 +57,10 @@ Docker Command: | ||
| { host: 9000, container: 9000 }, | ||
| { host: 9001, container: 9001 }, | ||
| { host: 9001, container: 9001 } | ||
| ], | ||
| env: { | ||
| MINIO_ROOT_USER: 'minioadmin', | ||
| MINIO_ROOT_PASSWORD: 'minioadmin', | ||
| MINIO_ROOT_PASSWORD: 'minioadmin' | ||
| }, | ||
| command: ['server', '/data', '--console-address', ':9001'], | ||
| volumes: [{ name: 'minio-data', containerPath: '/data' }], | ||
| volumes: [{ name: 'minio-data', containerPath: '/data' }] | ||
| }, | ||
@@ -70,8 +71,8 @@ ollama: { | ||
| ports: [ | ||
| { host: 11434, container: 11434 }, | ||
| { host: 11434, container: 11434 } | ||
| ], | ||
| env: {}, | ||
| volumes: [{ name: 'ollama-data', containerPath: '/root/.ollama' }], | ||
| gpuCapable: true, | ||
| }, | ||
| gpuCapable: true | ||
| } | ||
| }; | ||
@@ -104,10 +105,15 @@ function run(command, args, options = {}) { | ||
| } | ||
| async function checkDockerAvailable() { | ||
| try { | ||
| const result = await run('docker', ['--version']); | ||
| return result.code === 0; | ||
| async function ensureDockerReady() { | ||
| const status = await (0, doctor_1.getDockerStatus)(); | ||
| if (status.binary && status.daemon) { | ||
| return true; | ||
| } | ||
| catch (error) { | ||
| return false; | ||
| const platformInfo = (0, doctor_1.detectPlatform)(); | ||
| if (!status.binary) { | ||
| await (0, inquirerer_1.cliExitWithError)(`Docker is not installed or not available in PATH.\n${(0, doctor_1.dockerInstallGuidance)(platformInfo)}`); | ||
| } | ||
| else { | ||
| await (0, inquirerer_1.cliExitWithError)((0, doctor_1.dockerDaemonGuidance)(platformInfo)); | ||
| } | ||
| return false; | ||
| } | ||
@@ -137,5 +143,3 @@ async function isContainerRunning(name) { | ||
| const { name, image, port, user, password, shmSize, recreate } = options; | ||
| const dockerAvailable = await checkDockerAvailable(); | ||
| if (!dockerAvailable) { | ||
| await (0, inquirerer_1.cliExitWithError)('Docker is not installed or not available in PATH. Please install Docker first.'); | ||
| if (!(await ensureDockerReady())) { | ||
| return; | ||
@@ -191,5 +195,3 @@ } | ||
| async function stopContainer(name) { | ||
| const dockerAvailable = await checkDockerAvailable(); | ||
| if (!dockerAvailable) { | ||
| await (0, inquirerer_1.cliExitWithError)('Docker is not installed or not available in PATH. Please install Docker first.'); | ||
| if (!(await ensureDockerReady())) { | ||
| return; | ||
@@ -247,3 +249,3 @@ } | ||
| '-d', | ||
| '--name', name, | ||
| '--name', name | ||
| ]; | ||
@@ -292,3 +294,4 @@ for (const [key, value] of Object.entries(serviceEnv)) { | ||
| async function listServices() { | ||
| const dockerAvailable = await checkDockerAvailable(); | ||
| const dockerStatus = await (0, doctor_1.getDockerStatus)(); | ||
| const dockerAvailable = dockerStatus.binary && dockerStatus.daemon; | ||
| console.log('\nAvailable services:\n'); | ||
@@ -295,0 +298,0 @@ console.log(' Primary:'); |
+5
-3
@@ -11,2 +11,3 @@ import { checkForUpdates } from '@inquirerer/utils'; | ||
| import docker from './commands/docker'; | ||
| import doctor from './commands/doctor'; | ||
| import dump from './commands/dump'; | ||
@@ -22,4 +23,2 @@ import env from './commands/env'; | ||
| import plan from './commands/plan'; | ||
| import updateCmd from './commands/update'; | ||
| import upgrade from './commands/upgrade'; | ||
| import remove from './commands/remove'; | ||
@@ -32,2 +31,4 @@ import renameCmd from './commands/rename'; | ||
| import tune from './commands/tune'; | ||
| import updateCmd from './commands/update'; | ||
| import upgrade from './commands/upgrade'; | ||
| import verify from './commands/verify'; | ||
@@ -53,2 +54,3 @@ import { usageText } from './utils'; | ||
| docker, | ||
| doctor, | ||
| dump: pgt(dump), | ||
@@ -114,3 +116,3 @@ env, | ||
| pkgVersion: pkg.version, | ||
| toolName: 'pgpm', | ||
| toolName: 'pgpm' | ||
| }); | ||
@@ -117,0 +119,0 @@ if (updateResult.hasUpdate && updateResult.message) { |
+23
-20
| import { spawn } from 'child_process'; | ||
| import { cliExitWithError, extractFirst } from 'inquirerer'; | ||
| import { detectPlatform, dockerDaemonGuidance, dockerInstallGuidance, getDockerStatus } from '../utils/doctor'; | ||
| const dockerUsageText = ` | ||
@@ -53,10 +54,10 @@ Docker Command: | ||
| { host: 9000, container: 9000 }, | ||
| { host: 9001, container: 9001 }, | ||
| { host: 9001, container: 9001 } | ||
| ], | ||
| env: { | ||
| MINIO_ROOT_USER: 'minioadmin', | ||
| MINIO_ROOT_PASSWORD: 'minioadmin', | ||
| MINIO_ROOT_PASSWORD: 'minioadmin' | ||
| }, | ||
| command: ['server', '/data', '--console-address', ':9001'], | ||
| volumes: [{ name: 'minio-data', containerPath: '/data' }], | ||
| volumes: [{ name: 'minio-data', containerPath: '/data' }] | ||
| }, | ||
@@ -67,8 +68,8 @@ ollama: { | ||
| ports: [ | ||
| { host: 11434, container: 11434 }, | ||
| { host: 11434, container: 11434 } | ||
| ], | ||
| env: {}, | ||
| volumes: [{ name: 'ollama-data', containerPath: '/root/.ollama' }], | ||
| gpuCapable: true, | ||
| }, | ||
| gpuCapable: true | ||
| } | ||
| }; | ||
@@ -101,10 +102,15 @@ function run(command, args, options = {}) { | ||
| } | ||
| async function checkDockerAvailable() { | ||
| try { | ||
| const result = await run('docker', ['--version']); | ||
| return result.code === 0; | ||
| async function ensureDockerReady() { | ||
| const status = await getDockerStatus(); | ||
| if (status.binary && status.daemon) { | ||
| return true; | ||
| } | ||
| catch (error) { | ||
| return false; | ||
| const platformInfo = detectPlatform(); | ||
| if (!status.binary) { | ||
| await cliExitWithError(`Docker is not installed or not available in PATH.\n${dockerInstallGuidance(platformInfo)}`); | ||
| } | ||
| else { | ||
| await cliExitWithError(dockerDaemonGuidance(platformInfo)); | ||
| } | ||
| return false; | ||
| } | ||
@@ -134,5 +140,3 @@ async function isContainerRunning(name) { | ||
| const { name, image, port, user, password, shmSize, recreate } = options; | ||
| const dockerAvailable = await checkDockerAvailable(); | ||
| if (!dockerAvailable) { | ||
| await cliExitWithError('Docker is not installed or not available in PATH. Please install Docker first.'); | ||
| if (!(await ensureDockerReady())) { | ||
| return; | ||
@@ -188,5 +192,3 @@ } | ||
| async function stopContainer(name) { | ||
| const dockerAvailable = await checkDockerAvailable(); | ||
| if (!dockerAvailable) { | ||
| await cliExitWithError('Docker is not installed or not available in PATH. Please install Docker first.'); | ||
| if (!(await ensureDockerReady())) { | ||
| return; | ||
@@ -244,3 +246,3 @@ } | ||
| '-d', | ||
| '--name', name, | ||
| '--name', name | ||
| ]; | ||
@@ -289,3 +291,4 @@ for (const [key, value] of Object.entries(serviceEnv)) { | ||
| async function listServices() { | ||
| const dockerAvailable = await checkDockerAvailable(); | ||
| const dockerStatus = await getDockerStatus(); | ||
| const dockerAvailable = dockerStatus.binary && dockerStatus.daemon; | ||
| console.log('\nAvailable services:\n'); | ||
@@ -292,0 +295,0 @@ console.log(' Primary:'); |
@@ -44,2 +44,3 @@ export const usageText = ` | ||
| docker Manage Docker containers (start/stop/ls, --minio) | ||
| doctor Check local dependencies (node, docker, psql) with install guidance | ||
| env Manage environment variables (--supabase, --minio) | ||
@@ -46,0 +47,0 @@ test-packages Run integration tests on workspace packages |
| export * from './database'; | ||
| export * from './deployed-changes'; | ||
| export * from './display'; | ||
| export * from './doctor'; | ||
| export * from './driver'; | ||
| export * from './display'; | ||
| export * from './deployed-changes'; | ||
| export * from './module-utils'; | ||
| export * from './npm-version'; | ||
| export * from './package-alias'; |
+3
-3
| { | ||
| "name": "pgpm", | ||
| "version": "5.2.3", | ||
| "version": "5.3.0", | ||
| "author": "Constructive <developers@constructive.io>", | ||
@@ -51,3 +51,3 @@ "description": "PostgreSQL Package Manager - Database migration and package management CLI", | ||
| "@pgpmjs/env": "^2.30.2", | ||
| "@pgpmjs/export": "^1.4.0", | ||
| "@pgpmjs/export": "^1.5.0", | ||
| "@pgpmjs/logger": "^2.15.2", | ||
@@ -80,3 +80,3 @@ "@pgpmjs/types": "^2.37.2", | ||
| ], | ||
| "gitHead": "0e3ee42c44c9b35ffac4bf1faa6775eb69311ec4" | ||
| "gitHead": "518e7ab2270661c64875258436d90fdf76b4b336" | ||
| } |
@@ -1,1 +0,1 @@ | ||
| export declare const usageText = "\n Usage: pgpm <command> [options]\n\n Core Database Operations:\n add Add database changes to plans and create SQL files\n deploy Deploy database changes and migrations\n verify Verify database state and migrations\n revert Revert database changes and migrations\n\n Project Management:\n init Initialize workspace or module\n extension Manage module dependencies\n plan Generate module deployment plans\n package Package module for distribution\n export Export database migrations from existing databases\n update Update pgpm to the latest version\n cache Manage cached templates (clean)\n upgrade Upgrade installed pgpm modules to latest versions (alias: up)\n\n Database Administration:\n dump Dump a database to a sql file\n kill Terminate database connections and optionally drop databases\n install Install database modules\n tag Add tags to changes for versioning\n clear Clear database state\n remove Remove database changes\n analyze Analyze database structure\n rename Rename database changes\n admin-users Manage admin users\n tune Tune PostgreSQL for throwaway environments (CI/test)\n\n Testing:\n test-packages Run integration tests on all workspace packages\n\n Migration Tools:\n migrate Migration management subcommands\n init Initialize migration tracking\n status Show migration status\n list List all changes\n deps Show change dependencies\n \n Development Tools:\n docker Manage Docker containers (start/stop/ls, --minio)\n env Manage environment variables (--supabase, --minio)\n test-packages Run integration tests on workspace packages\n \n Global Options:\n -h, --help Display this help information\n -v, --version Display version information\n --cwd <directory> Working directory (default: current directory)\n\n Individual Command Help:\n pgpm <command> --help Display detailed help for specific command\n pgpm <command> -h Display detailed help for specific command\n\n Examples:\n pgpm deploy --help Show deploy command options\n pgpm init workspace Initialize new workspace\n pgpm install @pgpm/base32 Install a database module\n "; | ||
| export declare const usageText = "\n Usage: pgpm <command> [options]\n\n Core Database Operations:\n add Add database changes to plans and create SQL files\n deploy Deploy database changes and migrations\n verify Verify database state and migrations\n revert Revert database changes and migrations\n\n Project Management:\n init Initialize workspace or module\n extension Manage module dependencies\n plan Generate module deployment plans\n package Package module for distribution\n export Export database migrations from existing databases\n update Update pgpm to the latest version\n cache Manage cached templates (clean)\n upgrade Upgrade installed pgpm modules to latest versions (alias: up)\n\n Database Administration:\n dump Dump a database to a sql file\n kill Terminate database connections and optionally drop databases\n install Install database modules\n tag Add tags to changes for versioning\n clear Clear database state\n remove Remove database changes\n analyze Analyze database structure\n rename Rename database changes\n admin-users Manage admin users\n tune Tune PostgreSQL for throwaway environments (CI/test)\n\n Testing:\n test-packages Run integration tests on all workspace packages\n\n Migration Tools:\n migrate Migration management subcommands\n init Initialize migration tracking\n status Show migration status\n list List all changes\n deps Show change dependencies\n \n Development Tools:\n docker Manage Docker containers (start/stop/ls, --minio)\n doctor Check local dependencies (node, docker, psql) with install guidance\n env Manage environment variables (--supabase, --minio)\n test-packages Run integration tests on workspace packages\n \n Global Options:\n -h, --help Display this help information\n -v, --version Display version information\n --cwd <directory> Working directory (default: current directory)\n\n Individual Command Help:\n pgpm <command> --help Display detailed help for specific command\n pgpm <command> -h Display detailed help for specific command\n\n Examples:\n pgpm deploy --help Show deploy command options\n pgpm init workspace Initialize new workspace\n pgpm install @pgpm/base32 Install a database module\n "; |
+1
-0
@@ -47,2 +47,3 @@ "use strict"; | ||
| docker Manage Docker containers (start/stop/ls, --minio) | ||
| doctor Check local dependencies (node, docker, psql) with install guidance | ||
| env Manage environment variables (--supabase, --minio) | ||
@@ -49,0 +50,0 @@ test-packages Run integration tests on workspace packages |
+3
-2
| export * from './database'; | ||
| export * from './deployed-changes'; | ||
| export * from './display'; | ||
| export * from './doctor'; | ||
| export * from './driver'; | ||
| export * from './display'; | ||
| export * from './deployed-changes'; | ||
| export * from './module-utils'; | ||
| export * from './npm-version'; | ||
| export * from './package-alias'; |
+3
-2
@@ -18,7 +18,8 @@ "use strict"; | ||
| __exportStar(require("./database"), exports); | ||
| __exportStar(require("./deployed-changes"), exports); | ||
| __exportStar(require("./display"), exports); | ||
| __exportStar(require("./doctor"), exports); | ||
| __exportStar(require("./driver"), exports); | ||
| __exportStar(require("./display"), exports); | ||
| __exportStar(require("./deployed-changes"), exports); | ||
| __exportStar(require("./module-utils"), exports); | ||
| __exportStar(require("./npm-version"), exports); | ||
| __exportStar(require("./package-alias"), exports); |
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
481434
6.83%147
4.26%11394
7.25%50
4.17%18
28.57%Updated