Skip to content

Creación de una aplicación CLI con oclife ☁️

Esta es una traducción que desde EGA Futura ofrecemos como cortesía a toda la Ohana y comunidad de programadores , consultores , administradores y arquitectos de Salesforce para toda Iberoamérica .

El enlace a la publicación original, lo encontrarás al final de este artículo.

Creación de una aplicación CLI con oclife | Blog de desarrolladores de Salesforce

La forma más común de interactuar con un sistema operativo es a través de una interfaz de usuario (UI), donde las ventanas, etiquetas, formularios y botones familiares crean una experiencia de usuario atractiva (pero no siempre… es por eso que el diseño visual de UX es una ciencia dedicada ahora) . Pero, una interfaz de usuario no es la única forma; los usuarios más técnicos (como nosotros los desarrolladores) prefieren usar una línea de comando para interactuar con el sistema operativo.

Windows, macOS, Linux y otros sistemas operativos vienen con una forma de interactuar a través de comandos usando una aplicación de terminal. Puede realizar varios conjuntos de tareas, desde navegar por el sistema de archivos hasta manipular archivos y carpetas y realizar tareas más complejas. Estas interfaces de línea de comandos, o shells, vienen con un lenguaje de programación completo de Turing, por lo que puede crear sus comandos y automatizar tareas específicas o incluso una aplicación que interactúa con una API.

En esta publicación, aprenderá a crear una aplicación de línea de comandos usando un marco Node.js creado aquí en Salesforce llamado oclif, el Marco de Open CLI . No discutiremos esos lenguajes de programación nativos como Bash (Linux, macOS) o Power Shell (Windows); en su lugar, usaremos un lenguaje más familiar, TypeScript (o JavaScript), para crear una aplicación de línea de comandos simple pero poderosa.

¿Qué es oclif y por qué es importante?

ocif es un marco de trabajo de código abierto para Node.js para crear aplicaciones de línea de comandos. Fue creado en 2018 por Salesforce, y es el que impulsa no solo nuestras CLI de Salesforce, sino también la CLI de Heroku. Otras empresas como Twilio, Adobe y Shopify también confían en oclf para sus aplicaciones CLI.

Nuestro proyecto CLI de Salesforce es de código abierto y se puede ampliar a través de complementos, y estos complementos se crean utilizando oclf. Si, como desarrollador de Salesforce, necesita crear un complemento personalizado para su flujo de trabajo, o una aplicación o utilidad que se base en nuestras bibliotecas de código abierto, aprender oclf es un excelente punto de partida.

Diseño de una aplicación CLI

Antes de construir nuestra aplicación CLI, veamos exactamente qué construiremos. Digamos que queremos construir un comando para crear tareas de Salesforce. Este comando almacenará tareas localmente y proporcionará un subcomando para sincronizar tareas locales con tareas remotas en Salesforce, lo que significa enviar tareas locales no sincronizadas y extraer tareas remotas.

Diseñemos los comandos que queremos implementar y sus diferentes argumentos y banderas.

Los comandos oclif se pueden agregar como comandos independientes o múltiples comandos agrupados por temas . Para nuestra aplicación de task , crearemos un tema de tasks para agrupar todos los comandos relacionados. Si desea agregar otra funcionalidad a esta aplicación, piense en el tipo de comandos y temas que puede crear para organizar mejor su aplicación.

Crear una nueva tarea

El new comando crea una tarea en una base de datos local y la tarea consta de los siguientes campos: Subject , Comment , Priority y Status .

<dx-code-block title language="shell" code-block="task tasks new [Comment] [–priority] [–status]
task tasks new Email # Creates a Task with Subject=Email, default priority, and no comment
task tasks new Call "Follow up" –priority Urgent # Creates a Task with Subject=Call, a comment, and priority=Urgent «>

Nota: un patrón común que se encuentra en la documentación de la CLI es que los argumentos incluidos entre <> son obligatorios y los incluidos entre [] son opcionales.

Listar tareas

Enumere las tareas que están almacenadas en la base de datos local.

Sincronizar tareas

El comando de sync se sincroniza con Salesforce, impulsando tareas locales no sincronizadas y extrayendo tareas remotas. Si una tarea ya existe, se actualizará.

Generación de una aplicación CLI

oclf viene con un generador de proyectos que creará un andamiaje con lo que se necesita para comenzar a crear una aplicación CLI. Creará un proyecto Node.js compatible con TypeScript y un útil comando "hola mundo" para mostrarle cómo funciona un comando.

Generemos un proyecto ejecutando: npx generate oclif tasks-cli

Esto creará una carpeta tasks-cli con el código fuente necesario para comenzar a construir su oclf CLI. Exploremos antes de comenzar con nuestra aplicación.

Vaya al directorio ejecutando cd tasks-cli y ejecute el ejecutable de desarrollo: ./bin/dev

Nota: En un sistema operativo *NIX como Linux o macOS, ejecuta ejecutables locales usando ./ ; en Windows, lo haces usando . , por ejemplo, .bindev .

