diff --git a/404.html b/404.html index afc524df..8e827138 100644 --- a/404.html +++ b/404.html @@ -11,7 +11,7 @@ - +
diff --git a/assets/js/03a88bad.3fa9ada6.js b/assets/js/03a88bad.52baa0b3.js similarity index 94% rename from assets/js/03a88bad.3fa9ada6.js rename to assets/js/03a88bad.52baa0b3.js index a9f8b0b5..481226e8 100644 --- a/assets/js/03a88bad.3fa9ada6.js +++ b/assets/js/03a88bad.52baa0b3.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8078],{2584:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>d,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>i,toc:()=>a});var o=n(4848),r=n(8453);const s={},c=void 0,i={id:"index",title:"index",description:"",source:"@site/../docs/index.md",sourceDirName:".",slug:"/",permalink:"/docs/",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/index.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{}},d={},a=[];function u(t){return(0,o.jsx)("meta",{"http-equiv":"refresh",content:"0; url=https://oclif.io/docs/introduction.html"})}function l(t={}){const{wrapper:e}={...(0,r.R)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(u,{...t})}):u()}},8453:(t,e,n)=>{n.d(e,{R:()=>c,x:()=>i});var o=n(6540);const r={},s=o.createContext(r);function c(t){const e=o.useContext(s);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function i(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:c(t.components),o.createElement(s.Provider,{value:e},t.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8078],{2584:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>d,contentTitle:()=>c,default:()=>l,frontMatter:()=>s,metadata:()=>i,toc:()=>a});var o=n(4848),r=n(8453);const s={},c=void 0,i={id:"index",title:"index",description:"",source:"@site/../docs/index.md",sourceDirName:".",slug:"/",permalink:"/docs/",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/index.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{}},d={},a=[];function u(t){return(0,o.jsx)("meta",{"http-equiv":"refresh",content:"0; url=https://oclif.io/docs/introduction.html"})}function l(t={}){const{wrapper:e}={...(0,r.R)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(u,{...t})}):u()}},8453:(t,e,n)=>{n.d(e,{R:()=>c,x:()=>i});var o=n(6540);const r={},s=o.createContext(r);function c(t){const e=o.useContext(s);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function i(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:c(t.components),o.createElement(s.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/03abeb31.5415b57b.js b/assets/js/03abeb31.5f9309f2.js similarity index 94% rename from assets/js/03abeb31.5415b57b.js rename to assets/js/03abeb31.5f9309f2.js index 65a30d0e..582a23a4 100644 --- a/assets/js/03abeb31.5415b57b.js +++ b/assets/js/03abeb31.5f9309f2.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[844],{3680:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>u});var o=n(4848),i=n(8453);const s={title:"Debugging"},d=void 0,r={id:"debugging",title:"Debugging",description:"Use the debug for debugging. The CLI uses this module for all of its debugging. If you set the environment variable DEBUG=* it will print all the debug output to the screen.",source:"@site/../docs/debugging.md",sourceDirName:".",slug:"/debugging",permalink:"/docs/debugging",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/debugging.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Debugging"},sidebar:"docs",previous:{title:"Notifications",permalink:"/docs/notifications"},next:{title:"Flexible Taxonomy",permalink:"/docs/flexible_taxonomy"}},c={},u=[];function a(e){const t={a:"a",code:"code",img:"img",p:"p",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["Use the ",(0,o.jsx)(t.a,{href:"https://github.com/visionmedia/debug",children:"debug"})," for debugging. The CLI uses this module for all of its debugging. If you set the environment variable ",(0,o.jsx)(t.code,{children:"DEBUG=*"})," it will print all the debug output to the screen."]}),"\n",(0,o.jsxs)(t.p,{children:["Depending on your shell you may need to escape this with ",(0,o.jsx)(t.code,{children:"DEBUG=\\*"}),". On Windows you can't set environment variables in line, so you'll need to run ",(0,o.jsx)(t.code,{children:"set DEBUG=*"})," before running the command."]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"debug demo",src:n(1466).A+"",width:"2658",height:"1250"})})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(a,{...e})}):a(e)}},1466:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/debug_demo-efc07abda59d2b82da3fc695b96596c8.png"},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>r});var o=n(6540);const i={},s=o.createContext(i);function d(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[844],{3680:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>l,frontMatter:()=>s,metadata:()=>r,toc:()=>u});var o=n(4848),i=n(8453);const s={title:"Debugging"},d=void 0,r={id:"debugging",title:"Debugging",description:"Use the debug for debugging. The CLI uses this module for all of its debugging. If you set the environment variable DEBUG=* it will print all the debug output to the screen.",source:"@site/../docs/debugging.md",sourceDirName:".",slug:"/debugging",permalink:"/docs/debugging",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/debugging.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Debugging"},sidebar:"docs",previous:{title:"Notifications",permalink:"/docs/notifications"},next:{title:"Flexible Taxonomy",permalink:"/docs/flexible_taxonomy"}},c={},u=[];function a(e){const t={a:"a",code:"code",img:"img",p:"p",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["Use the ",(0,o.jsx)(t.a,{href:"https://github.com/visionmedia/debug",children:"debug"})," for debugging. The CLI uses this module for all of its debugging. If you set the environment variable ",(0,o.jsx)(t.code,{children:"DEBUG=*"})," it will print all the debug output to the screen."]}),"\n",(0,o.jsxs)(t.p,{children:["Depending on your shell you may need to escape this with ",(0,o.jsx)(t.code,{children:"DEBUG=\\*"}),". On Windows you can't set environment variables in line, so you'll need to run ",(0,o.jsx)(t.code,{children:"set DEBUG=*"})," before running the command."]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"debug demo",src:n(1466).A+"",width:"2658",height:"1250"})})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(a,{...e})}):a(e)}},1466:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/debug_demo-efc07abda59d2b82da3fc695b96596c8.png"},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>r});var o=n(6540);const i={},s=o.createContext(i);function d(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/0b218a01.00c2d643.js b/assets/js/0b218a01.de27cef5.js similarity index 98% rename from assets/js/0b218a01.00c2d643.js rename to assets/js/0b218a01.de27cef5.js index 31923405..fc3eb56c 100644 --- a/assets/js/0b218a01.00c2d643.js +++ b/assets/js/0b218a01.de27cef5.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3454],{6040:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>r});var a=s(4848),i=s(8453);const t={title:"Aliases"},o=void 0,l={id:"aliases",title:"Aliases",description:"Command Aliases",source:"@site/../docs/aliases.md",sourceDirName:".",slug:"/aliases",permalink:"/docs/aliases",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/aliases.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Aliases"},sidebar:"docs",previous:{title:"Just-in-Time Plugin Installation",permalink:"/docs/jit_plugins"},next:{title:"NSIS Installer Customization",permalink:"/docs/nsis-installer_customization"}},c={},r=[{value:"Command Aliases",id:"command-aliases",level:2},{value:"Flag Aliases",id:"flag-aliases",level:2},{value:"Bin Aliases",id:"bin-aliases",level:2}];function d(e){const n={code:"code",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"command-aliases",children:"Command Aliases"}),"\n",(0,a.jsxs)(n.p,{children:["Aliases let you define a string that maps to a command. This command can be run as ",(0,a.jsx)(n.code,{children:"mycli config"}),", ",(0,a.jsx)(n.code,{children:"mycli config:index"}),", or ",(0,a.jsx)(n.code,{children:"mycli config:list"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"import {Command, Flags} from '@oclif/core'\n\nexport class ConfigIndex extends Command {\n static aliases = ['config:index', 'config:list']\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:['By default, aliases find the "real" command and just work. If you\'re providing command aliases for backward compatibility but prefer users to use the "real" command, set ',(0,a.jsx)(n.code,{children:"deprecateAliases"})," to ",(0,a.jsx)(n.code,{children:"true"})," to warn users about the correct name"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"export class ConfigIndex extends Command {\n static aliases = ['config:index', 'config:list']\n static deprecateAliases = true\n}\n"})}),"\n",(0,a.jsx)(n.h2,{id:"flag-aliases",children:"Flag Aliases"}),"\n",(0,a.jsx)(n.p,{children:"Like command aliases, but on an individual flag. You can alias the name and short character, and optionally emit warnings when aliased names are used."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"export class ConfigIndex extends Command {\n static flags = {\n 'new-name': Flags.boolean({\n char: 'c',\n aliases: ['old-name', 'o'],\n deprecateAliases: true\n })\n }\n}\n\n"})}),"\n",(0,a.jsx)(n.h2,{id:"bin-aliases",children:"Bin Aliases"}),"\n",(0,a.jsxs)(n.p,{children:['Creating a CLI that responds to different names or "aliases" is easy, simply add a ',(0,a.jsx)(n.code,{children:"binAliases"})," property to your CLI's ",(0,a.jsx)(n.code,{children:"oclif"})," property in ",(0,a.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "name": "mycli",\n "version": "0.0.0",\n "description": "My CLI",\n "main": "bin/run.js",\n "bin": {\n "mycli": "./bin/run.js",\n "mycli-alias": "./bin/run.js"\n },\n "oclif": {\n "binAliases": ["mycli", "mycli-alias"]\n }\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Adding this property allows your CLI to respond to either of those names, and is used during the bundling and building process when shipping your CLI. Note that the ",(0,a.jsx)(n.code,{children:"bin"})," section was also modified to include both aliases, which is how npm creates bin aliases. To create a unified experience, regardless of the installation method, a CLI author must change both to match. Bin aliases also play nicely with ",(0,a.jsx)(n.code,{children:"@oclif/plugin-autocomplete"}),", so typing an alias and using autocomplete is the same experience as using the original name."]})]})}function m(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>l});var a=s(6540);const i={},t=a.createContext(i);function o(e){const n=a.useContext(t);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3454],{6040:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>m,frontMatter:()=>t,metadata:()=>l,toc:()=>r});var a=s(4848),i=s(8453);const t={title:"Aliases"},o=void 0,l={id:"aliases",title:"Aliases",description:"Command Aliases",source:"@site/../docs/aliases.md",sourceDirName:".",slug:"/aliases",permalink:"/docs/aliases",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/aliases.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Aliases"},sidebar:"docs",previous:{title:"Just-in-Time Plugin Installation",permalink:"/docs/jit_plugins"},next:{title:"NSIS Installer Customization",permalink:"/docs/nsis-installer_customization"}},c={},r=[{value:"Command Aliases",id:"command-aliases",level:2},{value:"Flag Aliases",id:"flag-aliases",level:2},{value:"Bin Aliases",id:"bin-aliases",level:2}];function d(e){const n={code:"code",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"command-aliases",children:"Command Aliases"}),"\n",(0,a.jsxs)(n.p,{children:["Aliases let you define a string that maps to a command. This command can be run as ",(0,a.jsx)(n.code,{children:"mycli config"}),", ",(0,a.jsx)(n.code,{children:"mycli config:index"}),", or ",(0,a.jsx)(n.code,{children:"mycli config:list"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"import {Command, Flags} from '@oclif/core'\n\nexport class ConfigIndex extends Command {\n static aliases = ['config:index', 'config:list']\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:['By default, aliases find the "real" command and just work. If you\'re providing command aliases for backward compatibility but prefer users to use the "real" command, set ',(0,a.jsx)(n.code,{children:"deprecateAliases"})," to ",(0,a.jsx)(n.code,{children:"true"})," to warn users about the correct name"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"export class ConfigIndex extends Command {\n static aliases = ['config:index', 'config:list']\n static deprecateAliases = true\n}\n"})}),"\n",(0,a.jsx)(n.h2,{id:"flag-aliases",children:"Flag Aliases"}),"\n",(0,a.jsx)(n.p,{children:"Like command aliases, but on an individual flag. You can alias the name and short character, and optionally emit warnings when aliased names are used."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-js",children:"export class ConfigIndex extends Command {\n static flags = {\n 'new-name': Flags.boolean({\n char: 'c',\n aliases: ['old-name', 'o'],\n deprecateAliases: true\n })\n }\n}\n\n"})}),"\n",(0,a.jsx)(n.h2,{id:"bin-aliases",children:"Bin Aliases"}),"\n",(0,a.jsxs)(n.p,{children:['Creating a CLI that responds to different names or "aliases" is easy, simply add a ',(0,a.jsx)(n.code,{children:"binAliases"})," property to your CLI's ",(0,a.jsx)(n.code,{children:"oclif"})," property in ",(0,a.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "name": "mycli",\n "version": "0.0.0",\n "description": "My CLI",\n "main": "bin/run.js",\n "bin": {\n "mycli": "./bin/run.js",\n "mycli-alias": "./bin/run.js"\n },\n "oclif": {\n "binAliases": ["mycli", "mycli-alias"]\n }\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Adding this property allows your CLI to respond to either of those names, and is used during the bundling and building process when shipping your CLI. Note that the ",(0,a.jsx)(n.code,{children:"bin"})," section was also modified to include both aliases, which is how npm creates bin aliases. To create a unified experience, regardless of the installation method, a CLI author must change both to match. Bin aliases also play nicely with ",(0,a.jsx)(n.code,{children:"@oclif/plugin-autocomplete"}),", so typing an alias and using autocomplete is the same experience as using the original name."]})]})}function m(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>o,x:()=>l});var a=s(6540);const i={},t=a.createContext(i);function o(e){const n=a.useContext(t);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),a.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/104cbb75.c7fb3ef1.js b/assets/js/104cbb75.c2ce6e10.js similarity index 98% rename from assets/js/104cbb75.c7fb3ef1.js rename to assets/js/104cbb75.c2ce6e10.js index 8cfc24d7..3af0bc4d 100644 --- a/assets/js/104cbb75.c7fb3ef1.js +++ b/assets/js/104cbb75.c2ce6e10.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6471],{8907:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var t=n(4848),i=n(8453);const a={title:"Flexible Taxonomy"},r=void 0,s={id:"flexible_taxonomy",title:"Flexible Taxonomy",description:"If you'd like for your customers to execute commands without adhereing to the defined command taxonomy, you can enable flexibleTaxonomy and add a hook to the oclif section of your package.json:",source:"@site/../docs/flexible_taxonomy.md",sourceDirName:".",slug:"/flexible_taxonomy",permalink:"/docs/flexible_taxonomy",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/flexible_taxonomy.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Flexible Taxonomy"},sidebar:"docs",previous:{title:"Debugging",permalink:"/docs/debugging"},next:{title:"Global Flags",permalink:"/docs/global_flags"}},c={},l=[{value:"Hook Implementation",id:"hook-implementation",level:3}];function d(e){const o={a:"a",code:"code",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(o.p,{children:["If you'd like for your customers to execute commands without adhereing to the defined command taxonomy, you can enable ",(0,t.jsx)(o.code,{children:"flexibleTaxonomy"})," and add a hook to the ",(0,t.jsx)(o.code,{children:"oclif"})," section of your package.json:"]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-json",children:'{\n "oclif": {\n "flexibleTaxonomy": true,\n "hooks": {\n "command_incomplete": "./dist/hooks/command_incomplete.js"\n }\n }\n}\n'})}),"\n",(0,t.jsx)(o.p,{children:"There are two main benefits to enabling flexible taxonomy:"}),"\n",(0,t.jsxs)(o.ol,{children:["\n",(0,t.jsxs)(o.li,{children:["It makes your CLI more user-friendly. For example, you might have a command, ",(0,t.jsx)(o.code,{children:"my-cli foobars:list"}),". If a user mistakenly enters ",(0,t.jsx)(o.code,{children:"my-cli list:foobars"})," then oclif will automatically know that it should execute ",(0,t.jsx)(o.code,{children:"foobars:list"})," instead of throwing an error."]}),"\n",(0,t.jsxs)(o.li,{children:["It gives you the opportunity to prompt a user for the right command if they only provide part of a command. This makes individual commands more discoverable, especially if you have a large number of commands. See ",(0,t.jsx)(o.a,{href:"#hook-implementation",children:"Hook Implementation"})," for more details."]}),"\n"]}),"\n",(0,t.jsx)(o.h3,{id:"hook-implementation",children:"Hook Implementation"}),"\n",(0,t.jsxs)(o.p,{children:["When ",(0,t.jsx)(o.code,{children:"flexibleTaxonomy"})," is enabled, oclif will run the ",(0,t.jsx)(o.code,{children:"command_incomplete"})," hook anytime a user enters an incomplete command (e.g. the command is ",(0,t.jsx)(o.code,{children:"one:two:three"})," but they only entered ",(0,t.jsx)(o.code,{children:"two"}),"). This hook gives you the opportunity to create an interactive user experience."]}),"\n",(0,t.jsxs)(o.p,{children:["This example shows how you can use the ",(0,t.jsx)(o.a,{href:"#https://www.npmjs.com/package/inquirer",children:"inquirer"})," package to prompt the user for which command they would like to run:"]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-typescript",children:'import { Hook, toConfiguredId, toStandardizedId } from "@oclif/core";\nimport { prompt } from "inquirer";\n\nconst hook: Hook.CommandIncomplete = async function ({\n config,\n matches,\n argv,\n}) {\n const { command } = await prompt<{ command: string }>([\n {\n name: "command",\n type: "list",\n message: "Which of these commands would you like to run?",\n choices: matches.map((p) => toConfiguredId(p.id, config)),\n },\n ]);\n\n if (argv.includes("--help") || argv.includes("-h")) {\n return config.runCommand("help", [toStandardizedId(command, config)]);\n }\n\n return config.runCommand(toStandardizedId(command, config), argv);\n};\n\nexport default hook;\n'})}),"\n",(0,t.jsx)(o.p,{children:"This is the prompt that the user would see:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{children:"$ my-cli list\n? Which of these commands did you mean (Use arrow keys)\n\u276f foobars list\n config list\n env list\n"})})]})}function m(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>r,x:()=>s});var t=n(6540);const i={},a=t.createContext(i);function r(e){const o=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function s(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(a.Provider,{value:o},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6471],{8907:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>c,contentTitle:()=>r,default:()=>m,frontMatter:()=>a,metadata:()=>s,toc:()=>l});var t=n(4848),i=n(8453);const a={title:"Flexible Taxonomy"},r=void 0,s={id:"flexible_taxonomy",title:"Flexible Taxonomy",description:"If you'd like for your customers to execute commands without adhereing to the defined command taxonomy, you can enable flexibleTaxonomy and add a hook to the oclif section of your package.json:",source:"@site/../docs/flexible_taxonomy.md",sourceDirName:".",slug:"/flexible_taxonomy",permalink:"/docs/flexible_taxonomy",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/flexible_taxonomy.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Flexible Taxonomy"},sidebar:"docs",previous:{title:"Debugging",permalink:"/docs/debugging"},next:{title:"Global Flags",permalink:"/docs/global_flags"}},c={},l=[{value:"Hook Implementation",id:"hook-implementation",level:3}];function d(e){const o={a:"a",code:"code",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(o.p,{children:["If you'd like for your customers to execute commands without adhereing to the defined command taxonomy, you can enable ",(0,t.jsx)(o.code,{children:"flexibleTaxonomy"})," and add a hook to the ",(0,t.jsx)(o.code,{children:"oclif"})," section of your package.json:"]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-json",children:'{\n "oclif": {\n "flexibleTaxonomy": true,\n "hooks": {\n "command_incomplete": "./dist/hooks/command_incomplete.js"\n }\n }\n}\n'})}),"\n",(0,t.jsx)(o.p,{children:"There are two main benefits to enabling flexible taxonomy:"}),"\n",(0,t.jsxs)(o.ol,{children:["\n",(0,t.jsxs)(o.li,{children:["It makes your CLI more user-friendly. For example, you might have a command, ",(0,t.jsx)(o.code,{children:"my-cli foobars:list"}),". If a user mistakenly enters ",(0,t.jsx)(o.code,{children:"my-cli list:foobars"})," then oclif will automatically know that it should execute ",(0,t.jsx)(o.code,{children:"foobars:list"})," instead of throwing an error."]}),"\n",(0,t.jsxs)(o.li,{children:["It gives you the opportunity to prompt a user for the right command if they only provide part of a command. This makes individual commands more discoverable, especially if you have a large number of commands. See ",(0,t.jsx)(o.a,{href:"#hook-implementation",children:"Hook Implementation"})," for more details."]}),"\n"]}),"\n",(0,t.jsx)(o.h3,{id:"hook-implementation",children:"Hook Implementation"}),"\n",(0,t.jsxs)(o.p,{children:["When ",(0,t.jsx)(o.code,{children:"flexibleTaxonomy"})," is enabled, oclif will run the ",(0,t.jsx)(o.code,{children:"command_incomplete"})," hook anytime a user enters an incomplete command (e.g. the command is ",(0,t.jsx)(o.code,{children:"one:two:three"})," but they only entered ",(0,t.jsx)(o.code,{children:"two"}),"). This hook gives you the opportunity to create an interactive user experience."]}),"\n",(0,t.jsxs)(o.p,{children:["This example shows how you can use the ",(0,t.jsx)(o.a,{href:"#https://www.npmjs.com/package/inquirer",children:"inquirer"})," package to prompt the user for which command they would like to run:"]}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{className:"language-typescript",children:'import { Hook, toConfiguredId, toStandardizedId } from "@oclif/core";\nimport { prompt } from "inquirer";\n\nconst hook: Hook.CommandIncomplete = async function ({\n config,\n matches,\n argv,\n}) {\n const { command } = await prompt<{ command: string }>([\n {\n name: "command",\n type: "list",\n message: "Which of these commands would you like to run?",\n choices: matches.map((p) => toConfiguredId(p.id, config)),\n },\n ]);\n\n if (argv.includes("--help") || argv.includes("-h")) {\n return config.runCommand("help", [toStandardizedId(command, config)]);\n }\n\n return config.runCommand(toStandardizedId(command, config), argv);\n};\n\nexport default hook;\n'})}),"\n",(0,t.jsx)(o.p,{children:"This is the prompt that the user would see:"}),"\n",(0,t.jsx)(o.pre,{children:(0,t.jsx)(o.code,{children:"$ my-cli list\n? Which of these commands did you mean (Use arrow keys)\n\u276f foobars list\n config list\n env list\n"})})]})}function m(e={}){const{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,t.jsx)(o,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,o,n)=>{n.d(o,{R:()=>r,x:()=>s});var t=n(6540);const i={},a=t.createContext(i);function r(e){const o=t.useContext(a);return t.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function s(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(a.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/19fd9079.ac45505f.js b/assets/js/19fd9079.0d5010f9.js similarity index 96% rename from assets/js/19fd9079.ac45505f.js rename to assets/js/19fd9079.0d5010f9.js index 9b4477c9..6a53715b 100644 --- a/assets/js/19fd9079.ac45505f.js +++ b/assets/js/19fd9079.0d5010f9.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8080],{4015:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var o=n(4848),s=n(8453);const r={title:"External Links"},l=void 0,i={id:"external_links",title:"External Links",description:"* Salesforce Release Announcement",source:"@site/../docs/external_links.md",sourceDirName:".",slug:"/external_links",permalink:"/docs/external_links",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/external_links.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"External Links"},sidebar:"docs",previous:{title:"Examples",permalink:"/docs/examples"},next:{title:"Related Repositories",permalink:"/docs/related_repos"}},a={},c=[];function d(e){const t={a:"a",li:"li",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"https://engineering.salesforce.com/open-sourcing-oclif-the-cli-framework-that-powers-our-clis-21fbda99d33a",children:"Salesforce Release Announcement"})}),"\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"https://blog.heroku.com/open-cli-framework",children:"Heroku Release Announcement"})}),"\n"]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>l,x:()=>i});var o=n(6540);const s={},r=o.createContext(s);function l(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),o.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8080],{4015:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var o=n(4848),s=n(8453);const r={title:"External Links"},l=void 0,i={id:"external_links",title:"External Links",description:"* Salesforce Release Announcement",source:"@site/../docs/external_links.md",sourceDirName:".",slug:"/external_links",permalink:"/docs/external_links",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/external_links.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"External Links"},sidebar:"docs",previous:{title:"Examples",permalink:"/docs/examples"},next:{title:"Related Repositories",permalink:"/docs/related_repos"}},a={},c=[];function d(e){const t={a:"a",li:"li",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"https://engineering.salesforce.com/open-sourcing-oclif-the-cli-framework-that-powers-our-clis-21fbda99d33a",children:"Salesforce Release Announcement"})}),"\n",(0,o.jsx)(t.li,{children:(0,o.jsx)(t.a,{href:"https://blog.heroku.com/open-cli-framework",children:"Heroku Release Announcement"})}),"\n"]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>l,x:()=>i});var o=n(6540);const s={},r=o.createContext(s);function l(e){const t=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),o.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1ed4142b.646b4f19.js b/assets/js/1ed4142b.a44c3e96.js similarity index 98% rename from assets/js/1ed4142b.646b4f19.js rename to assets/js/1ed4142b.a44c3e96.js index 3ecee4ea..a1a72392 100644 --- a/assets/js/1ed4142b.646b4f19.js +++ b/assets/js/1ed4142b.a44c3e96.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3782],{32:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=t(4848),o=t(8453);const s={title:"Just-in-Time Plugin Installation"},l=void 0,a={id:"jit_plugins",title:"Just-in-Time Plugin Installation",description:"Sometimes you might want to have a plugin that isn't bundled in your CLI but gets installed the first time it's executed by the user - we call this just-in-time plugin installation, or JIT for short. This can be useful if you need to reduce the package size of your CLI while still allowing users access to all the plugins.",source:"@site/../docs/jit_plugins.md",sourceDirName:".",slug:"/jit_plugins",permalink:"/docs/jit_plugins",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/jit_plugins.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Just-in-Time Plugin Installation"},sidebar:"docs",previous:{title:"Running Commands Programmatically",permalink:"/docs/running_programmatically"},next:{title:"Aliases",permalink:"/docs/aliases"}},r={},c=[];function u(e){const n={code:"code",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Sometimes you might want to have a plugin that isn't bundled in your CLI but gets installed the first time it's executed by the user - we call this just-in-time plugin installation, or JIT for short. This can be useful if you need to reduce the package size of your CLI while still allowing users access to all the plugins."}),"\n",(0,i.jsx)(n.p,{children:"To use this feature you need to:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Add ",(0,i.jsx)(n.code,{children:"jitPlugins"})," to the ",(0,i.jsx)(n.code,{children:"oclif"})," section of your package.json"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"oclif": {\n "jitPlugins": {\n "my-plugin": "^1.2.3",\n "another-plugin": "^1.2.3",\n }\n}\n'})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Ensure that your build process includes generating a manifest using ",(0,i.jsx)(n.code,{children:"oclif manifest"}),". The manifest will include the information about all the commands owned by JIT plugins which allows users to run ",(0,i.jsx)(n.code,{children:"--help"})," on those commands without having them installed yet. ",(0,i.jsx)(n.strong,{children:"If the generated manifest doesn't get packed with your CLI, then the feature will not work."})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Implement the ",(0,i.jsx)(n.code,{children:"jit_plugin_not_installed"})," hook."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@oclif/core"})," attempts to be UX-agnostic, meaning that we don't want to impose any particular user experience on you. Any time a user experience is required we utilize hooks so that you can design the exact user experience you want your users to have."]}),"\n",(0,i.jsx)(n.p,{children:"In the case of JIT plugin installation, there are many possible user experiences that you might want - maybe you want to prompt the user for confirmation first, or maybe you want to log a specific message, etc..."}),"\n",(0,i.jsx)(n.p,{children:"Here's an example of how you might implement the hook,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"import { Hook, CLIError, ux } from '@oclif/core';\n\nconst hook: Hook<'jit_plugin_not_installed'> = async function (opts) {\n try {\n const answer = await ux.confirm(`${opts.command.pluginName} not installed. Would you like to install?`)\n if (answer === 'y') {\n await opts.config.runCommand('plugins:install', [`${opts.command.pluginName}@${opts.pluginVersion}`]);\n }\n } catch (error) {\n throw new CLIError(`Could not install ${opts.command.pluginName}`, 'JitPluginInstallError');\n }\n};\n\nexport default hook;\n\n"})})]})}function d(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>a});var i=t(6540);const o={},s=i.createContext(o);function l(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3782],{32:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>d,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=t(4848),o=t(8453);const s={title:"Just-in-Time Plugin Installation"},l=void 0,a={id:"jit_plugins",title:"Just-in-Time Plugin Installation",description:"Sometimes you might want to have a plugin that isn't bundled in your CLI but gets installed the first time it's executed by the user - we call this just-in-time plugin installation, or JIT for short. This can be useful if you need to reduce the package size of your CLI while still allowing users access to all the plugins.",source:"@site/../docs/jit_plugins.md",sourceDirName:".",slug:"/jit_plugins",permalink:"/docs/jit_plugins",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/jit_plugins.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Just-in-Time Plugin Installation"},sidebar:"docs",previous:{title:"Running Commands Programmatically",permalink:"/docs/running_programmatically"},next:{title:"Aliases",permalink:"/docs/aliases"}},r={},c=[];function u(e){const n={code:"code",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Sometimes you might want to have a plugin that isn't bundled in your CLI but gets installed the first time it's executed by the user - we call this just-in-time plugin installation, or JIT for short. This can be useful if you need to reduce the package size of your CLI while still allowing users access to all the plugins."}),"\n",(0,i.jsx)(n.p,{children:"To use this feature you need to:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Add ",(0,i.jsx)(n.code,{children:"jitPlugins"})," to the ",(0,i.jsx)(n.code,{children:"oclif"})," section of your package.json"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'"oclif": {\n "jitPlugins": {\n "my-plugin": "^1.2.3",\n "another-plugin": "^1.2.3",\n }\n}\n'})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Ensure that your build process includes generating a manifest using ",(0,i.jsx)(n.code,{children:"oclif manifest"}),". The manifest will include the information about all the commands owned by JIT plugins which allows users to run ",(0,i.jsx)(n.code,{children:"--help"})," on those commands without having them installed yet. ",(0,i.jsx)(n.strong,{children:"If the generated manifest doesn't get packed with your CLI, then the feature will not work."})]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Implement the ",(0,i.jsx)(n.code,{children:"jit_plugin_not_installed"})," hook."]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"@oclif/core"})," attempts to be UX-agnostic, meaning that we don't want to impose any particular user experience on you. Any time a user experience is required we utilize hooks so that you can design the exact user experience you want your users to have."]}),"\n",(0,i.jsx)(n.p,{children:"In the case of JIT plugin installation, there are many possible user experiences that you might want - maybe you want to prompt the user for confirmation first, or maybe you want to log a specific message, etc..."}),"\n",(0,i.jsx)(n.p,{children:"Here's an example of how you might implement the hook,"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"import { Hook, CLIError, ux } from '@oclif/core';\n\nconst hook: Hook<'jit_plugin_not_installed'> = async function (opts) {\n try {\n const answer = await ux.confirm(`${opts.command.pluginName} not installed. Would you like to install?`)\n if (answer === 'y') {\n await opts.config.runCommand('plugins:install', [`${opts.command.pluginName}@${opts.pluginVersion}`]);\n }\n } catch (error) {\n throw new CLIError(`Could not install ${opts.command.pluginName}`, 'JitPluginInstallError');\n }\n};\n\nexport default hook;\n\n"})})]})}function d(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(u,{...e})}):u(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>a});var i=t(6540);const o={},s=i.createContext(o);function l(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/1f61ef73.ed364500.js b/assets/js/1f61ef73.51af529c.js similarity index 97% rename from assets/js/1f61ef73.ed364500.js rename to assets/js/1f61ef73.51af529c.js index 6b2aa07e..79db76ac 100644 --- a/assets/js/1f61ef73.ed364500.js +++ b/assets/js/1f61ef73.51af529c.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5082],{492:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>s,default:()=>h,frontMatter:()=>c,metadata:()=>a,toc:()=>d});var o=r(4848),t=r(8453);const c={title:"Error Handling"},s=void 0,a={id:"error_handling",title:"Error Handling",description:"oclif handles intentionally - and unintentionally - thrown errors in two places. First in the Command.catch method and then, finally, in the bin/run catch handler where the Error is printed and the CLI exits. This error flow makes it possible for you to control and respond to errors that occur in your CLI as you see fit.",source:"@site/../docs/error_handling.md",sourceDirName:".",slug:"/error_handling",permalink:"/docs/error_handling",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/error_handling.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Error Handling"},sidebar:"docs",previous:{title:"Help Classes",permalink:"/docs/help_classes"},next:{title:"JSON",permalink:"/docs/json"}},i={},d=[{value:"Error Handling in thecatch
method",id:"error-handling-in-the-catch-method",level:2},{value:"bin/run.js catch
handler",id:"binrunjs-catch-handler",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["oclif handles intentionally - and unintentionally - thrown errors in two places. First in the ",(0,o.jsx)(n.code,{children:"Command.catch"})," method and then, finally, in the bin/run ",(0,o.jsx)(n.code,{children:"catch"})," handler where the Error is printed and the CLI exits. This error flow makes it possible for you to control and respond to errors that occur in your CLI as you see fit."]}),"\n",(0,o.jsxs)(n.h2,{id:"error-handling-in-the-catch-method",children:["Error Handling in the ",(0,o.jsx)(n.code,{children:"catch"})," method"]}),"\n",(0,o.jsxs)(n.p,{children:["Every ",(0,o.jsx)(n.code,{children:"Command"})," instance has a ",(0,o.jsx)(n.code,{children:"catch"})," method that is called when an error occurs throughout the course of a command run. This method handles the edge case of users asking for help or version output, if applicable, otherwise, it re-throws the error. You can extend or overwrite the ",(0,o.jsx)(n.code,{children:"catch"})," method in your command class."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:"import {Command, flags} from '@oclif/core'\n\nexport default class Hello extends Command {\n async catch(error) {\n // do something or\n // re-throw to be handled globally\n throw error;\n }\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["If this type of error handling is being implemented across multiple commands consider using a Custom Base Class (",(0,o.jsx)(n.a,{href:"https://oclif.io/docs/base_class#docsNav",children:"https://oclif.io/docs/base_class#docsNav"}),") for your commands and overriding the ",(0,o.jsx)(n.code,{children:"catch"})," method."]}),"\n",(0,o.jsxs)(n.h2,{id:"binrunjs-catch-handler",children:["bin/run.js ",(0,o.jsx)(n.code,{children:"catch"})," handler"]}),"\n",(0,o.jsxs)(n.p,{children:["Every oclif CLI has a ./bin/run.js file that is the entry point of command invocation. Errors that occur in the CLI, including re-thrown errors from a Command, are caught here in the bin/run.js ",(0,o.jsx)(n.code,{children:"catch"})," handler."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:".catch(require('@oclif/core/handle'))\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This catch handler uses the ",(0,o.jsx)(n.code,{children:"@oclif/errors/handle"})," function to display (and cleanup, if necessary) the error to the user. This handler can be swapped for any function that receives an error argument."]}),"\n",(0,o.jsxs)(n.p,{children:["If you chose to implement your own handler here, we still recommend you delegate finally to the ",(0,o.jsx)(n.code,{children:"@oclif/core/handle"})," function for clean-up and exiting logic."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:".catch((error) => {\n const oclifHandler = require('@oclif/core/handle');\n // do any extra work with error\n return oclifHandler(error);\n})\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,r)=>{r.d(n,{R:()=>s,x:()=>a});var o=r(6540);const t={},c=o.createContext(t);function s(e){const n=o.useContext(c);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),o.createElement(c.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5082],{492:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>i,contentTitle:()=>s,default:()=>h,frontMatter:()=>c,metadata:()=>a,toc:()=>d});var o=r(4848),t=r(8453);const c={title:"Error Handling"},s=void 0,a={id:"error_handling",title:"Error Handling",description:"oclif handles intentionally - and unintentionally - thrown errors in two places. First in the Command.catch method and then, finally, in the bin/run catch handler where the Error is printed and the CLI exits. This error flow makes it possible for you to control and respond to errors that occur in your CLI as you see fit.",source:"@site/../docs/error_handling.md",sourceDirName:".",slug:"/error_handling",permalink:"/docs/error_handling",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/error_handling.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Error Handling"},sidebar:"docs",previous:{title:"Help Classes",permalink:"/docs/help_classes"},next:{title:"JSON",permalink:"/docs/json"}},i={},d=[{value:"Error Handling in the catch
method",id:"error-handling-in-the-catch-method",level:2},{value:"bin/run.js catch
handler",id:"binrunjs-catch-handler",level:2}];function l(e){const n={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["oclif handles intentionally - and unintentionally - thrown errors in two places. First in the ",(0,o.jsx)(n.code,{children:"Command.catch"})," method and then, finally, in the bin/run ",(0,o.jsx)(n.code,{children:"catch"})," handler where the Error is printed and the CLI exits. This error flow makes it possible for you to control and respond to errors that occur in your CLI as you see fit."]}),"\n",(0,o.jsxs)(n.h2,{id:"error-handling-in-the-catch-method",children:["Error Handling in the ",(0,o.jsx)(n.code,{children:"catch"})," method"]}),"\n",(0,o.jsxs)(n.p,{children:["Every ",(0,o.jsx)(n.code,{children:"Command"})," instance has a ",(0,o.jsx)(n.code,{children:"catch"})," method that is called when an error occurs throughout the course of a command run. This method handles the edge case of users asking for help or version output, if applicable, otherwise, it re-throws the error. You can extend or overwrite the ",(0,o.jsx)(n.code,{children:"catch"})," method in your command class."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:"import {Command, flags} from '@oclif/core'\n\nexport default class Hello extends Command {\n async catch(error) {\n // do something or\n // re-throw to be handled globally\n throw error;\n }\n}\n"})}),"\n",(0,o.jsxs)(n.p,{children:["If this type of error handling is being implemented across multiple commands consider using a Custom Base Class (",(0,o.jsx)(n.a,{href:"https://oclif.io/docs/base_class#docsNav",children:"https://oclif.io/docs/base_class#docsNav"}),") for your commands and overriding the ",(0,o.jsx)(n.code,{children:"catch"})," method."]}),"\n",(0,o.jsxs)(n.h2,{id:"binrunjs-catch-handler",children:["bin/run.js ",(0,o.jsx)(n.code,{children:"catch"})," handler"]}),"\n",(0,o.jsxs)(n.p,{children:["Every oclif CLI has a ./bin/run.js file that is the entry point of command invocation. Errors that occur in the CLI, including re-thrown errors from a Command, are caught here in the bin/run.js ",(0,o.jsx)(n.code,{children:"catch"})," handler."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:".catch(require('@oclif/core/handle'))\n"})}),"\n",(0,o.jsxs)(n.p,{children:["This catch handler uses the ",(0,o.jsx)(n.code,{children:"@oclif/errors/handle"})," function to display (and cleanup, if necessary) the error to the user. This handler can be swapped for any function that receives an error argument."]}),"\n",(0,o.jsxs)(n.p,{children:["If you chose to implement your own handler here, we still recommend you delegate finally to the ",(0,o.jsx)(n.code,{children:"@oclif/core/handle"})," function for clean-up and exiting logic."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-js",children:".catch((error) => {\n const oclifHandler = require('@oclif/core/handle');\n // do any extra work with error\n return oclifHandler(error);\n})\n"})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,r)=>{r.d(n,{R:()=>s,x:()=>a});var o=r(6540);const t={},c=o.createContext(t);function s(e){const n=o.useContext(c);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),o.createElement(c.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2486267b.f4424fc4.js b/assets/js/2486267b.0ba0fb70.js
similarity index 96%
rename from assets/js/2486267b.f4424fc4.js
rename to assets/js/2486267b.0ba0fb70.js
index 9518951e..94e46b4a 100644
--- a/assets/js/2486267b.f4424fc4.js
+++ b/assets/js/2486267b.0ba0fb70.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9e3],{7413:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var n=s(4848),o=s(8453);const i={title:"Spinner"},r=void 0,c={id:"spinner",title:"Spinner",description:"@oclif/core provides a simple ux.action, for more complex progress indicators we recommend using the listr library.",source:"@site/../docs/spinner.md",sourceDirName:".",slug:"/spinner",permalink:"/docs/spinner",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/spinner.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Spinner"},sidebar:"docs",previous:{title:"Prompting",permalink:"/docs/prompting"},next:{title:"Table",permalink:"/docs/table"}},a={},d=[{value:"ux.action
",id:"uxaction",level:2},{value:"listr",id:"listr",level:2}];function l(e){const t={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://github.com/oclif/core",children:"@oclif/core"})," provides a simple ",(0,n.jsx)(t.code,{children:"ux.action"}),", for more complex progress indicators we recommend using the ",(0,n.jsx)(t.a,{href:"https://www.npmjs.com/package/listr",children:"listr"})," library."]}),"\n",(0,n.jsx)(t.h2,{id:"uxaction",children:(0,n.jsx)(t.code,{children:"ux.action"})}),"\n",(0,n.jsx)(t.p,{children:"Shows a basic spinner"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\n\nexport class MyCommand extends Command {\n async run() {\n // start the spinner\n ux.action.start('starting a process')\n // do some action...\n // stop the spinner\n ux.action.stop() // shows 'starting a process... done'\n\n // show on stdout instead of stderr\n ux.action.start('starting a process', 'initializing', {stdout: true})\n // do some action...\n // stop the spinner with a custom message\n ux.action.stop('custom message') // shows 'starting a process... custom message'\n }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"This degrades gracefully when not connected to a TTY. It queues up any writes to stdout/stderr so they are displayed above the spinner."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"action demo",src:s(262).A+"",width:"563",height:"271"})}),"\n",(0,n.jsx)(t.h2,{id:"listr",children:"listr"}),"\n",(0,n.jsxs)(t.p,{children:["Here is an example of the complex workflows supported by ",(0,n.jsx)(t.a,{href:"https://www.npmjs.com/package/listr",children:"listr"}),"."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"listr demo",src:s(1146).A+"",width:"1177",height:"709"})})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},262:(e,t,s)=>{s.d(t,{A:()=>n});const n=s.p+"assets/images/action-3dc2f1c9da2526e7dacc7ba55a2e3f5a.gif"},1146:(e,t,s)=>{s.d(t,{A:()=>n});const n=s.p+"assets/images/listr-fb034a43c5d3159c331547ffba3b6559.gif"},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>c});var n=s(6540);const o={},i=n.createContext(o);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9e3],{7413:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var n=s(4848),o=s(8453);const i={title:"Spinner"},r=void 0,c={id:"spinner",title:"Spinner",description:"@oclif/core provides a simple ux.action, for more complex progress indicators we recommend using the listr library.",source:"@site/../docs/spinner.md",sourceDirName:".",slug:"/spinner",permalink:"/docs/spinner",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/spinner.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Spinner"},sidebar:"docs",previous:{title:"Prompting",permalink:"/docs/prompting"},next:{title:"Table",permalink:"/docs/table"}},a={},d=[{value:"ux.action
",id:"uxaction",level:2},{value:"listr",id:"listr",level:2}];function l(e){const t={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://github.com/oclif/core",children:"@oclif/core"})," provides a simple ",(0,n.jsx)(t.code,{children:"ux.action"}),", for more complex progress indicators we recommend using the ",(0,n.jsx)(t.a,{href:"https://www.npmjs.com/package/listr",children:"listr"})," library."]}),"\n",(0,n.jsx)(t.h2,{id:"uxaction",children:(0,n.jsx)(t.code,{children:"ux.action"})}),"\n",(0,n.jsx)(t.p,{children:"Shows a basic spinner"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\n\nexport class MyCommand extends Command {\n async run() {\n // start the spinner\n ux.action.start('starting a process')\n // do some action...\n // stop the spinner\n ux.action.stop() // shows 'starting a process... done'\n\n // show on stdout instead of stderr\n ux.action.start('starting a process', 'initializing', {stdout: true})\n // do some action...\n // stop the spinner with a custom message\n ux.action.stop('custom message') // shows 'starting a process... custom message'\n }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"This degrades gracefully when not connected to a TTY. It queues up any writes to stdout/stderr so they are displayed above the spinner."}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"action demo",src:s(262).A+"",width:"563",height:"271"})}),"\n",(0,n.jsx)(t.h2,{id:"listr",children:"listr"}),"\n",(0,n.jsxs)(t.p,{children:["Here is an example of the complex workflows supported by ",(0,n.jsx)(t.a,{href:"https://www.npmjs.com/package/listr",children:"listr"}),"."]}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"listr demo",src:s(1146).A+"",width:"1177",height:"709"})})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},262:(e,t,s)=>{s.d(t,{A:()=>n});const n=s.p+"assets/images/action-3dc2f1c9da2526e7dacc7ba55a2e3f5a.gif"},1146:(e,t,s)=>{s.d(t,{A:()=>n});const n=s.p+"assets/images/listr-fb034a43c5d3159c331547ffba3b6559.gif"},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>c});var n=s(6540);const o={},i=n.createContext(o);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/258a6413.25eadca6.js b/assets/js/258a6413.15131eb9.js
similarity index 94%
rename from assets/js/258a6413.25eadca6.js
rename to assets/js/258a6413.15131eb9.js
index 83e226e7..6f75f2b6 100644
--- a/assets/js/258a6413.25eadca6.js
+++ b/assets/js/258a6413.15131eb9.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3651],{5453:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>m,frontMatter:()=>i,metadata:()=>a,toc:()=>r});var o=n(4848),s=n(8453);const i={title:"Single Command CLI"},c=void 0,a={id:"single_command_cli",title:"Single Command CLI",description:"Sometimes you may want your CLI's executable to also be the only command, similar to many bash utilities like ls or cat.",source:"@site/../docs/single_command_cli.md",sourceDirName:".",slug:"/single_command_cli",permalink:"/docs/single_command_cli",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/single_command_cli.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Single Command CLI"},sidebar:"docs",previous:{title:"Global Flags",permalink:"/docs/global_flags"},next:{title:"ESM",permalink:"/docs/esm"}},l={},r=[];function d(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["Sometimes you may want your CLI's executable to also be the only command, similar to many bash utilities like ",(0,o.jsx)(t.code,{children:"ls"})," or ",(0,o.jsx)(t.code,{children:"cat"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["To support this, you will need to put your command logic into ",(0,o.jsx)(t.code,{children:"src/index.ts"})," and add the following to the oclif section of your package.json:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "single",\n "target": "./dist/index.js"\n }\n }\n}\n'})}),"\n",(0,o.jsxs)(t.p,{children:["See ",(0,o.jsx)(t.a,{href:"./command_discovery_strategies",children:"Command Discovery Strategies"})," for more details."]})]})}function m(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function c(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3651],{5453:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>m,frontMatter:()=>i,metadata:()=>a,toc:()=>r});var o=n(4848),s=n(8453);const i={title:"Single Command CLI"},c=void 0,a={id:"single_command_cli",title:"Single Command CLI",description:"Sometimes you may want your CLI's executable to also be the only command, similar to many bash utilities like ls or cat.",source:"@site/../docs/single_command_cli.md",sourceDirName:".",slug:"/single_command_cli",permalink:"/docs/single_command_cli",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/single_command_cli.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Single Command CLI"},sidebar:"docs",previous:{title:"Global Flags",permalink:"/docs/global_flags"},next:{title:"ESM",permalink:"/docs/esm"}},l={},r=[];function d(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["Sometimes you may want your CLI's executable to also be the only command, similar to many bash utilities like ",(0,o.jsx)(t.code,{children:"ls"})," or ",(0,o.jsx)(t.code,{children:"cat"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["To support this, you will need to put your command logic into ",(0,o.jsx)(t.code,{children:"src/index.ts"})," and add the following to the oclif section of your package.json:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "single",\n "target": "./dist/index.js"\n }\n }\n}\n'})}),"\n",(0,o.jsxs)(t.p,{children:["See ",(0,o.jsx)(t.a,{href:"./command_discovery_strategies",children:"Command Discovery Strategies"})," for more details."]})]})}function m(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function c(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2a33acc4.376963de.js b/assets/js/2a33acc4.ed23e4e6.js
similarity index 97%
rename from assets/js/2a33acc4.376963de.js
rename to assets/js/2a33acc4.ed23e4e6.js
index 497d225d..e317b8a0 100644
--- a/assets/js/2a33acc4.376963de.js
+++ b/assets/js/2a33acc4.ed23e4e6.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[1427],{2130:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>n,metadata:()=>r,toc:()=>d});var o=s(4848),i=s(8453);const n={title:"Topics"},c=void 0,r={id:"topics",title:"Topics",description:"As CLIs grow it can be useful to nest commands within topics. This is supported simply by placing command files in subdirectories. For example, with the Salesforce CLI we have a topic sf config with commands like sf config set and sf config get. The directory structure looks like this:",source:"@site/../docs/topics.md",sourceDirName:".",slug:"/topics",permalink:"/docs/topics",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/topics.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Topics"},sidebar:"docs",previous:{title:"Configuration",permalink:"/docs/config"},next:{title:"Topic Separators",permalink:"/docs/topic_separator"}},a={},d=[];function p(e){const t={code:"code",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["As CLIs grow it can be useful to nest commands within topics. This is supported simply by placing command files in subdirectories. For example, with the Salesforce CLI we have a topic ",(0,o.jsx)(t.code,{children:"sf config"})," with commands like ",(0,o.jsx)(t.code,{children:"sf config set"})," and ",(0,o.jsx)(t.code,{children:"sf config get"}),". The directory structure looks like this:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:"package.json\nsrc/\n\u2514\u2500\u2500 commands/\n \u2514\u2500\u2500 config/\n \xa0 \u251c\u2500\u2500 index.ts\n \xa0\xa0\u251c\u2500\u2500 set.ts\n \xa0\xa0 \u2514\u2500\u2500 get.ts\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The help descriptions will be the description of the first command within a directory. If you'd like to customize the help description, add it to the ",(0,o.jsx)(t.code,{children:"package.json"})," like so:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-js",children:'{\n "oclif": {\n "topics": {\n "apps:favorites": { "description": "manage favorite apps" },\n "config": { "description": "manage heroku config variables" },\n }\n }\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"Subtopics can be created by making subdirectories within topic directories, but for UX reasons we generally discourage going more than 1 or 2 levels deep even for the largest CLIs."})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(p,{...e})}):p(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>c,x:()=>r});var o=s(6540);const i={},n=o.createContext(i);function c(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[1427],{2130:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>n,metadata:()=>r,toc:()=>d});var o=s(4848),i=s(8453);const n={title:"Topics"},c=void 0,r={id:"topics",title:"Topics",description:"As CLIs grow it can be useful to nest commands within topics. This is supported simply by placing command files in subdirectories. For example, with the Salesforce CLI we have a topic sf config with commands like sf config set and sf config get. The directory structure looks like this:",source:"@site/../docs/topics.md",sourceDirName:".",slug:"/topics",permalink:"/docs/topics",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/topics.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Topics"},sidebar:"docs",previous:{title:"Configuration",permalink:"/docs/config"},next:{title:"Topic Separators",permalink:"/docs/topic_separator"}},a={},d=[];function p(e){const t={code:"code",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["As CLIs grow it can be useful to nest commands within topics. This is supported simply by placing command files in subdirectories. For example, with the Salesforce CLI we have a topic ",(0,o.jsx)(t.code,{children:"sf config"})," with commands like ",(0,o.jsx)(t.code,{children:"sf config set"})," and ",(0,o.jsx)(t.code,{children:"sf config get"}),". The directory structure looks like this:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:"package.json\nsrc/\n\u2514\u2500\u2500 commands/\n \u2514\u2500\u2500 config/\n \xa0 \u251c\u2500\u2500 index.ts\n \xa0\xa0\u251c\u2500\u2500 set.ts\n \xa0\xa0 \u2514\u2500\u2500 get.ts\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The help descriptions will be the description of the first command within a directory. If you'd like to customize the help description, add it to the ",(0,o.jsx)(t.code,{children:"package.json"})," like so:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-js",children:'{\n "oclif": {\n "topics": {\n "apps:favorites": { "description": "manage favorite apps" },\n "config": { "description": "manage heroku config variables" },\n }\n }\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"Subtopics can be created by making subdirectories within topic directories, but for UX reasons we generally discourage going more than 1 or 2 levels deep even for the largest CLIs."})]})}function l(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(p,{...e})}):p(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>c,x:()=>r});var o=s(6540);const i={},n=o.createContext(i);function c(e){const t=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),o.createElement(n.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/2f98ad87.be46cc71.js b/assets/js/2f98ad87.c0493a32.js
similarity index 96%
rename from assets/js/2f98ad87.be46cc71.js
rename to assets/js/2f98ad87.c0493a32.js
index 3b3a9445..ebe2657c 100644
--- a/assets/js/2f98ad87.be46cc71.js
+++ b/assets/js/2f98ad87.c0493a32.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8664],{2678:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>m,frontMatter:()=>c,metadata:()=>i,toc:()=>l});var t=o(4848),r=o(8453);const c={title:"Generator Commands"},a=void 0,i={id:"generator_commands",title:"Generator Commands",description:"- oclif generate NAME",source:"@site/../docs/generator_commands.md",sourceDirName:".",slug:"/generator_commands",permalink:"/docs/generator_commands",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/generator_commands.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Generator Commands"},sidebar:"docs",previous:{title:"FAQs",permalink:"/docs/faqs"},next:{title:"Command Execution",permalink:"/docs/command_execution"}},d={},l=[{value:"oclif generate NAME
",id:"oclif-generate-name",level:2},{value:"oclif generate command NAME
",id:"oclif-generate-command-name",level:2},{value:"oclif generate hook NAME
",id:"oclif-generate-hook-name",level:2}];function s(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#oclif-generate-name",children:(0,t.jsx)(n.code,{children:"oclif generate NAME"})})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#oclif-generate-command-name",children:(0,t.jsx)(n.code,{children:"oclif generate command NAME"})})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#oclif-generate-hook-name",children:(0,t.jsx)(n.code,{children:"oclif generate hook NAME"})})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"oclif-generate-name",children:(0,t.jsx)(n.code,{children:"oclif generate NAME"})}),"\n",(0,t.jsx)(n.p,{children:"generate a new CLI"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"USAGE\n $ oclif generate [NAME]\n\nARGUMENTS\n NAME directory name of new project\n\nDESCRIPTION\n generate a new CLI\n\n This will clone the template repo 'oclif/hello-world' and update package properties\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.em,{children:["See code: ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/oclif/blob/v2.2.0/src/commands/generate.ts",children:"src/commands/generate.ts"})]})}),"\n",(0,t.jsx)(n.h2,{id:"oclif-generate-command-name",children:(0,t.jsx)(n.code,{children:"oclif generate command NAME"})}),"\n",(0,t.jsx)(n.p,{children:"add a command to an existing CLI or plugin"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"USAGE\n $ oclif generate command [NAME] [--force]\n\nARGUMENTS\n NAME name of command\n\nFLAGS\n --force overwrite existing files\n\nDESCRIPTION\n add a command to an existing CLI or plugin\n"})}),"\n",(0,t.jsx)(n.h2,{id:"oclif-generate-hook-name",children:(0,t.jsx)(n.code,{children:"oclif generate hook NAME"})}),"\n",(0,t.jsx)(n.p,{children:"add a hook to an existing CLI or plugin"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"USAGE\n $ oclif generate hook [NAME] [--force] [--event oclif generate NAME
",id:"oclif-generate-name",level:2},{value:"oclif generate command NAME
",id:"oclif-generate-command-name",level:2},{value:"oclif generate hook NAME
",id:"oclif-generate-hook-name",level:2}];function s(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#oclif-generate-name",children:(0,t.jsx)(n.code,{children:"oclif generate NAME"})})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#oclif-generate-command-name",children:(0,t.jsx)(n.code,{children:"oclif generate command NAME"})})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"#oclif-generate-hook-name",children:(0,t.jsx)(n.code,{children:"oclif generate hook NAME"})})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"oclif-generate-name",children:(0,t.jsx)(n.code,{children:"oclif generate NAME"})}),"\n",(0,t.jsx)(n.p,{children:"generate a new CLI"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"USAGE\n $ oclif generate [NAME]\n\nARGUMENTS\n NAME directory name of new project\n\nDESCRIPTION\n generate a new CLI\n\n This will clone the template repo 'oclif/hello-world' and update package properties\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsxs)(n.em,{children:["See code: ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/oclif/blob/v2.2.0/src/commands/generate.ts",children:"src/commands/generate.ts"})]})}),"\n",(0,t.jsx)(n.h2,{id:"oclif-generate-command-name",children:(0,t.jsx)(n.code,{children:"oclif generate command NAME"})}),"\n",(0,t.jsx)(n.p,{children:"add a command to an existing CLI or plugin"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"USAGE\n $ oclif generate command [NAME] [--force]\n\nARGUMENTS\n NAME name of command\n\nFLAGS\n --force overwrite existing files\n\nDESCRIPTION\n add a command to an existing CLI or plugin\n"})}),"\n",(0,t.jsx)(n.h2,{id:"oclif-generate-hook-name",children:(0,t.jsx)(n.code,{children:"oclif generate hook NAME"})}),"\n",(0,t.jsx)(n.p,{children:"add a hook to an existing CLI or plugin"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"USAGE\n $ oclif generate hook [NAME] [--force] [--event pattern
Strategy",id:"pattern-strategy",level:3},{value:"explicit
Strategy",id:"explicit-strategy",level:3},{value:"Hooks",id:"hooks",level:4},{value:"Bundling",id:"bundling",level:4},{value:"single
Strategy",id:"single-strategy",level:3},{value:"Note about oclif.manifest.json
",id:"note-about-oclifmanifestjson",level:3}];function r(e){const n={a:"a",code:"code",em:"em",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"When oclif loads a plugin is must find all the commands within that plugin that can be executed. There a three strategies for discovering these commands:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"pattern"})," - this is the default behavior that finds commands based on glob patterns."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"explicit"})," - find commands that are exported from a specified file."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"single"})," - CLI contains a single command executed by top-level bin."]}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"pattern-strategy",children:[(0,t.jsx)(n.code,{children:"pattern"})," Strategy"]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"pattern"})," strategy tells oclif to use a predefined set of globs to find command files in a specified directory. This is the default behavior of oclif unless otherwise stated."]}),"\n",(0,t.jsxs)(n.p,{children:["Plugins can point the ",(0,t.jsx)(n.code,{children:"commands"})," property to a directory"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": "./dist/commands",\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["This will tell oclif to look for commands in that directory (this is skipped if an ",(0,t.jsx)(n.code,{children:"oclif.manifest.json"})," is present)"]}),"\n",(0,t.jsx)(n.p,{children:"Alternatively, you can set this configuration which will do the exact same thing:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "pattern",\n "target": "./dist/commands"\n }\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You also have the ability to set ",(0,t.jsx)(n.code,{children:"globPatterns"}),", which override the glob patterns that oclif uses when searching for command files:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "pattern",\n "target": "./dist/commands",\n "globPatterns": [\n "**/*.+(js|cjs|mjs|ts|tsx|mts|cts)",\n "!**/*.+(d.*|test.*|spec.*|helpers.*)?(x)"\n ]\n }\n }\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"This is useful if you like to put test or helper files in the same directory as your command files."}),"\n",(0,t.jsxs)(n.h3,{id:"explicit-strategy",children:[(0,t.jsx)(n.code,{children:"explicit"})," Strategy"]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"explicit"})," strategy tells oclif to import commands from a single file. In this case the ",(0,t.jsx)(n.code,{children:"target"})," is the file that exports the commands and ",(0,t.jsx)(n.code,{children:"identifier"})," is the name of the export (defaults to ",(0,t.jsx)(n.code,{children:"default"}),")."]}),"\n",(0,t.jsxs)(n.p,{children:["To use this you would add a new file (e.g. ",(0,t.jsx)(n.code,{children:"src/commands.ts"}),") and then add this configuration to the package.json"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "explicit",\n "target": "./dist/index.js",\n "identifier": "COMMANDS",\n }\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"src/index.ts"})," would then need to have an export with the same name as the ",(0,t.jsx)(n.code,{children:"identifier"})," (if not set, it defaults to ",(0,t.jsx)(n.code,{children:"default"}),") that's an object of command names to command classes, e.g."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import Hello from './commands/hello'\nimport HelloWorld from './commands/hello/world'\n\nexport const COMMANDS = {\n hello: Hello,\n 'hello:world': HelloWorld,\n howdy: Hello, // alias the `hello` command to `howdy`\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"explicit"})," strategy is useful to those who can't rely on file paths because they've bundled their code (see ",(0,t.jsx)(n.a,{href:"#bundling",children:"Bundling"}),') but it can also be used if you simply prefer to be more explicit about your commands instead of relying on oclif "magically" finding commands from the file system.']}),"\n",(0,t.jsxs)(n.p,{children:["It can also be leveraged to create or modify commands at runtime (e.g. internationalize messages at runtime or add flags to a command based on an API spec - see ",(0,t.jsx)(n.code,{children:"oclif + dynamic commands"})," section below)."]}),"\n",(0,t.jsx)(n.h4,{id:"hooks",children:"Hooks"}),"\n",(0,t.jsxs)(n.p,{children:["Hooks can also be defined using the ",(0,t.jsx)(n.code,{children:"explicit"})," strategy:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'"oclif": {\n "hooks": {\n "init": {\n "target": "./dist/index.js",\n "identifier": "INIT_HOOK"\n }\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"// src/index.ts\nimport Hello from './commands/hello'\nimport HelloWorld from './commands/hello/world'\nexport {default as INIT_HOOK} from './hooks/init/init.js'\n\nexport const COMMANDS = {\n hello: Hello,\n 'hello:world': HelloWorld,\n howdy: Hello, // alias the `hello` command to `howdy`\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["That configuration is essentially telling oclif to look for an ",(0,t.jsx)(n.code,{children:"INIT_HOOK"})," export inside of ",(0,t.jsx)(n.code,{children:"./dist/index.js"})]}),"\n",(0,t.jsx)(n.h4,{id:"bundling",children:"Bundling"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"We do not support bundling"})," given the endless number of tools + configurations that could be used. But if you choose to use a bundler, like ",(0,t.jsx)(n.code,{children:"esbuild"})," there are a couple hard requirements - you must have a package.json in your root directory and a ",(0,t.jsx)(n.code,{children:"bin/run"})," or ",(0,t.jsx)(n.code,{children:"bin/run.js"})," bin script. ",(0,t.jsx)(n.em,{children:"This means that you will not be able to successfully bundle your entire CLI (src code, package.json, node_modules, etc) into a single file."})]}),"\n",(0,t.jsxs)(n.p,{children:["If you want to use a bundler, you can see this ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/plugin-test-esbuild/",children:"example repo"}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"single-strategy",children:[(0,t.jsx)(n.code,{children:"single"})," Strategy"]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"single"})," strategy tells oclif that this CLI contains a single command that can be executed by the ",(0,t.jsx)(n.code,{children:"bin/run.js"})," (e.g. ",(0,t.jsx)(n.code,{children:"ls"})," or ",(0,t.jsx)(n.code,{children:"cat"}),")."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "single",\n "target": "./dist/index.js"\n }\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["In this example, ",(0,t.jsx)(n.code,{children:"./dist/index.js"})," exports the command class."]}),"\n",(0,t.jsxs)(n.h3,{id:"note-about-oclifmanifestjson",children:["Note about ",(0,t.jsx)(n.code,{children:"oclif.manifest.json"})]}),"\n",(0,t.jsxs)(n.p,{children:["For all strategies, the ",(0,t.jsx)(n.code,{children:"oclif.manifest.json"})," will be used to load the commands instead of the default behavior of the strategy."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(r,{...e})}):r(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>d});var t=s(6540);const o={},i=t.createContext(o);function l(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4260],{3602:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>d,toc:()=>a});var t=s(4848),o=s(8453);const i={title:"Command Discovery Strategies"},l=void 0,d={id:"command_discovery_strategies",title:"Command Discovery Strategies",description:"When oclif loads a plugin is must find all the commands within that plugin that can be executed. There a three strategies for discovering these commands:",source:"@site/../docs/command_discovery_strategies.md",sourceDirName:".",slug:"/command_discovery_strategies",permalink:"/docs/command_discovery_strategies",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/command_discovery_strategies.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Command Discovery Strategies"},sidebar:"docs",previous:{title:"Plugin Loading",permalink:"/docs/plugin_loading"},next:{title:"Commands",permalink:"/docs/commands"}},c={},a=[{value:"pattern
Strategy",id:"pattern-strategy",level:3},{value:"explicit
Strategy",id:"explicit-strategy",level:3},{value:"Hooks",id:"hooks",level:4},{value:"Bundling",id:"bundling",level:4},{value:"single
Strategy",id:"single-strategy",level:3},{value:"Note about oclif.manifest.json
",id:"note-about-oclifmanifestjson",level:3}];function r(e){const n={a:"a",code:"code",em:"em",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"When oclif loads a plugin is must find all the commands within that plugin that can be executed. There a three strategies for discovering these commands:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"pattern"})," - this is the default behavior that finds commands based on glob patterns."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"explicit"})," - find commands that are exported from a specified file."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"single"})," - CLI contains a single command executed by top-level bin."]}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"pattern-strategy",children:[(0,t.jsx)(n.code,{children:"pattern"})," Strategy"]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"pattern"})," strategy tells oclif to use a predefined set of globs to find command files in a specified directory. This is the default behavior of oclif unless otherwise stated."]}),"\n",(0,t.jsxs)(n.p,{children:["Plugins can point the ",(0,t.jsx)(n.code,{children:"commands"})," property to a directory"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": "./dist/commands",\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["This will tell oclif to look for commands in that directory (this is skipped if an ",(0,t.jsx)(n.code,{children:"oclif.manifest.json"})," is present)"]}),"\n",(0,t.jsx)(n.p,{children:"Alternatively, you can set this configuration which will do the exact same thing:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "pattern",\n "target": "./dist/commands"\n }\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You also have the ability to set ",(0,t.jsx)(n.code,{children:"globPatterns"}),", which override the glob patterns that oclif uses when searching for command files:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "pattern",\n "target": "./dist/commands",\n "globPatterns": [\n "**/*.+(js|cjs|mjs|ts|tsx|mts|cts)",\n "!**/*.+(d.*|test.*|spec.*|helpers.*)?(x)"\n ]\n }\n }\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"This is useful if you like to put test or helper files in the same directory as your command files."}),"\n",(0,t.jsxs)(n.h3,{id:"explicit-strategy",children:[(0,t.jsx)(n.code,{children:"explicit"})," Strategy"]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"explicit"})," strategy tells oclif to import commands from a single file. In this case the ",(0,t.jsx)(n.code,{children:"target"})," is the file that exports the commands and ",(0,t.jsx)(n.code,{children:"identifier"})," is the name of the export (defaults to ",(0,t.jsx)(n.code,{children:"default"}),")."]}),"\n",(0,t.jsxs)(n.p,{children:["To use this you would add a new file (e.g. ",(0,t.jsx)(n.code,{children:"src/commands.ts"}),") and then add this configuration to the package.json"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "explicit",\n "target": "./dist/index.js",\n "identifier": "COMMANDS",\n }\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"src/index.ts"})," would then need to have an export with the same name as the ",(0,t.jsx)(n.code,{children:"identifier"})," (if not set, it defaults to ",(0,t.jsx)(n.code,{children:"default"}),") that's an object of command names to command classes, e.g."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import Hello from './commands/hello'\nimport HelloWorld from './commands/hello/world'\n\nexport const COMMANDS = {\n hello: Hello,\n 'hello:world': HelloWorld,\n howdy: Hello, // alias the `hello` command to `howdy`\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"explicit"})," strategy is useful to those who can't rely on file paths because they've bundled their code (see ",(0,t.jsx)(n.a,{href:"#bundling",children:"Bundling"}),') but it can also be used if you simply prefer to be more explicit about your commands instead of relying on oclif "magically" finding commands from the file system.']}),"\n",(0,t.jsxs)(n.p,{children:["It can also be leveraged to create or modify commands at runtime (e.g. internationalize messages at runtime or add flags to a command based on an API spec - see ",(0,t.jsx)(n.code,{children:"oclif + dynamic commands"})," section below)."]}),"\n",(0,t.jsx)(n.h4,{id:"hooks",children:"Hooks"}),"\n",(0,t.jsxs)(n.p,{children:["Hooks can also be defined using the ",(0,t.jsx)(n.code,{children:"explicit"})," strategy:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'"oclif": {\n "hooks": {\n "init": {\n "target": "./dist/index.js",\n "identifier": "INIT_HOOK"\n }\n }\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"// src/index.ts\nimport Hello from './commands/hello'\nimport HelloWorld from './commands/hello/world'\nexport {default as INIT_HOOK} from './hooks/init/init.js'\n\nexport const COMMANDS = {\n hello: Hello,\n 'hello:world': HelloWorld,\n howdy: Hello, // alias the `hello` command to `howdy`\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["That configuration is essentially telling oclif to look for an ",(0,t.jsx)(n.code,{children:"INIT_HOOK"})," export inside of ",(0,t.jsx)(n.code,{children:"./dist/index.js"})]}),"\n",(0,t.jsx)(n.h4,{id:"bundling",children:"Bundling"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"We do not support bundling"})," given the endless number of tools + configurations that could be used. But if you choose to use a bundler, like ",(0,t.jsx)(n.code,{children:"esbuild"})," there are a couple hard requirements - you must have a package.json in your root directory and a ",(0,t.jsx)(n.code,{children:"bin/run"})," or ",(0,t.jsx)(n.code,{children:"bin/run.js"})," bin script. ",(0,t.jsx)(n.em,{children:"This means that you will not be able to successfully bundle your entire CLI (src code, package.json, node_modules, etc) into a single file."})]}),"\n",(0,t.jsxs)(n.p,{children:["If you want to use a bundler, you can see this ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/plugin-test-esbuild/",children:"example repo"}),"."]}),"\n",(0,t.jsxs)(n.h3,{id:"single-strategy",children:[(0,t.jsx)(n.code,{children:"single"})," Strategy"]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"single"})," strategy tells oclif that this CLI contains a single command that can be executed by the ",(0,t.jsx)(n.code,{children:"bin/run.js"})," (e.g. ",(0,t.jsx)(n.code,{children:"ls"})," or ",(0,t.jsx)(n.code,{children:"cat"}),")."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "oclif": {\n "commands": {\n "strategy": "single",\n "target": "./dist/index.js"\n }\n }\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["In this example, ",(0,t.jsx)(n.code,{children:"./dist/index.js"})," exports the command class."]}),"\n",(0,t.jsxs)(n.h3,{id:"note-about-oclifmanifestjson",children:["Note about ",(0,t.jsx)(n.code,{children:"oclif.manifest.json"})]}),"\n",(0,t.jsxs)(n.p,{children:["For all strategies, the ",(0,t.jsx)(n.code,{children:"oclif.manifest.json"})," will be used to load the commands instead of the default behavior of the strategy."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(r,{...e})}):r(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>d});var t=s(6540);const o={},i=t.createContext(o);function l(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:l(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/32060389.1eb0ee8b.js b/assets/js/32060389.cc2c1970.js
similarity index 98%
rename from assets/js/32060389.1eb0ee8b.js
rename to assets/js/32060389.cc2c1970.js
index a9af268f..bcb977ab 100644
--- a/assets/js/32060389.1eb0ee8b.js
+++ b/assets/js/32060389.cc2c1970.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7996],{1916:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var t=s(4848),a=s(8453);const o={title:"Table"},r=void 0,i={id:"table",title:"Table",description:"ux.table",source:"@site/../docs/table.md",sourceDirName:".",slug:"/table",permalink:"/docs/table",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/table.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Table"},sidebar:"docs",previous:{title:"Spinner",permalink:"/docs/spinner"},next:{title:"Notifications",permalink:"/docs/notifications"}},l={},c=[{value:"ux.table
",id:"uxtable",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"uxtable",children:(0,t.jsx)(n.code,{children:"ux.table"})}),"\n",(0,t.jsx)(n.p,{children:"Displays tabular data"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"ux.table(data, columns, options)\n"})}),"\n",(0,t.jsx)(n.p,{children:"Where:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"data"}),": array of data objects to display"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"columns"}),": ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/cli-ux/styled/table.ts",children:"Table.Columns"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"options"}),": ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/cli-ux/styled/table.ts",children:"Table.Options"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ux.table.flags()"})," returns an object containing all the table flags to include in your command."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"{\n columns: Flags.string({exclusive: ['additional'], description: 'only show provided columns (comma-seperated)'}),\n sort: Flags.string({description: 'property to sort by (prepend '-' for descending)'}),\n filter: Flags.string({description: 'filter property by partial string matching, ex: name=foo'}),\n csv: Flags.boolean({exclusive: ['no-truncate'], description: 'output is csv format'}),\n extended: Flags.boolean({char: 'x', description: 'show extra columns'}),\n 'no-truncate': Flags.boolean({exclusive: ['csv'], description: 'do not truncate output to fit screen'}),\n 'no-header': Flags.boolean({exclusive: ['csv'], description: 'hide table header from output'}),\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Passing ",(0,t.jsx)(n.code,{children:"{only: ['columns']}"})," or ",(0,t.jsx)(n.code,{children:"{except: ['columns']}"})," as an argument into ",(0,t.jsx)(n.code,{children:"cli.table.flags()"})," will allow/block those flags from the returned object."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ux.Table.Columns"})," defines the table columns and their display options."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const columns: ux.Table.Columns = {\n // where `.name` is a property of a data object\n name: {}, // \"Name\" inferred as the column header\n id: {\n header: 'ID', // override column header\n minWidth: '10', // column must display at this width or greater\n extended: true, // only display this column when the --extended flag is present\n get: row => `US-O1-${row.id}`, // custom getter for data row object\n },\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ux.Table.Options"})," defines the table options, most of which are the parsed flags from the user for display customization, all of which are optional."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const options: ux.Table.Options = {\n printLine: myLogger, // custom logger\n columns: flags.columns,\n sort: flags.sort,\n filter: flags.filter,\n csv: flags.csv,\n extended: flags.extended,\n 'no-truncate': flags['no-truncate'],\n 'no-header': flags['no-header'],\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Example class:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\nimport axios from 'axios'\n\nexport default class Users extends Command {\n static flags = {\n ...ux.table.flags()\n }\n\n async run() {\n const {flags} = await this.parse(Users)\n const {data: users} = await axios.get('https://jsonplaceholder.typicode.com/users')\n\n ux.table(users, {\n name: {\n minWidth: 7,\n },\n company: {\n get: row => row.company && row.company.name\n },\n id: {\n header: 'ID',\n extended: true\n }\n }, {\n printLine: this.log.bind(this),\n ...flags, // parsed flags\n })\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Displays:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:'$ example-cli users\nName Company\nLeanne Graham Romaguera-Crona\nErvin Howell Deckow-Crist\nClementine Bauch Romaguera-Jacobson\nPatricia Lebsack Robel-Corkery\nChelsey Dietrich Keebler LLC\nMrs. Dennis Schulist Considine-Lockman\nKurtis Weissnat Johns Group\nNicholas Runolfsdottir V Abernathy Group\nGlenna Reichert Yost and Sons\nClementina DuBuque Hoeger LLC\n\n$ example-cli users --extended\nName Company ID\nLeanne Graham Romaguera-Crona 1\nErvin Howell Deckow-Crist 2\nClementine Bauch Romaguera-Jacobson 3\nPatricia Lebsack Robel-Corkery 4\nChelsey Dietrich Keebler LLC 5\nMrs. Dennis Schulist Considine-Lockman 6\nKurtis Weissnat Johns Group 7\nNicholas Runolfsdottir V Abernathy Group 8\nGlenna Reichert Yost and Sons 9\nClementina DuBuque Hoeger LLC 10\n\n$ example-cli users --columns=name\nName\nLeanne Graham\nErvin Howell\nClementine Bauch\nPatricia Lebsack\nChelsey Dietrich\nMrs. Dennis Schulist\nKurtis Weissnat\nNicholas Runolfsdottir V\nGlenna Reichert\nClementina DuBuque\n\n$ example-cli users --filter="company=Group"\nName Company\nKurtis Weissnat Johns Group\nNicholas Runolfsdottir V Abernathy Group\n\n$ example-cli users --sort=company\nName Company\nNicholas Runolfsdottir V Abernathy Group\nMrs. Dennis Schulist Considine-Lockman\nErvin Howell Deckow-Crist\nClementina DuBuque Hoeger LLC\nKurtis Weissnat Johns Group\nChelsey Dietrich Keebler LLC\nPatricia Lebsack Robel-Corkery\nLeanne Graham Romaguera-Crona\nClementine Bauch Romaguera-Jacobson\nGlenna Reichert Yost and Sons\n'})})]})}function u(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>i});var t=s(6540);const a={},o=t.createContext(a);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7996],{1916:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var t=s(4848),a=s(8453);const o={title:"Table"},r=void 0,i={id:"table",title:"Table",description:"ux.table",source:"@site/../docs/table.md",sourceDirName:".",slug:"/table",permalink:"/docs/table",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/table.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Table"},sidebar:"docs",previous:{title:"Spinner",permalink:"/docs/spinner"},next:{title:"Notifications",permalink:"/docs/notifications"}},l={},c=[{value:"ux.table
",id:"uxtable",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"uxtable",children:(0,t.jsx)(n.code,{children:"ux.table"})}),"\n",(0,t.jsx)(n.p,{children:"Displays tabular data"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"ux.table(data, columns, options)\n"})}),"\n",(0,t.jsx)(n.p,{children:"Where:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"data"}),": array of data objects to display"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"columns"}),": ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/cli-ux/styled/table.ts",children:"Table.Columns"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"options"}),": ",(0,t.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/cli-ux/styled/table.ts",children:"Table.Options"})]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ux.table.flags()"})," returns an object containing all the table flags to include in your command."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"{\n columns: Flags.string({exclusive: ['additional'], description: 'only show provided columns (comma-seperated)'}),\n sort: Flags.string({description: 'property to sort by (prepend '-' for descending)'}),\n filter: Flags.string({description: 'filter property by partial string matching, ex: name=foo'}),\n csv: Flags.boolean({exclusive: ['no-truncate'], description: 'output is csv format'}),\n extended: Flags.boolean({char: 'x', description: 'show extra columns'}),\n 'no-truncate': Flags.boolean({exclusive: ['csv'], description: 'do not truncate output to fit screen'}),\n 'no-header': Flags.boolean({exclusive: ['csv'], description: 'hide table header from output'}),\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Passing ",(0,t.jsx)(n.code,{children:"{only: ['columns']}"})," or ",(0,t.jsx)(n.code,{children:"{except: ['columns']}"})," as an argument into ",(0,t.jsx)(n.code,{children:"cli.table.flags()"})," will allow/block those flags from the returned object."]}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ux.Table.Columns"})," defines the table columns and their display options."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const columns: ux.Table.Columns = {\n // where `.name` is a property of a data object\n name: {}, // \"Name\" inferred as the column header\n id: {\n header: 'ID', // override column header\n minWidth: '10', // column must display at this width or greater\n extended: true, // only display this column when the --extended flag is present\n get: row => `US-O1-${row.id}`, // custom getter for data row object\n },\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ux.Table.Options"})," defines the table options, most of which are the parsed flags from the user for display customization, all of which are optional."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const options: ux.Table.Options = {\n printLine: myLogger, // custom logger\n columns: flags.columns,\n sort: flags.sort,\n filter: flags.filter,\n csv: flags.csv,\n extended: flags.extended,\n 'no-truncate': flags['no-truncate'],\n 'no-header': flags['no-header'],\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Example class:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\nimport axios from 'axios'\n\nexport default class Users extends Command {\n static flags = {\n ...ux.table.flags()\n }\n\n async run() {\n const {flags} = await this.parse(Users)\n const {data: users} = await axios.get('https://jsonplaceholder.typicode.com/users')\n\n ux.table(users, {\n name: {\n minWidth: 7,\n },\n company: {\n get: row => row.company && row.company.name\n },\n id: {\n header: 'ID',\n extended: true\n }\n }, {\n printLine: this.log.bind(this),\n ...flags, // parsed flags\n })\n }\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Displays:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:'$ example-cli users\nName Company\nLeanne Graham Romaguera-Crona\nErvin Howell Deckow-Crist\nClementine Bauch Romaguera-Jacobson\nPatricia Lebsack Robel-Corkery\nChelsey Dietrich Keebler LLC\nMrs. Dennis Schulist Considine-Lockman\nKurtis Weissnat Johns Group\nNicholas Runolfsdottir V Abernathy Group\nGlenna Reichert Yost and Sons\nClementina DuBuque Hoeger LLC\n\n$ example-cli users --extended\nName Company ID\nLeanne Graham Romaguera-Crona 1\nErvin Howell Deckow-Crist 2\nClementine Bauch Romaguera-Jacobson 3\nPatricia Lebsack Robel-Corkery 4\nChelsey Dietrich Keebler LLC 5\nMrs. Dennis Schulist Considine-Lockman 6\nKurtis Weissnat Johns Group 7\nNicholas Runolfsdottir V Abernathy Group 8\nGlenna Reichert Yost and Sons 9\nClementina DuBuque Hoeger LLC 10\n\n$ example-cli users --columns=name\nName\nLeanne Graham\nErvin Howell\nClementine Bauch\nPatricia Lebsack\nChelsey Dietrich\nMrs. Dennis Schulist\nKurtis Weissnat\nNicholas Runolfsdottir V\nGlenna Reichert\nClementina DuBuque\n\n$ example-cli users --filter="company=Group"\nName Company\nKurtis Weissnat Johns Group\nNicholas Runolfsdottir V Abernathy Group\n\n$ example-cli users --sort=company\nName Company\nNicholas Runolfsdottir V Abernathy Group\nMrs. Dennis Schulist Considine-Lockman\nErvin Howell Deckow-Crist\nClementina DuBuque Hoeger LLC\nKurtis Weissnat Johns Group\nChelsey Dietrich Keebler LLC\nPatricia Lebsack Robel-Corkery\nLeanne Graham Romaguera-Crona\nClementine Bauch Romaguera-Jacobson\nGlenna Reichert Yost and Sons\n'})})]})}function u(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>i});var t=s(6540);const a={},o=t.createContext(a);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/35586d92.f1a1915a.js b/assets/js/35586d92.a74fcd5f.js
similarity index 96%
rename from assets/js/35586d92.f1a1915a.js
rename to assets/js/35586d92.a74fcd5f.js
index fa6c407c..e9ae9664 100644
--- a/assets/js/35586d92.f1a1915a.js
+++ b/assets/js/35586d92.a74fcd5f.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7187],{1810:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var o=i(4848),t=i(8453);const s={title:"Plugin Loading"},l=void 0,r={id:"plugin_loading",title:"Plugin Loading",description:"Below is a diagram that outlines how a plugin is loaded into the CLI.",source:"@site/../docs/plugin_loading.md",sourceDirName:".",slug:"/plugin_loading",permalink:"/docs/plugin_loading",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/plugin_loading.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Plugin Loading"},sidebar:"docs",previous:{title:"Command Execution",permalink:"/docs/command_execution"},next:{title:"Command Discovery Strategies",permalink:"/docs/command_discovery_strategies"}},a={},d=[{value:"Plugin Resolution Order",id:"plugin-resolution-order",level:3},{value:"Manifests Improve Performance",id:"manifests-improve-performance",level:3},{value:"Plugin Loading Diagram",id:"plugin-loading-diagram",level:2}];function c(e){const n={code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Below is a diagram that outlines how a plugin is loaded into the CLI."}),"\n",(0,o.jsx)(n.p,{children:"There are a couple of important takeaways from this diagram:"}),"\n",(0,o.jsx)(n.h3,{id:"plugin-resolution-order",children:"Plugin Resolution Order"}),"\n",(0,o.jsx)(n.p,{children:"Plugins are resolved in the following order:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsx)(n.li,{children:"User plugins (i.e. plugins installed by the users)"}),"\n",(0,o.jsxs)(n.li,{children:["Dev plugins (i.e. plugins listed under ",(0,o.jsx)(n.code,{children:"devPlugins"}),")"]}),"\n",(0,o.jsxs)(n.li,{children:["Core plugins (i.e. plugins listed under ",(0,o.jsx)(n.code,{children:"plugins"}),")"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"manifests-improve-performance",children:"Manifests Improve Performance"}),"\n",(0,o.jsxs)(n.p,{children:["When loading a plugin, oclif needs to require each command file in order to get the static properties of the command - the ",(0,o.jsx)(n.code,{children:"description"}),", ",(0,o.jsx)(n.code,{children:"examples"}),", ",(0,o.jsx)(n.code,{children:"flags"}),", etc..."]}),"\n",(0,o.jsxs)(n.p,{children:["However, oclif can skip this step if the plugin has an ",(0,o.jsx)(n.code,{children:"oclif.manifest.json"})," (generated by ",(0,o.jsx)(n.code,{children:"oclif manifest"}),"). The manifest caches all of these properties so that there's no need to require every single command on every command execution."]}),"\n",(0,o.jsx)(n.h2,{id:"plugin-loading-diagram",children:"Plugin Loading Diagram"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"plugin loading",src:i(4893).A+"",width:"8787",height:"5576"})})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},4893:(e,n,i)=>{i.d(n,{A:()=>o});const o=i.p+"assets/images/plugin-loading-63d248baba4db7ba0a9340ef6b0c0856.jpg"},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>r});var o=i(6540);const t={},s=o.createContext(t);function l(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7187],{1810:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>u,frontMatter:()=>s,metadata:()=>r,toc:()=>d});var o=i(4848),t=i(8453);const s={title:"Plugin Loading"},l=void 0,r={id:"plugin_loading",title:"Plugin Loading",description:"Below is a diagram that outlines how a plugin is loaded into the CLI.",source:"@site/../docs/plugin_loading.md",sourceDirName:".",slug:"/plugin_loading",permalink:"/docs/plugin_loading",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/plugin_loading.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Plugin Loading"},sidebar:"docs",previous:{title:"Command Execution",permalink:"/docs/command_execution"},next:{title:"Command Discovery Strategies",permalink:"/docs/command_discovery_strategies"}},a={},d=[{value:"Plugin Resolution Order",id:"plugin-resolution-order",level:3},{value:"Manifests Improve Performance",id:"manifests-improve-performance",level:3},{value:"Plugin Loading Diagram",id:"plugin-loading-diagram",level:2}];function c(e){const n={code:"code",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.p,{children:"Below is a diagram that outlines how a plugin is loaded into the CLI."}),"\n",(0,o.jsx)(n.p,{children:"There are a couple of important takeaways from this diagram:"}),"\n",(0,o.jsx)(n.h3,{id:"plugin-resolution-order",children:"Plugin Resolution Order"}),"\n",(0,o.jsx)(n.p,{children:"Plugins are resolved in the following order:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsx)(n.li,{children:"User plugins (i.e. plugins installed by the users)"}),"\n",(0,o.jsxs)(n.li,{children:["Dev plugins (i.e. plugins listed under ",(0,o.jsx)(n.code,{children:"devPlugins"}),")"]}),"\n",(0,o.jsxs)(n.li,{children:["Core plugins (i.e. plugins listed under ",(0,o.jsx)(n.code,{children:"plugins"}),")"]}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"manifests-improve-performance",children:"Manifests Improve Performance"}),"\n",(0,o.jsxs)(n.p,{children:["When loading a plugin, oclif needs to require each command file in order to get the static properties of the command - the ",(0,o.jsx)(n.code,{children:"description"}),", ",(0,o.jsx)(n.code,{children:"examples"}),", ",(0,o.jsx)(n.code,{children:"flags"}),", etc..."]}),"\n",(0,o.jsxs)(n.p,{children:["However, oclif can skip this step if the plugin has an ",(0,o.jsx)(n.code,{children:"oclif.manifest.json"})," (generated by ",(0,o.jsx)(n.code,{children:"oclif manifest"}),"). The manifest caches all of these properties so that there's no need to require every single command on every command execution."]}),"\n",(0,o.jsx)(n.h2,{id:"plugin-loading-diagram",children:"Plugin Loading Diagram"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.img,{alt:"plugin loading",src:i(4893).A+"",width:"8787",height:"5576"})})]})}function u(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},4893:(e,n,i)=>{i.d(n,{A:()=>o});const o=i.p+"assets/images/plugin-loading-63d248baba4db7ba0a9340ef6b0c0856.jpg"},8453:(e,n,i)=>{i.d(n,{R:()=>l,x:()=>r});var o=i(6540);const t={},s=o.createContext(t);function l(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/3e452c7e.0139d8d2.js b/assets/js/3e452c7e.747c7b5b.js
similarity index 97%
rename from assets/js/3e452c7e.0139d8d2.js
rename to assets/js/3e452c7e.747c7b5b.js
index 7898ccdf..3cfe40cd 100644
--- a/assets/js/3e452c7e.0139d8d2.js
+++ b/assets/js/3e452c7e.747c7b5b.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[55],{7780:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>i});var a=s(4848),t=s(8453);const o={title:"Custom Base Class"},r=void 0,c={id:"base_class",title:"Custom Base Class",description:"Use inheritance to share functionality between common commands. Here is an example of a command base class that has some common shared flags.",source:"@site/../docs/base_class.md",sourceDirName:".",slug:"/base_class",permalink:"/docs/base_class",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/base_class.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Custom Base Class"},sidebar:"docs",previous:{title:"NSIS Installer Customization",permalink:"/docs/nsis-installer_customization"},next:{title:"Prompting",permalink:"/docs/prompting"}},l={},i=[];function m(e){const n={a:"a",code:"code",p:"p",pre:"pre",...(0,t.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.p,{children:"Use inheritance to share functionality between common commands. Here is an example of a command base class that has some common shared flags."}),"\n",(0,a.jsx)(n.p,{children:"For large CLIs with multiple plugins, it's useful to put this base class into its own npm package to be shared."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-typescript",children:"// src/baseCommand.ts\nimport {Command, Flags, Interfaces} from '@oclif/core'\n\nenum LogLevel {\n debug = 'debug',\n info = 'info',\n warn = 'warn',\n error = 'error',\n}\n\nexport type Flagsthis.log(message: string)
",id:"thislogmessage-string",level:3},{value:"this.warn(message: string | Error)
",id:"thiswarnmessage-string--error",level:3},{value:"this.error(message: string | Error, options?: {code?: string, exit?: number, ref?: string; suggestions?: string[];})
",id:"thiserrormessage-string--error-options-code-string-exit-number-ref-string-suggestions-string",level:3},{value:"this.exit(code: number = 0)
",id:"thisexitcode-number--0",level:3},{value:"this.logToStderr(message: string)
",id:"thislogtostderrmessage-string",level:3},{value:"this.jsonEnabled()
",id:"thisjsonenabled",level:3},{value:"this.toSuccessJson(result: unknown)
",id:"thistosuccessjsonresult-unknown",level:3},{value:"this.toErrorJson(result: unknown)
",id:"thistoerrorjsonresult-unknown",level:3}];function l(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"A basic command looks like the following in TypeScript:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"import {Command} from '@oclif/core'\n\nexport class MyCommand extends Command {\n static description = 'description of this example command'\n\n async run(): Promisethis.log(message: string)
",id:"thislogmessage-string",level:3},{value:"this.warn(message: string | Error)
",id:"thiswarnmessage-string--error",level:3},{value:"this.error(message: string | Error, options?: {code?: string, exit?: number, ref?: string; suggestions?: string[];})
",id:"thiserrormessage-string--error-options-code-string-exit-number-ref-string-suggestions-string",level:3},{value:"this.exit(code: number = 0)
",id:"thisexitcode-number--0",level:3},{value:"this.logToStderr(message: string)
",id:"thislogtostderrmessage-string",level:3},{value:"this.jsonEnabled()
",id:"thisjsonenabled",level:3},{value:"this.toSuccessJson(result: unknown)
",id:"thistosuccessjsonresult-unknown",level:3},{value:"this.toErrorJson(result: unknown)
",id:"thistoerrorjsonresult-unknown",level:3}];function l(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:"A basic command looks like the following in TypeScript:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"import {Command} from '@oclif/core'\n\nexport class MyCommand extends Command {\n static description = 'description of this example command'\n\n async run(): Promiseux.prompt()
",id:"uxprompt",level:2},{value:"inquirer
",id:"inquirer",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",strong:"strong",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/cli-ux/README.md",children:"ux"})," export provides a simple ",(0,s.jsx)(n.code,{children:"cli.prompt()"})," function, for more complex input prompts, we recommend using the ",(0,s.jsx)(n.a,{href:"https://github.com/SBoudrias/Inquirer.js",children:"inquirer"})," library."]}),"\n",(0,s.jsx)(n.h2,{id:"uxprompt",children:(0,s.jsx)(n.code,{children:"ux.prompt()"})}),"\n",(0,s.jsxs)(n.p,{children:["Prompt for basic input with ",(0,s.jsx)(n.code,{children:"ux"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\n\nexport class MyCommand extends Command {\n async run() {\n // just prompt for input\n const name = await ux.prompt('What is your name?')\n\n // mask input after enter is pressed\n const secondFactor = await ux.prompt('What is your two-factor token?', {type: 'mask'})\n\n // hide input while typing\n const password = await ux.prompt('What is your password?', {type: 'hide'})\n\n this.log(`You entered: ${name}, ${secondFactor}, ${password}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Demo:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"prompt demo",src:t(164).A+"",width:"941",height:"605"})}),"\n",(0,s.jsx)(n.h2,{id:"inquirer",children:(0,s.jsx)(n.code,{children:"inquirer"})}),"\n",(0,s.jsxs)(n.p,{children:["Here is an example command that uses ",(0,s.jsx)(n.a,{href:"https://github.com/SBoudrias/Inquirer.js",children:"inquirer"}),". You will need to add ",(0,s.jsx)(n.code,{children:"inquirer"})," and ",(0,s.jsx)(n.code,{children:"@types/inquirer"})," (for TypeScript CLIs) for this to work."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import {Command, Flags} from '@oclif/core'\nimport * as inquirer from 'inquirer'\n\nexport class MyCommand extends Command {\n static flags = {\n stage: Flags.string({options: ['development', 'staging', 'production']})\n }\n\n async run() {\n const {flags} = await this.parse(MyCommand)\n let stage = flags.stage\n if (!stage) {\n let responses: any = await inquirer.prompt([{\n name: 'stage',\n message: 'select a stage',\n type: 'list',\n choices: [{name: 'development'}, {name: 'staging'}, {name: 'production'}],\n }])\n stage = responses.stage\n }\n this.log(`the stage is: ${stage}`)\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"NOTE"}),": inquirer >= v9 is an ESM package. If you aren't using ESM in your CLI/plugin, you should set ",(0,s.jsxs)(n.a,{href:"https://www.typescriptlang.org/tsconfig#moduleResolution",children:[(0,s.jsx)(n.code,{children:"moduleResolution"})," to ",(0,s.jsx)(n.code,{children:"node16"})]})," in your tsconfig.json and ",(0,s.jsxs)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import",children:["import it using ",(0,s.jsx)(n.code,{children:"await import"})]}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import {Command, Flags} from '@oclif/core'\n\nexport class MyCommand extends Command {\n static flags = {\n stage: Flags.string({options: ['development', 'staging', 'production']})\n }\n\n async run() {\n const {flags} = await this.parse(MyCommand)\n let stage = flags.stage\n if (!stage) {\n const { default: inquirer } = await import(\"inquirer\")\n let responses: any = inquirer.prompt([{\n name: 'stage',\n message: 'select a stage',\n type: 'list',\n choices: [{name: 'development'}, {name: 'staging'}, {name: 'production'}],\n }])\n stage = responses.stage\n }\n this.log(`the stage is: ${stage}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Demo:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"inquirer demo",src:t(7915).A+"",width:"1254",height:"806"})})]})}function m(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},7915:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/inquirer_demo-4d4cd8f9cf0bf300a5b853a4beef5672.gif"},164:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/prompt_demo-7bc9d5f614fdad73636bec3c864aff15.gif"},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>a});var s=t(6540);const r={},o=s.createContext(r);function i(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7071],{6362:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>o,metadata:()=>a,toc:()=>p});var s=t(4848),r=t(8453);const o={title:"Prompting"},i=void 0,a={id:"prompting",title:"Prompting",description:"The ux export provides a simple cli.prompt() function, for more complex input prompts, we recommend using the inquirer library.",source:"@site/../docs/prompting.md",sourceDirName:".",slug:"/prompting",permalink:"/docs/prompting",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/prompting.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Prompting"},sidebar:"docs",previous:{title:"Custom Base Class",permalink:"/docs/base_class"},next:{title:"Spinner",permalink:"/docs/spinner"}},c={},p=[{value:"ux.prompt()
",id:"uxprompt",level:2},{value:"inquirer
",id:"inquirer",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",img:"img",p:"p",pre:"pre",strong:"strong",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/cli-ux/README.md",children:"ux"})," export provides a simple ",(0,s.jsx)(n.code,{children:"cli.prompt()"})," function, for more complex input prompts, we recommend using the ",(0,s.jsx)(n.a,{href:"https://github.com/SBoudrias/Inquirer.js",children:"inquirer"})," library."]}),"\n",(0,s.jsx)(n.h2,{id:"uxprompt",children:(0,s.jsx)(n.code,{children:"ux.prompt()"})}),"\n",(0,s.jsxs)(n.p,{children:["Prompt for basic input with ",(0,s.jsx)(n.code,{children:"ux"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\n\nexport class MyCommand extends Command {\n async run() {\n // just prompt for input\n const name = await ux.prompt('What is your name?')\n\n // mask input after enter is pressed\n const secondFactor = await ux.prompt('What is your two-factor token?', {type: 'mask'})\n\n // hide input while typing\n const password = await ux.prompt('What is your password?', {type: 'hide'})\n\n this.log(`You entered: ${name}, ${secondFactor}, ${password}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Demo:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"prompt demo",src:t(164).A+"",width:"941",height:"605"})}),"\n",(0,s.jsx)(n.h2,{id:"inquirer",children:(0,s.jsx)(n.code,{children:"inquirer"})}),"\n",(0,s.jsxs)(n.p,{children:["Here is an example command that uses ",(0,s.jsx)(n.a,{href:"https://github.com/SBoudrias/Inquirer.js",children:"inquirer"}),". You will need to add ",(0,s.jsx)(n.code,{children:"inquirer"})," and ",(0,s.jsx)(n.code,{children:"@types/inquirer"})," (for TypeScript CLIs) for this to work."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import {Command, Flags} from '@oclif/core'\nimport * as inquirer from 'inquirer'\n\nexport class MyCommand extends Command {\n static flags = {\n stage: Flags.string({options: ['development', 'staging', 'production']})\n }\n\n async run() {\n const {flags} = await this.parse(MyCommand)\n let stage = flags.stage\n if (!stage) {\n let responses: any = await inquirer.prompt([{\n name: 'stage',\n message: 'select a stage',\n type: 'list',\n choices: [{name: 'development'}, {name: 'staging'}, {name: 'production'}],\n }])\n stage = responses.stage\n }\n this.log(`the stage is: ${stage}`)\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"NOTE"}),": inquirer >= v9 is an ESM package. If you aren't using ESM in your CLI/plugin, you should set ",(0,s.jsxs)(n.a,{href:"https://www.typescriptlang.org/tsconfig#moduleResolution",children:[(0,s.jsx)(n.code,{children:"moduleResolution"})," to ",(0,s.jsx)(n.code,{children:"node16"})]})," in your tsconfig.json and ",(0,s.jsxs)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import",children:["import it using ",(0,s.jsx)(n.code,{children:"await import"})]}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"import {Command, Flags} from '@oclif/core'\n\nexport class MyCommand extends Command {\n static flags = {\n stage: Flags.string({options: ['development', 'staging', 'production']})\n }\n\n async run() {\n const {flags} = await this.parse(MyCommand)\n let stage = flags.stage\n if (!stage) {\n const { default: inquirer } = await import(\"inquirer\")\n let responses: any = inquirer.prompt([{\n name: 'stage',\n message: 'select a stage',\n type: 'list',\n choices: [{name: 'development'}, {name: 'staging'}, {name: 'production'}],\n }])\n stage = responses.stage\n }\n this.log(`the stage is: ${stage}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Demo:"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"inquirer demo",src:t(7915).A+"",width:"1254",height:"806"})})]})}function m(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},7915:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/inquirer_demo-4d4cd8f9cf0bf300a5b853a4beef5672.gif"},164:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/prompt_demo-7bc9d5f614fdad73636bec3c864aff15.gif"},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>a});var s=t(6540);const r={},o=s.createContext(r);function i(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/82247a8b.a76eaf65.js b/assets/js/82247a8b.de433149.js
similarity index 99%
rename from assets/js/82247a8b.a76eaf65.js
rename to assets/js/82247a8b.de433149.js
index b0565b8a..bad26fa9 100644
--- a/assets/js/82247a8b.a76eaf65.js
+++ b/assets/js/82247a8b.de433149.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9409],{7840:(n,e,s)=>{s.r(e),s.d(e,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>t,toc:()=>d});var i=s(4848),r=s(8453);const o={title:"Configuration"},c=void 0,t={id:"config",title:"Configuration",description:"Inside a command, this.config provides useful properties you can use in your command. Here are a list of its methods and properties:",source:"@site/../docs/config.md",sourceDirName:".",slug:"/config",permalink:"/docs/config",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/config.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Configuration"},sidebar:"docs",previous:{title:"Command Flags",permalink:"/docs/flags"},next:{title:"Topics",permalink:"/docs/topics"}},l={},d=[{value:"Custom User Configuration",id:"custom-user-configuration",level:2}];function a(n){const e={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...n.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(e.p,{children:["Inside a command, ",(0,i.jsx)(e.code,{children:"this.config"})," provides useful properties you can use in your command. Here are a list of its methods and properties:"]}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"name"})," - name of CLI"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"version"})," - Version of the CLI."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"pjson"})," - Parsed and ",(0,i.jsx)(e.a,{href:"https://github.com/npm/normalize-package-data",children:"normalized"})," CLI ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"bin"})," - CLI bin name"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"binAliases"})," - An array of strings that will all execute the CLI's bin. This is useful for backwards compatibility and for CLIs built with installers or tarballs. For npm-installed CLIs, change the ",(0,i.jsx)(e.code,{children:"bin"})," property in ",(0,i.jsx)(e.code,{children:"package.json"})," instead. See ",(0,i.jsx)(e.a,{href:"https://oclif.io/docs/aliases",children:"Bin Aliases"})," for more information."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"nsisCustomization"})," - A path to a .nsis file that's used to customize the installer for Windows. See ",(0,i.jsx)(e.a,{href:"https://github.com/oclif/nsis-custom",children:"nsis-custom"})," for more information."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"cacheDir"})," - CLI cache directory","\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["macOS: ",(0,i.jsx)(e.code,{children:"~/Library/Caches/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Unix: ",(0,i.jsx)(e.code,{children:"~/.cache/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Windows: ",(0,i.jsx)(e.code,{children:"%LOCALAPPDATA%\\mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Can be overridden with ",(0,i.jsx)(e.code,{children:"XDG_CACHE_HOME"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"configDir"})," - CLI config directory","\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Unix: ",(0,i.jsx)(e.code,{children:"~/.config/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Windows: ",(0,i.jsx)(e.code,{children:"%LOCALAPPDATA%\\mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Can be overridden with ",(0,i.jsx)(e.code,{children:"XDG_CONFIG_HOME"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"dataDir"})," - CLI data directory","\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Unix: ",(0,i.jsx)(e.code,{children:"~/.data/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Windows: ",(0,i.jsx)(e.code,{children:"%LOCALAPPDATA%\\mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Can be overridden with ",(0,i.jsx)(e.code,{children:"XDG_DATA_HOME"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"dirname"})," - dirname used with ",(0,i.jsx)(e.code,{children:"cacheDir|configDir|dataDir"}),". Can be overridden in ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"errlog"})," - path to error log inside of ",(0,i.jsx)(e.code,{children:"cacheDir"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"home"})," - user home directory"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"platform"})," - operating system ",(0,i.jsx)(e.code,{children:"darwin|linux|win32"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"arch"})," - process architecture ",(0,i.jsx)(e.code,{children:"x64|x86"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"shell"})," - current shell in use"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"userAgent"})," - user-agent intended for http calls. example: ",(0,i.jsx)(e.code,{children:"mycli/1.2.3 (darwin-x64) node-9.0.0"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"windows"})," - boolean"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"topicSeparator"})," - the separator to use between topics - only colons (",(0,i.jsx)(e.code,{children:'":"'}),") and spaces (",(0,i.jsx)(e.code,{children:'" "'}),") are supported."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"debug"})," - set to 1 if debug is enabled (with ",(0,i.jsx)(e.code,{children:"${BIN}_DEBUG=1"})," or ",(0,i.jsx)(e.code,{children:"DEBUG=$BIN"}),"). In the future this may be used for multiple debug levels."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"npmRegistry"})," - current npm registry to use with the ",(0,i.jsx)(e.a,{href:"https://github.com/oclif/plugin-plugins",children:"plugins"})," plugin"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"plugins"})," - loaded plugins"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"commands"})," - all commands in CLI"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"default"})," - default cli command"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"topics"})," - all topics in CLI"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"commandIDs"})," - string IDs of all commands"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"async runHook(event, opts)"})," - trigger a hook"]}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"custom-user-configuration",children:"Custom User Configuration"}),"\n",(0,i.jsxs)(e.p,{children:["Often it's useful to have a custom configuration for your users. One way to implement this is to read a ",(0,i.jsx)(e.code,{children:"config.json"})," file from the CLI's config directory:"]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-typescript",children:"import {Command} from '@oclif/core'\nimport * as fs from 'fs-extra'\nimport * as path from 'path'\n\nexport class extends Command {\n async run() {\n const userConfig = await fs.readJSON(path.join(this.config.configDir, 'config.json'))\n\n this.log('User config:')\n console.dir(userConfig)\n }\n}\n"})}),"\n",(0,i.jsxs)(e.p,{children:["To share this logic between different commands, use a ",(0,i.jsx)(e.a,{href:"/docs/base_class",children:"base class"}),"."]})]})}function h(n={}){const{wrapper:e}={...(0,r.R)(),...n.components};return e?(0,i.jsx)(e,{...n,children:(0,i.jsx)(a,{...n})}):a(n)}},8453:(n,e,s)=>{s.d(e,{R:()=>c,x:()=>t});var i=s(6540);const r={},o=i.createContext(r);function c(n){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function t(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(r):n.components||r:c(n.components),i.createElement(o.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9409],{7840:(n,e,s)=>{s.r(e),s.d(e,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>o,metadata:()=>t,toc:()=>d});var i=s(4848),r=s(8453);const o={title:"Configuration"},c=void 0,t={id:"config",title:"Configuration",description:"Inside a command, this.config provides useful properties you can use in your command. Here are a list of its methods and properties:",source:"@site/../docs/config.md",sourceDirName:".",slug:"/config",permalink:"/docs/config",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/config.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Configuration"},sidebar:"docs",previous:{title:"Command Flags",permalink:"/docs/flags"},next:{title:"Topics",permalink:"/docs/topics"}},l={},d=[{value:"Custom User Configuration",id:"custom-user-configuration",level:2}];function a(n){const e={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...n.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(e.p,{children:["Inside a command, ",(0,i.jsx)(e.code,{children:"this.config"})," provides useful properties you can use in your command. Here are a list of its methods and properties:"]}),"\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"name"})," - name of CLI"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"version"})," - Version of the CLI."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"pjson"})," - Parsed and ",(0,i.jsx)(e.a,{href:"https://github.com/npm/normalize-package-data",children:"normalized"})," CLI ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"bin"})," - CLI bin name"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"binAliases"})," - An array of strings that will all execute the CLI's bin. This is useful for backwards compatibility and for CLIs built with installers or tarballs. For npm-installed CLIs, change the ",(0,i.jsx)(e.code,{children:"bin"})," property in ",(0,i.jsx)(e.code,{children:"package.json"})," instead. See ",(0,i.jsx)(e.a,{href:"https://oclif.io/docs/aliases",children:"Bin Aliases"})," for more information."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"nsisCustomization"})," - A path to a .nsis file that's used to customize the installer for Windows. See ",(0,i.jsx)(e.a,{href:"https://github.com/oclif/nsis-custom",children:"nsis-custom"})," for more information."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"cacheDir"})," - CLI cache directory","\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["macOS: ",(0,i.jsx)(e.code,{children:"~/Library/Caches/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Unix: ",(0,i.jsx)(e.code,{children:"~/.cache/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Windows: ",(0,i.jsx)(e.code,{children:"%LOCALAPPDATA%\\mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Can be overridden with ",(0,i.jsx)(e.code,{children:"XDG_CACHE_HOME"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"configDir"})," - CLI config directory","\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Unix: ",(0,i.jsx)(e.code,{children:"~/.config/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Windows: ",(0,i.jsx)(e.code,{children:"%LOCALAPPDATA%\\mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Can be overridden with ",(0,i.jsx)(e.code,{children:"XDG_CONFIG_HOME"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"dataDir"})," - CLI data directory","\n",(0,i.jsxs)(e.ul,{children:["\n",(0,i.jsxs)(e.li,{children:["Unix: ",(0,i.jsx)(e.code,{children:"~/.data/mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Windows: ",(0,i.jsx)(e.code,{children:"%LOCALAPPDATA%\\mycli"})]}),"\n",(0,i.jsxs)(e.li,{children:["Can be overridden with ",(0,i.jsx)(e.code,{children:"XDG_DATA_HOME"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"dirname"})," - dirname used with ",(0,i.jsx)(e.code,{children:"cacheDir|configDir|dataDir"}),". Can be overridden in ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"errlog"})," - path to error log inside of ",(0,i.jsx)(e.code,{children:"cacheDir"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"home"})," - user home directory"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"platform"})," - operating system ",(0,i.jsx)(e.code,{children:"darwin|linux|win32"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"arch"})," - process architecture ",(0,i.jsx)(e.code,{children:"x64|x86"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"shell"})," - current shell in use"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"userAgent"})," - user-agent intended for http calls. example: ",(0,i.jsx)(e.code,{children:"mycli/1.2.3 (darwin-x64) node-9.0.0"})]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"windows"})," - boolean"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"topicSeparator"})," - the separator to use between topics - only colons (",(0,i.jsx)(e.code,{children:'":"'}),") and spaces (",(0,i.jsx)(e.code,{children:'" "'}),") are supported."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"debug"})," - set to 1 if debug is enabled (with ",(0,i.jsx)(e.code,{children:"${BIN}_DEBUG=1"})," or ",(0,i.jsx)(e.code,{children:"DEBUG=$BIN"}),"). In the future this may be used for multiple debug levels."]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"npmRegistry"})," - current npm registry to use with the ",(0,i.jsx)(e.a,{href:"https://github.com/oclif/plugin-plugins",children:"plugins"})," plugin"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"plugins"})," - loaded plugins"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"commands"})," - all commands in CLI"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"default"})," - default cli command"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"topics"})," - all topics in CLI"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"commandIDs"})," - string IDs of all commands"]}),"\n",(0,i.jsxs)(e.li,{children:[(0,i.jsx)(e.strong,{children:"async runHook(event, opts)"})," - trigger a hook"]}),"\n"]}),"\n",(0,i.jsx)(e.h2,{id:"custom-user-configuration",children:"Custom User Configuration"}),"\n",(0,i.jsxs)(e.p,{children:["Often it's useful to have a custom configuration for your users. One way to implement this is to read a ",(0,i.jsx)(e.code,{children:"config.json"})," file from the CLI's config directory:"]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-typescript",children:"import {Command} from '@oclif/core'\nimport * as fs from 'fs-extra'\nimport * as path from 'path'\n\nexport class extends Command {\n async run() {\n const userConfig = await fs.readJSON(path.join(this.config.configDir, 'config.json'))\n\n this.log('User config:')\n console.dir(userConfig)\n }\n}\n"})}),"\n",(0,i.jsxs)(e.p,{children:["To share this logic between different commands, use a ",(0,i.jsx)(e.a,{href:"/docs/base_class",children:"base class"}),"."]})]})}function h(n={}){const{wrapper:e}={...(0,r.R)(),...n.components};return e?(0,i.jsx)(e,{...n,children:(0,i.jsx)(a,{...n})}):a(n)}},8453:(n,e,s)=>{s.d(e,{R:()=>c,x:()=>t});var i=s(6540);const r={},o=i.createContext(r);function c(n){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function t(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(r):n.components||r:c(n.components),i.createElement(o.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/8705a681.a24a496a.js b/assets/js/8705a681.eedb41eb.js
similarity index 98%
rename from assets/js/8705a681.a24a496a.js
rename to assets/js/8705a681.eedb41eb.js
index 7b1e115c..51f3b322 100644
--- a/assets/js/8705a681.a24a496a.js
+++ b/assets/js/8705a681.eedb41eb.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[125],{1766:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var a=t(4848),s=t(8453);const i={title:"Running Commands Programmatically"},o=void 0,r={id:"running_programmatically",title:"Running Commands Programmatically",description:"If you need to run a command from another, or programmatically run a command in another codebase, there are a couple options.",source:"@site/../docs/running_programmatically.md",sourceDirName:".",slug:"/running_programmatically",permalink:"/docs/running_programmatically",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/running_programmatically.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Running Commands Programmatically"},sidebar:"docs",previous:{title:"Testing",permalink:"/docs/testing"},next:{title:"Just-in-Time Plugin Installation",permalink:"/docs/jit_plugins"}},c={},l=[{value:"Sharing code with modules",id:"sharing-code-with-modules",level:2},{value:"Calling commands directly",id:"calling-commands-directly",level:2}];function d(n){const e={a:"a",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...n.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"If you need to run a command from another, or programmatically run a command in another codebase, there are a couple options."}),"\n",(0,a.jsx)(e.p,{children:"First, it is generally a bad idea to run a command directly as the command exports a user interface, not a code interface. It's a design smell that should rarely (if ever) be used. Generally speaking, it's better to break up the code so that it can be called directly rather than as a command. We'll show this better method first."}),"\n",(0,a.jsx)(e.h2,{id:"sharing-code-with-modules",children:"Sharing code with modules"}),"\n",(0,a.jsxs)(e.p,{children:["For example, if we use ",(0,a.jsx)(e.code,{children:"sf config list"})," as an example, we could have a command that outputs the config vars of an app to the screen like this:"]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/list.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"export class ConfigList extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigList)\n const config = await api.get(`/apps/${flags.app}/config-vars`)\n for (let [key, value] of Object.entries(config)) {\n this.log(`${key}=${value}`)\n }\n }\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["If we had another command such as ",(0,a.jsx)(e.code,{children:"sf config update"})," that would do some logic then display the config variables using the same logic, we should create a new module that we could call directly:"]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/update.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"import {displayConfigVars} from '../displayConfigVars'\n\nexport class ConfigUpdate extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigUpdate)\n await this.doUpdate(flags.app)\n await displayConfigVars(flags.app)\n }\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/displayConfigVars.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"export async function displayConfigVars(app: string) {\n const config = await api.get(`/apps/${app}config-vars`)\n for (let [key, value] of Object.entries(config)) {\n this.log(`${key}=${value}`)\n }\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"This is the recommended way to share code. This can be extended further by putting shared code into its own npm package."}),"\n",(0,a.jsx)(e.h2,{id:"calling-commands-directly",children:"Calling commands directly"}),"\n",(0,a.jsxs)(e.p,{children:["Still, if you ",(0,a.jsx)(e.em,{children:"really"})," want to call a command directly, it's easy to do. You have a couple of options."]}),"\n",(0,a.jsxs)(e.p,{children:["If you know that the command you want to run is installed in the CLI, you can use ",(0,a.jsx)(e.code,{children:"this.config.runCommand"}),". For this, we could write our ",(0,a.jsx)(e.code,{children:"sf config update"})," command like so:"]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/update.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"export class ConfigUpdate extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigUpdate)\n await this.doUpdate(flags.app)\n await this.config.runCommand('config:list', ['--global'])\n }\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"Or you could import the command directly and execute it directly like so:"}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/update.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"import {ConfigList} from './config/list'\n\nexport class ConfigUpdate extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigUpdate)\n await this.doUpdate(flags.app)\n await ConfigList.run(['--global'])\n }\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["This works because commands have a static ",(0,a.jsx)(e.code,{children:".run()"})," ",(0,a.jsx)(e.a,{href:"https://github.com/oclif/core/blob/main/src/command.ts",children:"method on them"})," that can be used to instantiate the command and run the instance ",(0,a.jsx)(e.code,{children:".run()"})," method. It takes in the argv as input to the command."]})]})}function p(n={}){const{wrapper:e}={...(0,s.R)(),...n.components};return e?(0,a.jsx)(e,{...n,children:(0,a.jsx)(d,{...n})}):d(n)}},8453:(n,e,t)=>{t.d(e,{R:()=>o,x:()=>r});var a=t(6540);const s={},i=a.createContext(s);function o(n){const e=a.useContext(i);return a.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function r(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(s):n.components||s:o(n.components),a.createElement(i.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[125],{1766:(n,e,t)=>{t.r(e),t.d(e,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var a=t(4848),s=t(8453);const i={title:"Running Commands Programmatically"},o=void 0,r={id:"running_programmatically",title:"Running Commands Programmatically",description:"If you need to run a command from another, or programmatically run a command in another codebase, there are a couple options.",source:"@site/../docs/running_programmatically.md",sourceDirName:".",slug:"/running_programmatically",permalink:"/docs/running_programmatically",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/running_programmatically.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Running Commands Programmatically"},sidebar:"docs",previous:{title:"Testing",permalink:"/docs/testing"},next:{title:"Just-in-Time Plugin Installation",permalink:"/docs/jit_plugins"}},c={},l=[{value:"Sharing code with modules",id:"sharing-code-with-modules",level:2},{value:"Calling commands directly",id:"calling-commands-directly",level:2}];function d(n){const e={a:"a",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...n.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(e.p,{children:"If you need to run a command from another, or programmatically run a command in another codebase, there are a couple options."}),"\n",(0,a.jsx)(e.p,{children:"First, it is generally a bad idea to run a command directly as the command exports a user interface, not a code interface. It's a design smell that should rarely (if ever) be used. Generally speaking, it's better to break up the code so that it can be called directly rather than as a command. We'll show this better method first."}),"\n",(0,a.jsx)(e.h2,{id:"sharing-code-with-modules",children:"Sharing code with modules"}),"\n",(0,a.jsxs)(e.p,{children:["For example, if we use ",(0,a.jsx)(e.code,{children:"sf config list"})," as an example, we could have a command that outputs the config vars of an app to the screen like this:"]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/list.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"export class ConfigList extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigList)\n const config = await api.get(`/apps/${flags.app}/config-vars`)\n for (let [key, value] of Object.entries(config)) {\n this.log(`${key}=${value}`)\n }\n }\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["If we had another command such as ",(0,a.jsx)(e.code,{children:"sf config update"})," that would do some logic then display the config variables using the same logic, we should create a new module that we could call directly:"]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/update.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"import {displayConfigVars} from '../displayConfigVars'\n\nexport class ConfigUpdate extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigUpdate)\n await this.doUpdate(flags.app)\n await displayConfigVars(flags.app)\n }\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/displayConfigVars.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"export async function displayConfigVars(app: string) {\n const config = await api.get(`/apps/${app}config-vars`)\n for (let [key, value] of Object.entries(config)) {\n this.log(`${key}=${value}`)\n }\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"This is the recommended way to share code. This can be extended further by putting shared code into its own npm package."}),"\n",(0,a.jsx)(e.h2,{id:"calling-commands-directly",children:"Calling commands directly"}),"\n",(0,a.jsxs)(e.p,{children:["Still, if you ",(0,a.jsx)(e.em,{children:"really"})," want to call a command directly, it's easy to do. You have a couple of options."]}),"\n",(0,a.jsxs)(e.p,{children:["If you know that the command you want to run is installed in the CLI, you can use ",(0,a.jsx)(e.code,{children:"this.config.runCommand"}),". For this, we could write our ",(0,a.jsx)(e.code,{children:"sf config update"})," command like so:"]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/update.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"export class ConfigUpdate extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigUpdate)\n await this.doUpdate(flags.app)\n await this.config.runCommand('config:list', ['--global'])\n }\n}\n"})}),"\n",(0,a.jsx)(e.p,{children:"Or you could import the command directly and execute it directly like so:"}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"./src/commands/config/update.ts"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsx)(e.code,{className:"language-typescript",children:"import {ConfigList} from './config/list'\n\nexport class ConfigUpdate extends Command {\n static flags = {\n app: Flags.string({required: true})\n }\n\n async run() {\n const {flags} = await this.parse(ConfigUpdate)\n await this.doUpdate(flags.app)\n await ConfigList.run(['--global'])\n }\n}\n"})}),"\n",(0,a.jsxs)(e.p,{children:["This works because commands have a static ",(0,a.jsx)(e.code,{children:".run()"})," ",(0,a.jsx)(e.a,{href:"https://github.com/oclif/core/blob/main/src/command.ts",children:"method on them"})," that can be used to instantiate the command and run the instance ",(0,a.jsx)(e.code,{children:".run()"})," method. It takes in the argv as input to the command."]})]})}function p(n={}){const{wrapper:e}={...(0,s.R)(),...n.components};return e?(0,a.jsx)(e,{...n,children:(0,a.jsx)(d,{...n})}):d(n)}},8453:(n,e,t)=>{t.d(e,{R:()=>o,x:()=>r});var a=t(6540);const s={},i=a.createContext(s);function o(n){const e=a.useContext(i);return a.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function r(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(s):n.components||s:o(n.components),a.createElement(i.Provider,{value:e},n.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/935116ff.7148886a.js b/assets/js/935116ff.dc866d9f.js
similarity index 98%
rename from assets/js/935116ff.7148886a.js
rename to assets/js/935116ff.dc866d9f.js
index 5b416ba5..23b9c762 100644
--- a/assets/js/935116ff.7148886a.js
+++ b/assets/js/935116ff.dc866d9f.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8212],{1687:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=o(4848),n=o(8453);const s={title:"FAQs"},r=void 0,a={id:"faqs",title:"FAQs",description:"Why Node?",source:"@site/../docs/faqs.md",sourceDirName:".",slug:"/faqs",permalink:"/docs/faqs",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/faqs.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"FAQs"},sidebar:"docs",previous:{title:"Features",permalink:"/docs/features"},next:{title:"Generator Commands",permalink:"/docs/generator_commands"}},l={},d=[{value:"Why Node?",id:"why-node",level:2},{value:"I want a single binary CLI like with Go",id:"i-want-a-single-binary-cli-like-with-go",level:2},{value:"Should I use TypeScript or JavaScript?",id:"should-i-use-typescript-or-javascript",level:2},{value:"What editor is best for oclif?",id:"what-editor-is-best-for-oclif",level:2},{value:"Should I use npm or yarn?",id:"should-i-use-npm-or-yarn",level:2},{value:"How can I make the oclif generator run faster?",id:"how-can-i-make-the-oclif-generator-run-faster",level:2},{value:"Why isn't Node X supported?",id:"why-isnt-node-x-supported",level:2},{value:"How do I pronounce "oclif"?",id:"how-do-i-pronounce-oclif",level:2}];function c(e){const t={a:"a",code:"code",h2:"h2",p:"p",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"why-node",children:"Why Node?"}),"\n",(0,i.jsxs)(t.p,{children:["There are a number of reasons why Node is the best choice for writing CLI code. At Salesforce, we've released the heroku CLI in Ruby, Go, as well as Node. ",(0,i.jsx)(t.a,{href:"https://blog.heroku.com/evolution-of-heroku-cli-2008-2017",children:"This article gets more into detail on that history"}),", but we've certainly found that Node offers the best of everything."]}),"\n",(0,i.jsx)(t.p,{children:"First, JavaScript is the biggest language in the world. More people are able to write JavaScript than any other language and it by far has the biggest open source community. Everyone can write it and you'll find the most helpful libraries to help build your CLI."}),"\n",(0,i.jsx)(t.p,{children:"We've found that Node has the best cross platform support of any language we've used. In general, if you write code on macOS, you won't find many issues making it also run on Windows."}),"\n",(0,i.jsxs)(t.p,{children:["Node has the best support for our ",(0,i.jsx)(t.a,{href:"/docs/plugins",children:"plugins"})," model. Plugins are a way to share code between CLIs, to modularize a CLIs codebase, or allow users to add functionality to an existing CLI. With Node, we're able to have separate dependency versions sitting alongside one another. This means if you want to release an update to a dependency in one plugin, it won't affect how another plugin works. oclif takes this to an extreme and even flag parsing is done at the individual plugin level. If we ever want to make a breaking change to flag parsing (we certainly don't intend to, but this is just an example), you can update just one plugin and keep the old behavior in other plugins. This is very helpful for large CLI codebases where you want to migrate to new code slowly."]}),"\n",(0,i.jsx)(t.h2,{id:"i-want-a-single-binary-cli-like-with-go",children:"I want a single binary CLI like with Go"}),"\n",(0,i.jsxs)(t.p,{children:["Use ",(0,i.jsx)(t.a,{href:"https://github.com/zeit/pkg",children:"pkg"}),". Just make sure to add the commands and other source files by setting ",(0,i.jsx)(t.code,{children:'pkg.scripts: "./lib/**/*.js"'})," in ",(0,i.jsx)(t.code,{children:"package.json"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["In the Salesforce CLI, however, we prefer to ship a tarball (and various installers) that has Node baked in. Use ",(0,i.jsx)(t.code,{children:"oclif pack"})," to create a set of tarballs for different platforms with Node built in. You'll likely need to use ",(0,i.jsx)(t.a,{href:"https://github.com/oclif/plugin-update",children:"@oclif/plugin-update"})," with this, otherwise the users won't have a way to update the CLI from the tarball without reinstalling it."]}),"\n",(0,i.jsx)(t.h2,{id:"should-i-use-typescript-or-javascript",children:"Should I use TypeScript or JavaScript?"}),"\n",(0,i.jsx)(t.p,{children:"We suggest TypeScript as we find the typing to really help when refactoring code and updating dependencies. It's nicer to get compilation errors rather than finding errors in production."}),"\n",(0,i.jsxs)(t.p,{children:["We've put a lot of care into making it easy to make a TypeScript CLI even if you've never written TypeScript before. We generate CLIs and plugins that use ",(0,i.jsx)(t.a,{href:"https://github.com/TypeStrong/ts-node",children:"ts-node"})," to make it fast to run the TypeScript code without a compilation step. You won't have to mess around with build configuration using oclif."]}),"\n",(0,i.jsx)(t.p,{children:"Still, the languages today are very similar. The code you write in JavaScript will be nearly identical to what you would have in TypeScript. (Just no type definitions, of course)"}),"\n",(0,i.jsx)(t.h2,{id:"what-editor-is-best-for-oclif",children:"What editor is best for oclif?"}),"\n",(0,i.jsxs)(t.p,{children:["Of course if you already have a go-to editor, you should use that. However, we typically recommend ",(0,i.jsx)(t.a,{href:"https://code.visualstudio.com",children:"vscode"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"Microsoft has done a great job with this editor and it works particularly well in TypeScript projects. You'll get nice type checking, linting, and autocomplete right out of the box."}),"\n",(0,i.jsx)(t.h2,{id:"should-i-use-npm-or-yarn",children:"Should I use npm or yarn?"}),"\n",(0,i.jsx)(t.p,{children:"It really doesn't make that much of a difference. If you're just getting started, keep it simple and use npm which comes with Node. We like to use yarn internally as it's a bit faster and we find the lockfiles friendlier."}),"\n",(0,i.jsx)(t.h2,{id:"how-can-i-make-the-oclif-generator-run-faster",children:"How can I make the oclif generator run faster?"}),"\n",(0,i.jsxs)(t.p,{children:["If you're using npx, install it first with ",(0,i.jsx)(t.code,{children:"npm install -g oclif"}),". This won't stay current with updates though, so you'll need to run ",(0,i.jsx)(t.code,{children:"npm update -g oclif"})," to get new versions of the generator."]}),"\n",(0,i.jsx)(t.h2,{id:"why-isnt-node-x-supported",children:"Why isn't Node X supported?"}),"\n",(0,i.jsxs)(t.p,{children:["The oclif project follows and supports ",(0,i.jsx)(t.a,{href:"https://nodejs.org/en/about/releases/",children:"Node's LTS support schedule"}),". This allows oclif to stay current with Node's development."]}),"\n",(0,i.jsx)(t.h2,{id:"how-do-i-pronounce-oclif",children:'How do I pronounce "oclif"?'}),"\n",(0,i.jsx)(t.p,{children:'We say "oh-cliff".'})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>a});var i=o(6540);const n={},s=i.createContext(n);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8212],{1687:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var i=o(4848),n=o(8453);const s={title:"FAQs"},r=void 0,a={id:"faqs",title:"FAQs",description:"Why Node?",source:"@site/../docs/faqs.md",sourceDirName:".",slug:"/faqs",permalink:"/docs/faqs",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/faqs.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"FAQs"},sidebar:"docs",previous:{title:"Features",permalink:"/docs/features"},next:{title:"Generator Commands",permalink:"/docs/generator_commands"}},l={},d=[{value:"Why Node?",id:"why-node",level:2},{value:"I want a single binary CLI like with Go",id:"i-want-a-single-binary-cli-like-with-go",level:2},{value:"Should I use TypeScript or JavaScript?",id:"should-i-use-typescript-or-javascript",level:2},{value:"What editor is best for oclif?",id:"what-editor-is-best-for-oclif",level:2},{value:"Should I use npm or yarn?",id:"should-i-use-npm-or-yarn",level:2},{value:"How can I make the oclif generator run faster?",id:"how-can-i-make-the-oclif-generator-run-faster",level:2},{value:"Why isn't Node X supported?",id:"why-isnt-node-x-supported",level:2},{value:"How do I pronounce "oclif"?",id:"how-do-i-pronounce-oclif",level:2}];function c(e){const t={a:"a",code:"code",h2:"h2",p:"p",...(0,n.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h2,{id:"why-node",children:"Why Node?"}),"\n",(0,i.jsxs)(t.p,{children:["There are a number of reasons why Node is the best choice for writing CLI code. At Salesforce, we've released the heroku CLI in Ruby, Go, as well as Node. ",(0,i.jsx)(t.a,{href:"https://blog.heroku.com/evolution-of-heroku-cli-2008-2017",children:"This article gets more into detail on that history"}),", but we've certainly found that Node offers the best of everything."]}),"\n",(0,i.jsx)(t.p,{children:"First, JavaScript is the biggest language in the world. More people are able to write JavaScript than any other language and it by far has the biggest open source community. Everyone can write it and you'll find the most helpful libraries to help build your CLI."}),"\n",(0,i.jsx)(t.p,{children:"We've found that Node has the best cross platform support of any language we've used. In general, if you write code on macOS, you won't find many issues making it also run on Windows."}),"\n",(0,i.jsxs)(t.p,{children:["Node has the best support for our ",(0,i.jsx)(t.a,{href:"/docs/plugins",children:"plugins"})," model. Plugins are a way to share code between CLIs, to modularize a CLIs codebase, or allow users to add functionality to an existing CLI. With Node, we're able to have separate dependency versions sitting alongside one another. This means if you want to release an update to a dependency in one plugin, it won't affect how another plugin works. oclif takes this to an extreme and even flag parsing is done at the individual plugin level. If we ever want to make a breaking change to flag parsing (we certainly don't intend to, but this is just an example), you can update just one plugin and keep the old behavior in other plugins. This is very helpful for large CLI codebases where you want to migrate to new code slowly."]}),"\n",(0,i.jsx)(t.h2,{id:"i-want-a-single-binary-cli-like-with-go",children:"I want a single binary CLI like with Go"}),"\n",(0,i.jsxs)(t.p,{children:["Use ",(0,i.jsx)(t.a,{href:"https://github.com/zeit/pkg",children:"pkg"}),". Just make sure to add the commands and other source files by setting ",(0,i.jsx)(t.code,{children:'pkg.scripts: "./lib/**/*.js"'})," in ",(0,i.jsx)(t.code,{children:"package.json"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["In the Salesforce CLI, however, we prefer to ship a tarball (and various installers) that has Node baked in. Use ",(0,i.jsx)(t.code,{children:"oclif pack"})," to create a set of tarballs for different platforms with Node built in. You'll likely need to use ",(0,i.jsx)(t.a,{href:"https://github.com/oclif/plugin-update",children:"@oclif/plugin-update"})," with this, otherwise the users won't have a way to update the CLI from the tarball without reinstalling it."]}),"\n",(0,i.jsx)(t.h2,{id:"should-i-use-typescript-or-javascript",children:"Should I use TypeScript or JavaScript?"}),"\n",(0,i.jsx)(t.p,{children:"We suggest TypeScript as we find the typing to really help when refactoring code and updating dependencies. It's nicer to get compilation errors rather than finding errors in production."}),"\n",(0,i.jsxs)(t.p,{children:["We've put a lot of care into making it easy to make a TypeScript CLI even if you've never written TypeScript before. We generate CLIs and plugins that use ",(0,i.jsx)(t.a,{href:"https://github.com/TypeStrong/ts-node",children:"ts-node"})," to make it fast to run the TypeScript code without a compilation step. You won't have to mess around with build configuration using oclif."]}),"\n",(0,i.jsx)(t.p,{children:"Still, the languages today are very similar. The code you write in JavaScript will be nearly identical to what you would have in TypeScript. (Just no type definitions, of course)"}),"\n",(0,i.jsx)(t.h2,{id:"what-editor-is-best-for-oclif",children:"What editor is best for oclif?"}),"\n",(0,i.jsxs)(t.p,{children:["Of course if you already have a go-to editor, you should use that. However, we typically recommend ",(0,i.jsx)(t.a,{href:"https://code.visualstudio.com",children:"vscode"}),"."]}),"\n",(0,i.jsx)(t.p,{children:"Microsoft has done a great job with this editor and it works particularly well in TypeScript projects. You'll get nice type checking, linting, and autocomplete right out of the box."}),"\n",(0,i.jsx)(t.h2,{id:"should-i-use-npm-or-yarn",children:"Should I use npm or yarn?"}),"\n",(0,i.jsx)(t.p,{children:"It really doesn't make that much of a difference. If you're just getting started, keep it simple and use npm which comes with Node. We like to use yarn internally as it's a bit faster and we find the lockfiles friendlier."}),"\n",(0,i.jsx)(t.h2,{id:"how-can-i-make-the-oclif-generator-run-faster",children:"How can I make the oclif generator run faster?"}),"\n",(0,i.jsxs)(t.p,{children:["If you're using npx, install it first with ",(0,i.jsx)(t.code,{children:"npm install -g oclif"}),". This won't stay current with updates though, so you'll need to run ",(0,i.jsx)(t.code,{children:"npm update -g oclif"})," to get new versions of the generator."]}),"\n",(0,i.jsx)(t.h2,{id:"why-isnt-node-x-supported",children:"Why isn't Node X supported?"}),"\n",(0,i.jsxs)(t.p,{children:["The oclif project follows and supports ",(0,i.jsx)(t.a,{href:"https://nodejs.org/en/about/releases/",children:"Node's LTS support schedule"}),". This allows oclif to stay current with Node's development."]}),"\n",(0,i.jsx)(t.h2,{id:"how-do-i-pronounce-oclif",children:'How do I pronounce "oclif"?'}),"\n",(0,i.jsx)(t.p,{children:'We say "oh-cliff".'})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>r,x:()=>a});var i=o(6540);const n={},s=i.createContext(n);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/9eaa546a.5801dc53.js b/assets/js/9eaa546a.45d375f7.js
similarity index 99%
rename from assets/js/9eaa546a.5801dc53.js
rename to assets/js/9eaa546a.45d375f7.js
index 9eb1a1d9..a6fe5526 100644
--- a/assets/js/9eaa546a.5801dc53.js
+++ b/assets/js/9eaa546a.45d375f7.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4711],{2449:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>l,toc:()=>c});var o=n(4848),i=n(8453);const s={title:"Features"},a=void 0,l={id:"features",title:"Features",description:"Flag/Argument parsing",source:"@site/../docs/features.md",sourceDirName:".",slug:"/features",permalink:"/docs/features",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/features.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Features"},sidebar:"docs",previous:{title:"Introduction",permalink:"/docs/introduction"},next:{title:"FAQs",permalink:"/docs/faqs"}},r={},c=[{value:"Flag/Argument parsing",id:"flagargument-parsing",level:3},{value:"Configurable Topic Separators",id:"configurable-topic-separators",level:3},{value:"Super Speed",id:"super-speed",level:3},{value:"CLI Generator",id:"cli-generator",level:3},{value:"Testing Helpers",id:"testing-helpers",level:3},{value:"Auto-documentation",id:"auto-documentation",level:3},{value:"Plugins",id:"plugins",level:3},{value:"Hooks",id:"hooks",level:3},{value:"JSON Output",id:"json-output",level:3},{value:"TypeScript (or not)",id:"typescript-or-not",level:3},{value:"Auto-updating Installers",id:"auto-updating-installers",level:3},{value:"Autocomplete",id:"autocomplete",level:3}];function d(e){const t={a:"a",code:"code",h3:"h3",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h3,{id:"flagargument-parsing",children:"Flag/Argument parsing"}),"\n",(0,o.jsx)(t.p,{children:"No CLI framework would be complete without a flag parser. We've built a custom one from years of experimentation that we feel consistently handles user input flexible enough for the user to be able to easily use the CLI in ways they expect, but without compromising strictness guarantees to the developer."}),"\n",(0,o.jsx)(t.h3,{id:"configurable-topic-separators",children:"Configurable Topic Separators"}),"\n",(0,o.jsxs)(t.p,{children:["By default topics will be separated with colons, e.g. ",(0,o.jsx)(t.code,{children:"my:awesome:command"}),". However, you have the option to use spaces if you prefer, e.g. ",(0,o.jsx)(t.code,{children:"my awesome command"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"super-speed",children:"Super Speed"}),"\n",(0,o.jsxs)(t.p,{children:["The overhead for running an oclif CLI command is almost nothing. ",(0,o.jsx)(t.a,{href:"https://www.npmjs.com/package/@oclif/core?activeTab=dependencies",children:"It requires very few dependencies"})," (only 28 dependencies in a minimal setup\u2014including all transitive dependencies). Also, only the command to be executed will be required with node. So large CLIs with many commands will load just as fast as a small one with a single command."]}),"\n",(0,o.jsx)(t.h3,{id:"cli-generator",children:"CLI Generator"}),"\n",(0,o.jsxs)(t.p,{children:["Run a single command to scaffold out a fully functional CLI and get started quickly. See ",(0,o.jsx)(t.a,{href:"https://oclif.io/docs/generator_commands",children:"Generator Commands"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"testing-helpers",children:"Testing Helpers"}),"\n",(0,o.jsxs)(t.p,{children:["We've put a lot of work into making commands easily testable and easy to mock out stdout/stderr. The generator will automatically create ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/hello-world/blob/main/test/commands/hello/world.test.ts",children:"scaffolded tests"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"auto-documentation",children:"Auto-documentation"}),"\n",(0,o.jsxs)(t.p,{children:["By default you can pass ",(0,o.jsx)(t.code,{children:"--help"})," to the CLI to get help such as flag options and argument information. This information is also automatically placed in the README whenever the npm package of the CLI is published. See the ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/hello-world",children:"hello-world CLI example"})]}),"\n",(0,o.jsx)(t.h3,{id:"plugins",children:"Plugins"}),"\n",(0,o.jsxs)(t.p,{children:["Using plugins, users of the CLI can extend it with new functionality, a CLI can be split into modular components, and functionality can be shared amongst multiple CLIs. See ",(0,o.jsx)(t.a,{href:"https://oclif.io/docs/plugins#building-your-own-plugin",children:"Building your own plugin"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"hooks",children:"Hooks"}),"\n",(0,o.jsxs)(t.p,{children:["Use lifecycle hooks to run functionality any time a CLI starts, or on custom triggers. Use this whenever custom functionality needs to be shared between various components of the CLI. See ",(0,o.jsx)(t.a,{href:"https://oclif.io/docs/hooks",children:"Hooks"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"json-output",children:"JSON Output"}),"\n",(0,o.jsxs)(t.p,{children:["You can opt-in to using the ",(0,o.jsx)(t.code,{children:"--json"})," flag which will automatically suppress console logs and display the final result of the command as valid JSON output. This is very useful if you want your CLI to be used for scripting in CI/CD environments. See ",(0,o.jsx)(t.a,{href:"https://oclif.io/docs/json",children:"JSON"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"typescript-or-not",children:"TypeScript (or not)"}),"\n",(0,o.jsxs)(t.p,{children:["Everything in the core of oclif is written in TypeScript and the generator can build fully configured TypeScript CLIs or just plain JavaScript CLIs. By virtue of static properties in TypeScript the syntax is a bit cleaner in TypeScript \u2014 but everything will work no matter which language you choose. If you use plugins support, the CLI will automatically use ",(0,o.jsx)(t.code,{children:"ts-node"})," to run the plugins making it easy and fast to use TypeScript with minimal-to-no boilerplate needed for any oclif CLI."]}),"\n",(0,o.jsx)(t.h3,{id:"auto-updating-installers",children:"Auto-updating Installers"}),"\n",(0,o.jsxs)(t.p,{children:["oclif can package your CLI into ",(0,o.jsx)(t.a,{href:"/docs/releasing",children:"different installers"})," that will not require the user to already have node installed on the machine. These can be made auto-updatable by using ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/plugin-update",children:"plugin-update"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"autocomplete",children:"Autocomplete"}),"\n",(0,o.jsxs)(t.p,{children:["Include terminal autocompletion for your CLI via ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/plugin-autocomplete",children:"plugin-autocomplete"}),". Once installed, users can complete command names and flag names."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-bash",children:"$ my-cli pHelpBase
class",id:"extending-the-helpbase-class",level:2},{value:"Extending the default Help
class",id:"extending-the-default-help-class",level:2},{value:"Building custom help classes in JavaScript projects",id:"building-custom-help-classes-in-javascript-projects",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Out of the box oclif provides a great help experience for CLIs. Users can invoke help with the ",(0,s.jsx)(n.code,{children:"--help"})," flag."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ my-cli login --help\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you want your CLI to have an explicit ",(0,s.jsx)(n.code,{children:"help"})," command, add ",(0,s.jsx)(n.code,{children:"@oclif/plugin-help"})," as an ",(0,s.jsx)(n.a,{href:"/docs/plugins",children:"oclif plugin in your config"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ my-cli help\n"})}),"\n",(0,s.jsx)(n.h2,{id:"custom-help",children:"Custom Help"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ yarn add @oclif/core --latest\n"})}),"\n",(0,s.jsx)(n.p,{children:"To get started, first define the filepath to your help class in oclif's config in package.json. This is a relative path to the help class, without a file extension."}),"\n",(0,s.jsx)(n.p,{children:'For this example, the help class will be created in a file at "[project root]/src/help.ts".'}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n // ...\n "oclif": {\n "helpClass": "./dist/help"\n // ...\n }\n // ...\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["From here there are two paths, implement the ",(0,s.jsx)(n.code,{children:"HelpBase"})," abstract class yourself or overwrite the parts of the default ",(0,s.jsx)(n.code,{children:"Help"})," class you want to customize (ex: how command usage is displayed). We recommend the latter approach but cover both below."]}),"\n",(0,s.jsxs)(n.h2,{id:"extending-the-helpbase-class",children:["Extending the ",(0,s.jsx)(n.code,{children:"HelpBase"})," class"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"HelpBase"})," abstract class provides a starting point requiring the minimum needed methods implemented to be compatible with oclif."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-TypeScript",children:"import {Command, HelpBase} from '@oclif/core';\n\nexport default class CustomHelp extends HelpBase {\n showHelp(args: string[]) {\n console.log('This will be displayed in multi-command CLIs')\n }\n\n showCommandHelp(command: Command) {\n console.log('This will be displayed in single-command CLIs')\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"showHelp"})," method is called by oclif to display help in multi-command CLIs, while ",(0,s.jsx)(n.code,{children:"showCommandHelp"})," is called directly for single-command CLIs."]}),"\n",(0,s.jsxs)(n.p,{children:["The class is instantiated with a ",(0,s.jsx)(n.code,{children:"config"})," property that provides helpful context for constructing your custom output."]}),"\n",(0,s.jsxs)(n.p,{children:["To see an example of what is possible take a look at the source code for the ",(0,s.jsxs)(n.a,{href:"https://github.com/oclif/core/blob/main/src/help/index.ts",children:["default ",(0,s.jsx)(n.code,{children:"Help"})," class exported from @oclif/core"]}),"."]}),"\n",(0,s.jsxs)(n.h2,{id:"extending-the-default-help-class",children:["Extending the default ",(0,s.jsx)(n.code,{children:"Help"})," class"]}),"\n",(0,s.jsxs)(n.p,{children:["The default ",(0,s.jsx)(n.code,{children:"Help"})," class provides many method \u201chooks\u201d that make it easy to override the particular parts of help's output you want to customize."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-TypeScript",children:"import {Command, Help, Topic} from '@oclif/core';\n\nexport default class MyHelpClass extends Help {\n // acts as a \"router\"\n // and based on the args it receives\n // calls one of showRootHelp, showTopicHelp,\n // or showCommandHelp\n showHelp(args: string[]): void {\n }\n\n // display the root help of a CLI\n showRootHelp(): void {\n }\n\n // display help for a topic\n showTopicHelp(topic: Topic): void {\n }\n\n // display help for a command\n showCommandHelp(command: Command): void {\n }\n\n // the default implementations of showRootHelp\n // showTopicHelp and showCommandHelp\n // will call various format methods that\n // provide the formatting for their corresponding\n // help sections;\n // these can be overwritten as well\n\n // the formatting responsible for the header\n // displayed for the root help\n formatRoot(): string {\n }\n\n // the formatting for an individual topic\n formatTopic(topic: Config.Topic): string {\n }\n\n // the formatting for a list of topics\n protected formatTopics(topics: Config.Topic[]): string {\n }\n\n // the formatting for a list of commands\n formatCommands(commands: Config.Command[]): string {\n }\n\n // the formatting for an individual command\n formatCommand(command: Config.Command): string {\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["To see the default implementation of these methods take a look at the ",(0,s.jsxs)(n.a,{href:"https://github.com/oclif/core/blob/main/src/help/index.ts",children:["default ",(0,s.jsx)(n.code,{children:"Help"})," class exported from @oclif/core"]}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["To start experimenting, define ",(0,s.jsx)(n.code,{children:"showCommandHelp"})," in your custom help class and change the output."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-TypeScript",children:"import {Command, Help, Topic} from '@oclif/core';\n\nexport default class MyHelpClass extends Help {\n public showCommandHelp(command: Config.Command) {\n console.log('Display my custom command help!')\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Then run help for any command."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ my-cli login --help\nDisplay my custom command help!\n"})}),"\n",(0,s.jsx)(n.h2,{id:"building-custom-help-classes-in-javascript-projects",children:"Building custom help classes in JavaScript projects"}),"\n",(0,s.jsxs)(n.p,{children:['These examples above followed a TypeScript project. For JavaScript project with an example help file at "[project root]/src/help.js" would have a package.json with the ',(0,s.jsx)(n.code,{children:"helpClass"})," defined:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n // ...\n "oclif": {\n "helpClass": "./src/help"\n // ...\n }\n // ...\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:"The imports are handled slightly different for JavaScript projects but the rest of the help class mimic the TypeScript examples above, except without type annotations."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"const {HelpBase} = require('@oclif/core');\n\nmodule.exports = class MyHelpClass extends HelpBase {\n showHelp(args) {\n console.log('This will be displayed in multi-command CLIs')\n }\n\n showCommandHelp(command) {\n console.log('This will be displayed for a single command')\n }\n}\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"const {Help} = require('@oclif/core');\n\nmodule.exports = class MyHelpClass extends Help {\n showHelp(args) {\n }\n\n showRootHelp() {\n }\n\n showTopicHelp(topic) {\n }\n\n showCommandHelp(command) {\n }\n\n formatRoot() {\n }\n\n formatTopic(topic) {\n }\n\n formatTopics(topics) {\n }\n\n formatCommands(commands) {\n }\n\n formatCommand(command) {\n }\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>i,x:()=>c});var s=o(6540);const l={},t=s.createContext(l);function i(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:i(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9036],{354:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>t,metadata:()=>c,toc:()=>r});var s=o(4848),l=o(8453);const t={title:"Help Classes"},i=void 0,c={id:"help_classes",title:"Help Classes",description:"Out of the box oclif provides a great help experience for CLIs. Users can invoke help with the --help flag.",source:"@site/../docs/help_classes.md",sourceDirName:".",slug:"/help_classes",permalink:"/docs/help_classes",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/help_classes.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Help Classes"},sidebar:"docs",previous:{title:"Plugins",permalink:"/docs/plugins"},next:{title:"Error Handling",permalink:"/docs/error_handling"}},a={},r=[{value:"Custom Help",id:"custom-help",level:2},{value:"Extending the HelpBase
class",id:"extending-the-helpbase-class",level:2},{value:"Extending the default Help
class",id:"extending-the-default-help-class",level:2},{value:"Building custom help classes in JavaScript projects",id:"building-custom-help-classes-in-javascript-projects",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Out of the box oclif provides a great help experience for CLIs. Users can invoke help with the ",(0,s.jsx)(n.code,{children:"--help"})," flag."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ my-cli login --help\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you want your CLI to have an explicit ",(0,s.jsx)(n.code,{children:"help"})," command, add ",(0,s.jsx)(n.code,{children:"@oclif/plugin-help"})," as an ",(0,s.jsx)(n.a,{href:"/docs/plugins",children:"oclif plugin in your config"}),"."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ my-cli help\n"})}),"\n",(0,s.jsx)(n.h2,{id:"custom-help",children:"Custom Help"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ yarn add @oclif/core --latest\n"})}),"\n",(0,s.jsx)(n.p,{children:"To get started, first define the filepath to your help class in oclif's config in package.json. This is a relative path to the help class, without a file extension."}),"\n",(0,s.jsx)(n.p,{children:'For this example, the help class will be created in a file at "[project root]/src/help.ts".'}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n // ...\n "oclif": {\n "helpClass": "./dist/help"\n // ...\n }\n // ...\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["From here there are two paths, implement the ",(0,s.jsx)(n.code,{children:"HelpBase"})," abstract class yourself or overwrite the parts of the default ",(0,s.jsx)(n.code,{children:"Help"})," class you want to customize (ex: how command usage is displayed). We recommend the latter approach but cover both below."]}),"\n",(0,s.jsxs)(n.h2,{id:"extending-the-helpbase-class",children:["Extending the ",(0,s.jsx)(n.code,{children:"HelpBase"})," class"]}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"HelpBase"})," abstract class provides a starting point requiring the minimum needed methods implemented to be compatible with oclif."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-TypeScript",children:"import {Command, HelpBase} from '@oclif/core';\n\nexport default class CustomHelp extends HelpBase {\n showHelp(args: string[]) {\n console.log('This will be displayed in multi-command CLIs')\n }\n\n showCommandHelp(command: Command) {\n console.log('This will be displayed in single-command CLIs')\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"showHelp"})," method is called by oclif to display help in multi-command CLIs, while ",(0,s.jsx)(n.code,{children:"showCommandHelp"})," is called directly for single-command CLIs."]}),"\n",(0,s.jsxs)(n.p,{children:["The class is instantiated with a ",(0,s.jsx)(n.code,{children:"config"})," property that provides helpful context for constructing your custom output."]}),"\n",(0,s.jsxs)(n.p,{children:["To see an example of what is possible take a look at the source code for the ",(0,s.jsxs)(n.a,{href:"https://github.com/oclif/core/blob/main/src/help/index.ts",children:["default ",(0,s.jsx)(n.code,{children:"Help"})," class exported from @oclif/core"]}),"."]}),"\n",(0,s.jsxs)(n.h2,{id:"extending-the-default-help-class",children:["Extending the default ",(0,s.jsx)(n.code,{children:"Help"})," class"]}),"\n",(0,s.jsxs)(n.p,{children:["The default ",(0,s.jsx)(n.code,{children:"Help"})," class provides many method \u201chooks\u201d that make it easy to override the particular parts of help's output you want to customize."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-TypeScript",children:"import {Command, Help, Topic} from '@oclif/core';\n\nexport default class MyHelpClass extends Help {\n // acts as a \"router\"\n // and based on the args it receives\n // calls one of showRootHelp, showTopicHelp,\n // or showCommandHelp\n showHelp(args: string[]): void {\n }\n\n // display the root help of a CLI\n showRootHelp(): void {\n }\n\n // display help for a topic\n showTopicHelp(topic: Topic): void {\n }\n\n // display help for a command\n showCommandHelp(command: Command): void {\n }\n\n // the default implementations of showRootHelp\n // showTopicHelp and showCommandHelp\n // will call various format methods that\n // provide the formatting for their corresponding\n // help sections;\n // these can be overwritten as well\n\n // the formatting responsible for the header\n // displayed for the root help\n formatRoot(): string {\n }\n\n // the formatting for an individual topic\n formatTopic(topic: Config.Topic): string {\n }\n\n // the formatting for a list of topics\n protected formatTopics(topics: Config.Topic[]): string {\n }\n\n // the formatting for a list of commands\n formatCommands(commands: Config.Command[]): string {\n }\n\n // the formatting for an individual command\n formatCommand(command: Config.Command): string {\n }\n}\n"})}),"\n",(0,s.jsxs)(n.p,{children:["To see the default implementation of these methods take a look at the ",(0,s.jsxs)(n.a,{href:"https://github.com/oclif/core/blob/main/src/help/index.ts",children:["default ",(0,s.jsx)(n.code,{children:"Help"})," class exported from @oclif/core"]}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["To start experimenting, define ",(0,s.jsx)(n.code,{children:"showCommandHelp"})," in your custom help class and change the output."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-TypeScript",children:"import {Command, Help, Topic} from '@oclif/core';\n\nexport default class MyHelpClass extends Help {\n public showCommandHelp(command: Config.Command) {\n console.log('Display my custom command help!')\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Then run help for any command."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ my-cli login --help\nDisplay my custom command help!\n"})}),"\n",(0,s.jsx)(n.h2,{id:"building-custom-help-classes-in-javascript-projects",children:"Building custom help classes in JavaScript projects"}),"\n",(0,s.jsxs)(n.p,{children:['These examples above followed a TypeScript project. For JavaScript project with an example help file at "[project root]/src/help.js" would have a package.json with the ',(0,s.jsx)(n.code,{children:"helpClass"})," defined:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'{\n // ...\n "oclif": {\n "helpClass": "./src/help"\n // ...\n }\n // ...\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:"The imports are handled slightly different for JavaScript projects but the rest of the help class mimic the TypeScript examples above, except without type annotations."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"const {HelpBase} = require('@oclif/core');\n\nmodule.exports = class MyHelpClass extends HelpBase {\n showHelp(args) {\n console.log('This will be displayed in multi-command CLIs')\n }\n\n showCommandHelp(command) {\n console.log('This will be displayed for a single command')\n }\n}\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"const {Help} = require('@oclif/core');\n\nmodule.exports = class MyHelpClass extends Help {\n showHelp(args) {\n }\n\n showRootHelp() {\n }\n\n showTopicHelp(topic) {\n }\n\n showCommandHelp(command) {\n }\n\n formatRoot() {\n }\n\n formatTopic(topic) {\n }\n\n formatTopics(topics) {\n }\n\n formatCommands(commands) {\n }\n\n formatCommand(command) {\n }\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>i,x:()=>c});var s=o(6540);const l={},t=s.createContext(l);function i(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:i(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f182954c.53a8635a.js b/assets/js/f182954c.67c31c13.js
similarity index 96%
rename from assets/js/f182954c.53a8635a.js
rename to assets/js/f182954c.67c31c13.js
index a598c5b6..6e74b5db 100644
--- a/assets/js/f182954c.53a8635a.js
+++ b/assets/js/f182954c.67c31c13.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[607],{3685:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>n,metadata:()=>l,toc:()=>a});var r=o(4848),s=o(8453);const n={title:"Related Repositories"},i=void 0,l={id:"related_repos",title:"Related Repositories",description:"* @oclif/core - Base library for oclif CLIs or plugins. This can be used directly without the generator.",source:"@site/../docs/related_repos.md",sourceDirName:".",slug:"/related_repos",permalink:"/docs/related_repos",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/related_repos.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Related Repositories"},sidebar:"docs",previous:{title:"External Links",permalink:"/docs/external_links"},next:{title:"How We Work",permalink:"/docs/how_we_work"}},c={},a=[];function d(e){const t={a:"a",li:"li",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://github.com/oclif/core",children:"@oclif/core"})," - Base library for oclif CLIs or plugins. This can be used directly without the generator."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://github.com/oclif/test",children:"@oclif/test"})," - Test helper for oclif."]}),"\n"]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>l});var r=o(6540);const s={},n=r.createContext(s);function i(e){const t=r.useContext(n);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(n.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[607],{3685:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>n,metadata:()=>l,toc:()=>a});var r=o(4848),s=o(8453);const n={title:"Related Repositories"},i=void 0,l={id:"related_repos",title:"Related Repositories",description:"* @oclif/core - Base library for oclif CLIs or plugins. This can be used directly without the generator.",source:"@site/../docs/related_repos.md",sourceDirName:".",slug:"/related_repos",permalink:"/docs/related_repos",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/related_repos.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Related Repositories"},sidebar:"docs",previous:{title:"External Links",permalink:"/docs/external_links"},next:{title:"How We Work",permalink:"/docs/how_we_work"}},c={},a=[];function d(e){const t={a:"a",li:"li",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://github.com/oclif/core",children:"@oclif/core"})," - Base library for oclif CLIs or plugins. This can be used directly without the generator."]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://github.com/oclif/test",children:"@oclif/test"})," - Test helper for oclif."]}),"\n"]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>i,x:()=>l});var r=o(6540);const s={},n=r.createContext(s);function i(e){const t=r.useContext(n);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(n.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f6c5328e.c07cba91.js b/assets/js/f6c5328e.a958af26.js
similarity index 97%
rename from assets/js/f6c5328e.c07cba91.js
rename to assets/js/f6c5328e.a958af26.js
index 6b8366be..7794bd10 100644
--- a/assets/js/f6c5328e.c07cba91.js
+++ b/assets/js/f6c5328e.a958af26.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9181],{5500:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>r});var t=o(4848),s=o(8453);const i={title:"Hooks"},c=void 0,l={id:"hooks",title:"Hooks",description:"oclif exposes lifecycle event hooks such as init and commandnotfound. See below for a list of all the lifecycle events. In addition to these built-in events, you can create your own events and allow commands/plugins to watch for these custom events. It's a great way to allow multiple plugins to interact with each other.",source:"@site/../docs/hooks.md",sourceDirName:".",slug:"/hooks",permalink:"/docs/hooks",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/hooks.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Hooks"},sidebar:"docs",previous:{title:"Topic Separators",permalink:"/docs/topic_separator"},next:{title:"Plugins",permalink:"/docs/plugins"}},a={},r=[{value:"Lifecycle Events",id:"lifecycle-events",level:2},{value:"Custom Events",id:"custom-events",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["oclif exposes lifecycle event hooks such as ",(0,t.jsx)(n.code,{children:"init"})," and ",(0,t.jsx)(n.code,{children:"command_not_found"}),". ",(0,t.jsx)(n.a,{href:"#lifecycle-events",children:"See below for a list of all the lifecycle events"}),". In addition to these built-in events, you can create your own events and allow commands/plugins to watch for these custom events. It's a great way to allow multiple plugins to interact with each other."]}),"\n",(0,t.jsxs)(n.p,{children:["Multiple hooks are run in parallel. ",(0,t.jsx)(n.strong,{children:"This behavior may change in a future release."})]}),"\n",(0,t.jsx)(n.p,{children:"A basic hook looks like the following in TypeScript:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Hook} from '@oclif/core'\n\nconst hook: Hook<'init'> = async function (options) {\n console.log(`example init hook running before ${options.id}`)\n}\n\nexport default hook\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The hook must also be declared with the event's name and hook's file path under oclif's settings in ",(0,t.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:' "oclif": {\n "commands": "./lib/commands",\n "hooks": {\n "init": "./lib/hooks/init/example"\n }\n }\n'})}),"\n",(0,t.jsx)(n.p,{children:"Multiple hooks of the same event type can be declared with an array."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:' "oclif": {\n "commands": "./lib/commands",\n "hooks": {\n "init": [\n "./lib/hooks/init/example",\n "./lib/hooks/init/another_hook"\n ]\n }\n }\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You can create hooks with ",(0,t.jsx)(n.code,{children:"oclif generate hook myhook --event=init"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"lifecycle-events",children:"Lifecycle Events"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"init"})," - runs when the CLI is initialized before a command is found to run"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"prerun"})," - runs after ",(0,t.jsx)(n.code,{children:"init"})," and after the command is found, but just before running the command itself"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"postrun"})," - runs after the command only if the command finishes with no error"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"command_not_found"})," - runs if a command is not found before the error is displayed"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"custom-events",children:"Custom Events"}),"\n",(0,t.jsxs)(n.p,{children:["Custom events are just like lifecycle events, but you need to call ",(0,t.jsx)(n.code,{children:"this.config.runHook()"})," to fire the event."]}),"\n",(0,t.jsx)(n.p,{children:"For example, you could define an analytics post function that you will run in your command after submitting analytics telemetry. First define:"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"src/hooks/analytics/post.ts"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const hook = async function (options: {id: string}) {\n // code to post options.id to analytics server\n}\n\nexport default hook\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"package.json"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:' "oclif": {\n "commands": "./lib/commands",\n "hooks": {\n "analytics": "./lib/hooks/analytics/post"\n },\n },\n'})}),"\n",(0,t.jsx)(n.p,{children:"Then in any command you want to trigger the event:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:"export class extends Command {\n async run() {\n // emit analytics\n await this.config.runHook('analytics', {id: 'my_command'})\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you need to exit during a hook, use ",(0,t.jsx)(n.code,{children:"this.error()"})," or ",(0,t.jsx)(n.code,{children:"this.exit()"}),". Otherwise the hook will just emit a warning. This is to prevent an issue such as a plugin failing in ",(0,t.jsx)(n.code,{children:"init"})," causing the entire CLI to not function."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>c,x:()=>l});var t=o(6540);const s={},i=t.createContext(s);function c(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9181],{5500:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>i,metadata:()=>l,toc:()=>r});var t=o(4848),s=o(8453);const i={title:"Hooks"},c=void 0,l={id:"hooks",title:"Hooks",description:"oclif exposes lifecycle event hooks such as init and commandnotfound. See below for a list of all the lifecycle events. In addition to these built-in events, you can create your own events and allow commands/plugins to watch for these custom events. It's a great way to allow multiple plugins to interact with each other.",source:"@site/../docs/hooks.md",sourceDirName:".",slug:"/hooks",permalink:"/docs/hooks",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/hooks.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Hooks"},sidebar:"docs",previous:{title:"Topic Separators",permalink:"/docs/topic_separator"},next:{title:"Plugins",permalink:"/docs/plugins"}},a={},r=[{value:"Lifecycle Events",id:"lifecycle-events",level:2},{value:"Custom Events",id:"custom-events",level:2}];function d(e){const n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["oclif exposes lifecycle event hooks such as ",(0,t.jsx)(n.code,{children:"init"})," and ",(0,t.jsx)(n.code,{children:"command_not_found"}),". ",(0,t.jsx)(n.a,{href:"#lifecycle-events",children:"See below for a list of all the lifecycle events"}),". In addition to these built-in events, you can create your own events and allow commands/plugins to watch for these custom events. It's a great way to allow multiple plugins to interact with each other."]}),"\n",(0,t.jsxs)(n.p,{children:["Multiple hooks are run in parallel. ",(0,t.jsx)(n.strong,{children:"This behavior may change in a future release."})]}),"\n",(0,t.jsx)(n.p,{children:"A basic hook looks like the following in TypeScript:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Hook} from '@oclif/core'\n\nconst hook: Hook<'init'> = async function (options) {\n console.log(`example init hook running before ${options.id}`)\n}\n\nexport default hook\n"})}),"\n",(0,t.jsxs)(n.p,{children:["The hook must also be declared with the event's name and hook's file path under oclif's settings in ",(0,t.jsx)(n.code,{children:"package.json"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:' "oclif": {\n "commands": "./lib/commands",\n "hooks": {\n "init": "./lib/hooks/init/example"\n }\n }\n'})}),"\n",(0,t.jsx)(n.p,{children:"Multiple hooks of the same event type can be declared with an array."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:' "oclif": {\n "commands": "./lib/commands",\n "hooks": {\n "init": [\n "./lib/hooks/init/example",\n "./lib/hooks/init/another_hook"\n ]\n }\n }\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You can create hooks with ",(0,t.jsx)(n.code,{children:"oclif generate hook myhook --event=init"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"lifecycle-events",children:"Lifecycle Events"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"init"})," - runs when the CLI is initialized before a command is found to run"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"prerun"})," - runs after ",(0,t.jsx)(n.code,{children:"init"})," and after the command is found, but just before running the command itself"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"postrun"})," - runs after the command only if the command finishes with no error"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"command_not_found"})," - runs if a command is not found before the error is displayed"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"custom-events",children:"Custom Events"}),"\n",(0,t.jsxs)(n.p,{children:["Custom events are just like lifecycle events, but you need to call ",(0,t.jsx)(n.code,{children:"this.config.runHook()"})," to fire the event."]}),"\n",(0,t.jsx)(n.p,{children:"For example, you could define an analytics post function that you will run in your command after submitting analytics telemetry. First define:"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"src/hooks/analytics/post.ts"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const hook = async function (options: {id: string}) {\n // code to post options.id to analytics server\n}\n\nexport default hook\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"package.json"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:' "oclif": {\n "commands": "./lib/commands",\n "hooks": {\n "analytics": "./lib/hooks/analytics/post"\n },\n },\n'})}),"\n",(0,t.jsx)(n.p,{children:"Then in any command you want to trigger the event:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:"export class extends Command {\n async run() {\n // emit analytics\n await this.config.runHook('analytics', {id: 'my_command'})\n }\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["If you need to exit during a hook, use ",(0,t.jsx)(n.code,{children:"this.error()"})," or ",(0,t.jsx)(n.code,{children:"this.exit()"}),". Otherwise the hook will just emit a warning. This is to prevent an issue such as a plugin failing in ",(0,t.jsx)(n.code,{children:"init"})," causing the entire CLI to not function."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>c,x:()=>l});var t=o(6540);const s={},i=t.createContext(s);function c(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:c(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/f905d0fe.e4e807ba.js b/assets/js/f905d0fe.2c295ea7.js
similarity index 93%
rename from assets/js/f905d0fe.e4e807ba.js
rename to assets/js/f905d0fe.2c295ea7.js
index f7b57572..8c4febd3 100644
--- a/assets/js/f905d0fe.e4e807ba.js
+++ b/assets/js/f905d0fe.2c295ea7.js
@@ -1 +1 @@
-"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6122],{156:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var o=n(4848),c=n(8453);const a={title:"Command Execution"},i=void 0,s={id:"command_execution",title:"Command Execution",description:"Below is a diagram that outlines at a high level the process that occurs every time a user executes an oclif command.",source:"@site/../docs/command_execution.md",sourceDirName:".",slug:"/command_execution",permalink:"/docs/command_execution",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/command_execution.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Command Execution"},sidebar:"docs",previous:{title:"Generator Commands",permalink:"/docs/generator_commands"},next:{title:"Plugin Loading",permalink:"/docs/plugin_loading"}},r={},d=[];function m(e){const t={img:"img",p:"p",...(0,c.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"Below is a diagram that outlines at a high level the process that occurs every time a user executes an oclif command."}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"command execution flow",src:n(28).A+"",width:"3258",height:"4910"})})]})}function u(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(m,{...e})}):m(e)}},28:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/command-execution-flow-7722f834b51111bcf89f6c2f7ae2cdf5.jpg"},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>s});var o=n(6540);const c={},a=o.createContext(c);function i(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:i(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
+"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6122],{156:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>r,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>s,toc:()=>d});var o=n(4848),c=n(8453);const a={title:"Command Execution"},i=void 0,s={id:"command_execution",title:"Command Execution",description:"Below is a diagram that outlines at a high level the process that occurs every time a user executes an oclif command.",source:"@site/../docs/command_execution.md",sourceDirName:".",slug:"/command_execution",permalink:"/docs/command_execution",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/command_execution.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Command Execution"},sidebar:"docs",previous:{title:"Generator Commands",permalink:"/docs/generator_commands"},next:{title:"Plugin Loading",permalink:"/docs/plugin_loading"}},r={},d=[];function m(e){const t={img:"img",p:"p",...(0,c.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.p,{children:"Below is a diagram that outlines at a high level the process that occurs every time a user executes an oclif command."}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.img,{alt:"command execution flow",src:n(28).A+"",width:"3258",height:"4910"})})]})}function u(e={}){const{wrapper:t}={...(0,c.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(m,{...e})}):m(e)}},28:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/command-execution-flow-7722f834b51111bcf89f6c2f7ae2cdf5.jpg"},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>s});var o=n(6540);const c={},a=o.createContext(c);function i(e){const t=o.useContext(a);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function s(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(c):e.components||c:i(e.components),o.createElement(a.Provider,{value:t},e.children)}}}]);
\ No newline at end of file
diff --git a/assets/js/runtime~main.a7ad947a.js b/assets/js/runtime~main.c6cfc268.js
similarity index 82%
rename from assets/js/runtime~main.a7ad947a.js
rename to assets/js/runtime~main.c6cfc268.js
index e9320382..3608bd97 100644
--- a/assets/js/runtime~main.a7ad947a.js
+++ b/assets/js/runtime~main.c6cfc268.js
@@ -1 +1 @@
-(()=>{"use strict";var e,a,c,d,f={},b={};function r(e){var a=b[e];if(void 0!==a)return a.exports;var c=b[e]={id:e,loaded:!1,exports:{}};return f[e].call(c.exports,c,c.exports,r),c.loaded=!0,c.exports}r.m=f,r.c=b,e=[],r.O=(a,c,d,f)=>{if(!c){var b=1/0;for(i=0;iCreating a CLI that responds to different names or "aliases" is easy, simply add a binAliases
property to your CLI's oclif
property in package.json
:
{
"name": "mycli",
"version": "0.0.0",
"description": "My CLI",
"main": "bin/run.js",
"bin": {
"mycli": "./bin/run.js",
"mycli-alias": "./bin/run.js"
},
"oclif": {
"binAliases": ["mycli", "mycli-alias"]
}
}
Adding this property allows your CLI to respond to either of those names, and is used during the bundling and building process when shipping your CLI. Note that the bin
section was also modified to include both aliases, which is how npm creates bin aliases. To create a unified experience, regardless of the installation method, a CLI author must change both to match. Bin aliases also play nicely with @oclif/plugin-autocomplete
, so typing an alias and using autocomplete is the same experience as using the original name.
Adding this property allows your CLI to respond to either of those names, and is used during the bundling and building process when shipping your CLI. Note that the bin
section was also modified to include both aliases, which is how npm creates bin aliases. To create a unified experience, regardless of the installation method, a CLI author must change both to match. Bin aliases also play nicely with @oclif/plugin-autocomplete
, so typing an alias and using autocomplete is the same experience as using the original name.