UNPKG

@commercelayer/cli

Version:
223 lines (219 loc) 8.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cli_core_1 = require("@commercelayer/cli-core"); const core_1 = require("@oclif/core"); const node_fs_1 = require("node:fs"); const node_path_1 = require("node:path"); const prettier_1 = require("prettier"); const node_os_1 = require("node:os"); const FIG_SPECS_DIR = `${(0, node_os_1.homedir)()}/Documents/GitHub/fig-autocomplete/src`; const SPEC_NAME = 'commercelayer'; const processedCommands = []; function getFigArgs(args) { const figArgs = []; for (const arg of args) { if (arg.hidden) continue; const figArg = { name: arg.name, ...(arg.description && { description: description(arg.description) }), ...(arg.default && { default: `${arg.default}` }), ...(arg.options?.length && { suggestions: arg.options }), ...(arg.required === false && { isOptional: true }) }; figArgs.push(figArg); } return figArgs; } function getFigOptions(options) { const figOptions = []; for (const flag of options) { const figOption = { name: flag.char ? [`-${flag.char}`, `--${flag.name}`] : `--${flag.name}`, ...(flag.description && { description: description(flag.description) }), ...(flag.type === "option" && { args: { description: description(flag.helpValue), ...(flag.options?.length && { suggestions: flag.options }), ...(flag.default && { default: `${flag.default}` }), }, }), ...(flag.required === true && { isRequired: true }), ...(flag.type === "boolean" && flag.allowNo && { exclusiveOn: [`--no-${flag.name}`] }), hidden: flag.hidden }; figOptions.push(figOption); if (flag.type === "boolean" && flag.allowNo) { figOptions.push({ name: `--no-${flag.name}` }); } } return figOptions; } function description(desc) { if (!desc) return desc; let d = desc; if (Array.isArray(d)) { if (d.length > 0) d = d[0]; else d = ''; } if (d) { if (d.length > 80) { d = d.substring(0, d.indexOf('.') + 1); if (d.length > 80) d = d.substring(0, 80); } if (d.endsWith('...') && (d.charAt(d.indexOf('...') - 1) === '|')) d = d.replace('...', 'etc'); d = cli_core_1.clText.capitalize(d) || ''; if (d.endsWith('.')) d = d.substring(0, d.length - 1); d = d.trim(); } return d; } function getFigSubcommands(commands, hidden = false) { const subcommands = []; for (const command of commands) { // skip... if (['fig', 'cli:fig'].includes(command.id) // this command || processedCommands.includes(command.id) // command aliases || (command.hidden && !hidden)) continue; // hidden commands if no explicitely requested const options = getFigOptions(Object.values(command.flags)); const args = getFigArgs(Object.values(command.args)); const commandNames = [command.id]; if (command.aliases) command.aliases.forEach(a => { if (!commandNames.includes(a)) commandNames.push(a); }); const subCommand = { name: (commandNames.length === 1) ? commandNames[0] : commandNames, ...(command.description && { description: description(command.description) }), ...(options.length && { options }), ...(args.length && { args: (args.length === 1) ? args[0] : args }), hidden: command.hidden }; subcommands.push(subCommand); processedCommands.push(...commandNames); // mark command and its aliases as processed } return subcommands; } const buildSpec = (spec) => { return `/** * Autogenerated by @commercelayer/cli cli:fig command **/ const completionSpec: Fig.Spec = ${JSON.stringify(spec, null, 2)} export default completionSpec `; }; async function classifyResources(resUrl) { const resources = (await (await fetch(resUrl)).json()).data; const classes = { listable: [], retrievable: [], updatable: [], creatable: [], deletable: [] }; resources.filter(res => res.type === 'resources').forEach(res => { if (res.attributes?.actions) { const r = res.id; const actions = res.attributes.actions; if (actions.includes('list')) classes.listable.push(r); if (actions.includes('retrieve')) classes.retrievable.push(r); if (actions.includes('update')) classes.updatable.push(r); if (actions.includes('create')) classes.creatable.push(r); if (actions.includes('delete')) classes.deletable.push(r); } }); return classes; } function setCmdArgSuggestions(spec, cmd, res, suggestions) { const args = spec.subcommands?.find(res => res.name.includes(cmd))?.args; if (args) { const arg = Array.isArray(args) ? args.find(a => a.name === res) : args; if (arg) arg.suggestions = suggestions; } return spec; } async function enhanceSpec(spec) { let classes; // CORE classes = await classifyResources('https://core.commercelayer.io/api/public/resources'); setCmdArgSuggestions(spec, 'resources:list', 'resource', classes.listable.map(r => cli_core_1.clText.pluralize(r))); setCmdArgSuggestions(spec, 'resources:retrieve', 'resource', classes.retrievable); setCmdArgSuggestions(spec, 'resources:update', 'resource', classes.updatable); setCmdArgSuggestions(spec, 'resources:create', 'resource', classes.creatable); setCmdArgSuggestions(spec, 'resources:delete', 'resource', classes.deletable); // PROVISIONING classes = await classifyResources('https://provisioning.commercelayer.co/api/public/resources'); setCmdArgSuggestions(spec, 'provisioning:list', 'resource', classes.listable.map(r => cli_core_1.clText.pluralize(r))); setCmdArgSuggestions(spec, 'provisioning:retrieve', 'resource', classes.retrievable); setCmdArgSuggestions(spec, 'provisioning:update', 'resource', classes.updatable); setCmdArgSuggestions(spec, 'provisioning:create', 'resource', classes.creatable); setCmdArgSuggestions(spec, 'provisioning:delete', 'resource', classes.deletable); return spec; } class CliFig extends core_1.Command { static description = 'generate a Fig completion spec for Commerce Layer CLI'; static hidden = true; static flags = { dir: core_1.Flags.directory({ char: 'd', description: 'directory where to save the output spec file', exclusive: ['install'] }), hidden: core_1.Flags.boolean({ char: 'h', description: 'include hidden commands' }), install: core_1.Flags.boolean({ char: 'i', description: 'copy into Fig specs directory', exclusive: ['dir'], hidden: true }), blind: core_1.Flags.boolean({ char: 'b', description: 'execute in blind mode without terminal output', hidden: true, exclusive: ['install'] }) }; async run() { const { flags } = await this.parse(CliFig); const spec = { name: this.config.name, subcommands: getFigSubcommands(this.config.commands) }; await enhanceSpec(spec); const template = await (0, prettier_1.format)(buildSpec(spec), { parser: 'typescript', printWidth: 80 }); if (flags.dir || flags.install) { const fileName = `${SPEC_NAME}.ts`; let fileDir = '.'; if (flags.dir) fileDir = cli_core_1.clUtil.specialFolder(flags.dir); else if (flags.install) fileDir = FIG_SPECS_DIR; if (!(0, node_fs_1.existsSync)(fileDir)) this.error(`Folder does not exists: ${cli_core_1.clColor.msg.error(fileDir)}`); const filePath = (0, node_path_1.join)(fileDir, fileName); core_1.ux.action.start(`Generating spec file ${filePath}`); (0, node_fs_1.writeFileSync)(filePath, template, { encoding: 'utf8', flag: 'w' }); core_1.ux.action.stop(); } else if (!flags.blind) this.log(template); } } exports.default = CliFig;