Verás la ayuda que genera oclf para ti. ¡¿Qué tan genial es eso?! Aquí puedes ver los temas disponibles y los comandos que puedes ejecutar; si desea obtener más información sobre un comando, puede ejecutar ./bin/dev help [command] .

Ahora, podemos saltar al código fuente de nuestro proyecto; la lógica de temas y comandos se encuentra en la carpeta src/commands . Un tema es solo un subdirectorio con archivos de comando. Puede anidar tantos subcomandos como desee, pero no se recomienda profundizar más de uno o dos niveles.

Para el proyecto tasks-cli , no necesitamos el tema hello ; continúe y elimínelo, pero antes, eche un vistazo al código fuente commands/hello/index.ts y vea lo que hace. Si no lo entiende, está bien, exploraremos la estructura de un comando oclife en la siguiente sección.

Creando nuevos comandos

Queremos crear la siguiente estructura de carpetas para la aplicación tasks-cli , pero no lo haga manualmente, ocif proporciona un generador de comandos.

Nota: No se preocupe por la carpeta lib/ , no cubriremos su contenido en esta publicación. Puede obtener el código fuente completo del repositorio julianduque/sf-tasks-cli GitHub. Este contiene una clase con los métodos requeridos para almacenar los datos localmente usando sqlite3 .

Para generar un comando, puede ejecutar lo siguiente: npx oclif generate command <command name>


Ahora, tenemos dos archivos nuevos, nuestra clase de comando y un archivo de prueba. Cubriremos las pruebas en una publicación futura; por ahora, concentrémonos en la estructura de la clase de comando.

Estamos utilizando aquí una versión ligeramente simplificada del new comando utilizado en la aplicación final. Comentemos las partes más importantes de este código.

<dx-code-block title language="typescript" code-block="import {Command, Flags} from '@oclif/core'
import TasksDb from '../../lib/tasks-db'
import {Task} from '../../lib/task' export default class TasksNew extends Command { // Get the local database instance #db = new TasksDb(this.config.dataDir) // Define aliases for the command static aliases = ['new', 'create'] // Describe the command static description = 'Create a new Salesforce Task' // Provide examples of how to use the command static examples = [ ' "Email" –priority "Normal" –status "Not Started"’, ‘ "Call" "This is a comment" -p "Urgent" -s "Not Started"’, ] // Define the arguments and flags for the command static flags = { priority: Flags.string({char: ‘p’, description: ‘Priority of the task’, default: ‘Normal’}), status: Flags.string({char: ‘s’, description: ‘Status of the task’, default: ‘Not Started’}), } static args = [{ name: ‘subject’, options: [‘Call’, ‘Email’, ‘Send Letter’, ‘Send Quote’, ‘Other’], required: true, }, { name: ‘comment’, required: false, }] // Main method to run the command public async run(): Promise { // Parse both arguments and flags const {args, flags} = await this.parse(TasksNew) // Create a new Task object const task : Task = { subject: args.subject, priority: flags.priority, status: flags.status, comment: args.comment || », sfid: null, } // Store task in the local database const {id} = this.#db.createTask(task) // Use the logger to notify the user this.log(`Task created successfully with subject: ${subject} and id: ${id}`) }
} «>

  • un comando oclif se extiende desde la clase Command que se importa desde @oclif/core
  • la propiedad aliases es útil para crear alias para el comando; se pueden asignar a la raíz si no se especifica ningún tema
  • la propiedad de description se utiliza para documentar el comando; este texto se muestra en la ayuda y documentación
  • la propiedad de examples define diferentes formas de usar este comando, lo cual es útil para la información de ayuda y la documentación
  • la propiedad args define los argumentos para este comando; ampliaremos los argumentos en la siguiente sección
  • la propiedad flags define las banderas para este comando; ampliaremos las banderas en la siguiente sección
  • el método run() es donde ocurre la magia; aquí escribimos la lógica del comando

Para obtener más información sobre los comandos, consulte la documentación oficial de oclife .

Argumentos y banderas: ¿cómo interactuar con los comandos?

Un comando puede recibir argumentos y banderas, pero ¿cuáles son esos? Definámoslos y veamos cómo podemos configurarlos en una aplicación oclife.

Argumentos

Los argumentos son cadenas posicionales que se pueden pasar a un comando, por ejemplo, task new Call "Follow up with the customer" . En el ejemplo anterior, tanto Call como Follow up with the customer son argumentos. Para definirlos en ocif, define la propiedad args con una matriz de argumentos y sus propiedades:

Nota: ¿Recuerdas la parte posicional de la definición? Bueno, aquí, la posición importa; el orden de los argumentos se especifica en la matriz args .

Para obtener más información sobre los argumentos y sus propiedades, consulte la documentación de oclife.

banderas

Las banderas, por otro lado, no son posicionales; se pueden pasar en cualquier orden y recibir un valor de cadena o un valor booleano si la bandera está presente. Para definir banderas en oclif, puede usar la clase Flag que se importa de @oclif/core y establecerlas en la propiedad flags .

Nota: si desea crear un indicador booleano, puede hacerlo mediante Flags.boolean .

