UNPKG

@devicecloud.dev/dcd

Version:

Better cloud maestro testing

144 lines (143 loc) 6.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@oclif/core"); const constants_1 = require("../constants"); const api_gateway_1 = require("../gateways/api-gateway"); const styling_1 = require("../utils/styling"); class List extends core_1.Command { static description = 'List recent flow uploads for your organization'; static enableJsonFlag = true; static examples = [ '<%= config.bin %> <%= command.id %>', '<%= config.bin %> <%= command.id %> --limit 10', '<%= config.bin %> <%= command.id %> --name "nightly-*" # Quote wildcards to prevent shell expansion!', '<%= config.bin %> <%= command.id %> --from 2024-01-01 --to 2024-01-31', '<%= config.bin %> <%= command.id %> --json', ]; static flags = { apiKey: constants_1.flags.apiKey, apiUrl: constants_1.flags.apiUrl, from: core_1.Flags.string({ description: 'Filter uploads created on or after this date (ISO 8601 format, e.g., 2024-01-01)', }), json: core_1.Flags.boolean({ description: 'Output in JSON format', }), limit: core_1.Flags.integer({ default: 20, description: 'Maximum number of uploads to return', }), name: core_1.Flags.string({ description: 'Filter by upload name (supports * wildcard, e.g., "nightly-*"). IMPORTANT: Always quote wildcards to prevent shell expansion!', }), offset: core_1.Flags.integer({ default: 0, description: 'Number of uploads to skip (for pagination)', }), to: core_1.Flags.string({ description: 'Filter uploads created on or before this date (ISO 8601 format, e.g., 2024-01-31)', }), }; async run() { const { flags } = await this.parse(List); const { apiKey: apiKeyFlag, apiUrl, from, json, limit, name, offset, to, } = flags; const apiKey = apiKeyFlag || process.env.DEVICE_CLOUD_API_KEY; if (!apiKey) { this.error('API key is required. Please provide it via --api-key flag or DEVICE_CLOUD_API_KEY environment variable.'); return; } // Validate date formats if provided if (from && Number.isNaN(Date.parse(from))) { this.error('Invalid --from date format. Please use ISO 8601 format (e.g., 2024-01-01).'); return; } if (to && Number.isNaN(Date.parse(to))) { this.error('Invalid --to date format. Please use ISO 8601 format (e.g., 2024-01-31).'); return; } // Detect potential shell expansion of wildcards if (name) { this.detectShellExpansion(name); } try { const response = await api_gateway_1.ApiGateway.listUploads(apiUrl, apiKey, { from, limit, name, offset, to, }); if (json) { return response; } this.displayResults(response); } catch (error) { this.error(`Failed to list uploads: ${error.message}`); } } /** * Detects if the provided name parameter likely underwent shell expansion * Warns the user if shell expansion is detected * @param name - The name parameter to check for shell expansion * @returns void */ detectShellExpansion(name) { const shellExpansionIndicators = [ // Contains file path separators (likely expanded to file paths) name.includes('/') || name.includes('\\'), // Contains file extensions (likely expanded to filenames) /\.(yaml|yml|json|txt|md|ts|js|py|sh)$/i.test(name), // Looks like multiple space-separated filenames (shell expanded glob to multiple files) name.includes(' ') && !name.includes('*') && !name.includes('?'), ]; if (shellExpansionIndicators.some(Boolean)) { this.warn(`\nThe --name parameter appears to have been expanded by your shell: "${name}"\n` + 'Wildcards like * should be quoted to prevent shell expansion.\n' + 'Examples:\n' + ' ✓ Correct: dcd list --name "nightly-*"\n' + ' ✓ Correct: dcd list --name \'nightly-*\'\n' + ' ✗ Incorrect: dcd list --name nightly-*\n'); } } displayResults(response) { const { uploads, total, limit, offset } = response; if (uploads.length === 0) { this.log('\nNo uploads found matching your criteria.\n'); return; } this.log((0, styling_1.sectionHeader)('Recent Uploads')); this.log(` ${styling_1.colors.dim('Showing')} ${uploads.length} ${styling_1.colors.dim('of')} ${total} ${styling_1.colors.dim('uploads')}`); if (offset > 0) { this.log(` ${styling_1.colors.dim('(offset:')} ${offset}${styling_1.colors.dim(')')}`); } this.log(''); for (const upload of uploads) { const date = new Date(upload.created_at); const formattedDate = date.toLocaleDateString('en-US', { day: 'numeric', hour: '2-digit', minute: '2-digit', month: 'short', year: 'numeric', }); // Upload name const displayName = upload.name || styling_1.colors.dim('(unnamed)'); this.log(` ${styling_1.colors.bold(displayName)}`); // Upload ID and date this.log(` ${styling_1.colors.dim('ID:')} ${(0, styling_1.formatId)(upload.id)}`); this.log(` ${styling_1.colors.dim('Created:')} ${formattedDate}`); // Console URL this.log(` ${styling_1.colors.dim('Console:')} ${(0, styling_1.formatUrl)(upload.consoleUrl)}`); this.log(''); } // Pagination hint if (total > offset + uploads.length) { const remaining = total - (offset + uploads.length); this.log(` ${styling_1.colors.dim('Use')} --offset ${offset + limit} ${styling_1.colors.dim('to see the next')} ${Math.min(remaining, limit)} ${styling_1.colors.dim('uploads')}\n`); } // Hint about getting detailed status this.log(` ${styling_1.colors.dim('Tip: Use')} dcd status --upload-id <id> ${styling_1.colors.dim('for detailed test results')}\n`); } } exports.default = List;