La propiedad char es una versión abreviada de ese indicador, por lo que, en lugar de pasar --priority Urgent , puede pasar -p Urgent .

Para obtener más información sobre las banderas y sus propiedades, consulte la documentación de oclife.

Análisis de argumentos y banderas

Hemos aprendido a definir argumentos y banderas, pero ¿cómo podemos extraer los valores pasados a nuestro comando? Hacemos eso en nuestro método run() ejecutando this.parse() .

Los valores de los argumentos y las banderas se establecen en los objetos args y flags , y puede acceder a ellos usando la notación de puntos de JavaScript, por ejemplo, flags.priority o args.subject .

¡UX lo es todo!

oclf viene con herramientas útiles para mejorar la experiencia tanto de los usuarios de nuestra aplicación como de los sistemas que dependerán de ella.

A veces, los usuarios de nuestras aplicaciones no son humanos sino otros comandos que dependen de nuestra salida.
Para eso, oclf ofrece una forma práctica de devolver datos como un objeto JSON. Para lograr esto, deberá configurar enableJsonFlag en true .


Al interactuar con humanos, la clase CliUx de @oclif/core ofrece utilidades para solicitar información , representar datos como una tabla y mostrar una rueda mientras nuestra aplicación realiza una tarea.

<dx-code-block title language="typescript" code-block=" public static enableJsonFlag = true public async run(): Promise { const {flags} = await this.parse(TasksList) const tasks = this.#db.listTasks() CliUx.ux.table(tasks, { id: { header: ‘ID’, extended: true, }, subject: {}, priority: {}, status: {}, comment: { extended: true, }, sfid: { header: ‘Synced’, get: (row: Task) => row.sfid ? `Yes (${row.sfid})` : ‘No’, extended: true, }, }, { printLine: this.log.bind(this), …flags, }) return tasks } «>

Nota: Puede encontrar el código fuente completo de command/tasks/list.ts en el repositorio julianduque/sf-tasks-cli GitHub.

También puede confiar en componentes CLI UX más avanzados del ecosistema npm, como inquirer (ver documentos ), que ofrece más opciones para solicitar, como un cuadro de selección.

Nota: Puede encontrar el código fuente completo del command/tasks/new.ts en el repositorio julianduque/sf-tasks-cli GitHub.

Uso de complementos

Una de las principales ventajas que tiene oclf es su capacidad de complemento. No solo podrá escribir complementos para sus aplicaciones, sino también usar complementos publicados por otros. Para nuestra aplicación de tasks , usaremos @salesforce/plugin-auth para permitir que nuestra aplicación se autentique en una organización de Salesforce; este complemento es el mismo que usa la CLI de sfdx .

Instalemos el complemento ejecutando ./bin/dev plugins install @salesforce/plugin-auth . Esto instalará el complemento en nuestra aplicación y agregará un nuevo tema de auth . Ahora, podemos autenticarnos en una organización de Salesforce de la misma manera que lo hacemos con la CLI de sfdx .

Conexión a Salesforce

Otro proyecto útil de código abierto del equipo de la CLI de Salesforce es @salesforce/core (consulte el repositorio de GitHub ). Con esto, podemos crear un objeto de autenticación y crear una conexión a una organización.

Nota: Puede encontrar el código fuente completo del command/tasks/sync.ts en el repositorio julianduque/sf-tasks-cli GitHub.

El método AuthInfo.create requiere un nombre de usuario para obtener la información de la organización de las que ha autenticado previamente (por ejemplo, con el comando auth que acabamos de agregar). Para proporcionar un buen UX, lo solicitamos como un --target-org .

Connection.create devuelve un objeto JSforce Connection para que pueda realizar cualquier operación disponible en ese objeto.

Nota: JSforce es una potente biblioteca de JavaScript para desarrollar aplicaciones de Salesforce.

Conclusión

ocif es un marco poderoso para crear aplicaciones CLI. No hemos discutido todo lo que puede hacer. Por ejemplo, podrás publicar esta aplicación y ponerla a disposición del público, e incluso empaquetarla para diferentes sistemas operativos. Si desea obtener más información al respecto, puede leer la sección Lanzamiento de la documentación de oclf.

Creé una serie de videos donde construí esta aplicación tasks-cli en vivo en YouTube. Puede encontrar un enlace en la sección Recursos de aprendizaje a continuación.

¿Que sigue?

En una próxima publicación, aprenderá cómo crear un complemento personalizado para la CLI de Salesforce y publicarlo en el repositorio de npm.

Recursos de aprendizaje

Sobre el Autor

Julián Duque es Defensor Principal de Desarrolladores en Salesforce. Es desarrollador y educador y pasa su tiempo libre ejecutando juegos TTRPG en línea y jugando y entrenando su Mini Aussie, Cumbia.

Obtenga las últimas publicaciones de blog de desarrolladores de Salesforce y episodios de podcast a través de Slack o RSS.

Agregar a Slack Suscríbete a RSS

Esta es una traducción realizada por EGA Futura, y este es el link a la publicación original: https://developer.salesforce.com/blogs/2022/10/building-a-cli-application-with-oclif.html

Entradas recomendadas