From 715c175c0bd852005d3bc5c00844184384740aa0 Mon Sep 17 00:00:00 2001 From: svc-cli-bot Date: Fri, 22 Mar 2024 15:39:34 +0000 Subject: [PATCH] Deploy website - based on d4e983271a7ac9e2931f952055af877ac0aaf730 --- 404.html | 2 +- assets/js/{03a88bad.3fa9ada6.js => 03a88bad.52baa0b3.js} | 2 +- assets/js/{03abeb31.5415b57b.js => 03abeb31.5f9309f2.js} | 2 +- assets/js/{0b218a01.00c2d643.js => 0b218a01.de27cef5.js} | 2 +- assets/js/{104cbb75.c7fb3ef1.js => 104cbb75.c2ce6e10.js} | 2 +- assets/js/{19fd9079.ac45505f.js => 19fd9079.0d5010f9.js} | 2 +- assets/js/{1ed4142b.646b4f19.js => 1ed4142b.a44c3e96.js} | 2 +- assets/js/{1f61ef73.ed364500.js => 1f61ef73.51af529c.js} | 2 +- assets/js/{2486267b.f4424fc4.js => 2486267b.0ba0fb70.js} | 2 +- assets/js/{258a6413.25eadca6.js => 258a6413.15131eb9.js} | 2 +- assets/js/{2a33acc4.376963de.js => 2a33acc4.ed23e4e6.js} | 2 +- assets/js/{2f98ad87.be46cc71.js => 2f98ad87.c0493a32.js} | 2 +- assets/js/{3042343a.8ba035fd.js => 3042343a.6b9057ed.js} | 2 +- assets/js/{30d74566.bf95441d.js => 30d74566.f5a0ed76.js} | 2 +- assets/js/{32060389.1eb0ee8b.js => 32060389.cc2c1970.js} | 2 +- assets/js/{35586d92.f1a1915a.js => 35586d92.a74fcd5f.js} | 2 +- assets/js/{3e452c7e.0139d8d2.js => 3e452c7e.747c7b5b.js} | 2 +- assets/js/{53e18611.cbaa63c9.js => 53e18611.174f50c6.js} | 2 +- assets/js/{5d5620c4.7d436f77.js => 5d5620c4.aa5bafe0.js} | 2 +- assets/js/{6f3bb722.82eaa226.js => 6f3bb722.36477967.js} | 2 +- assets/js/{713bb917.dbd2243e.js => 713bb917.cf149bb6.js} | 2 +- assets/js/{7bd58895.825ec359.js => 7bd58895.bbd59ad7.js} | 2 +- assets/js/{82247a8b.a76eaf65.js => 82247a8b.de433149.js} | 2 +- assets/js/{8705a681.a24a496a.js => 8705a681.eedb41eb.js} | 2 +- assets/js/{935116ff.7148886a.js => 935116ff.dc866d9f.js} | 2 +- assets/js/{9eaa546a.5801dc53.js => 9eaa546a.45d375f7.js} | 2 +- assets/js/{a92e169d.c9dc0b54.js => a92e169d.82f135f1.js} | 2 +- assets/js/{a96ec439.53b19970.js => a96ec439.3b3c006e.js} | 2 +- assets/js/{b3cc73c6.473e1578.js => b3cc73c6.b180e5dd.js} | 2 +- assets/js/{b4a95747.e4ee3a79.js => b4a95747.8bdd8694.js} | 2 +- assets/js/{c5890d18.2ec84b3e.js => c5890d18.1f021986.js} | 2 +- assets/js/{c81fd975.0551bf12.js => c81fd975.02a85bfa.js} | 2 +- assets/js/{c94a68c1.6d6c394a.js => c94a68c1.1dcb0da4.js} | 2 +- assets/js/{d0e73d62.44497857.js => d0e73d62.2de45aa6.js} | 2 +- assets/js/{d665a578.f44b824d.js => d665a578.a0187057.js} | 2 +- assets/js/{d9b0bdb4.243a840b.js => d9b0bdb4.3425f4a7.js} | 2 +- assets/js/{df1cd967.a69943d3.js => df1cd967.28611b4c.js} | 2 +- assets/js/{e360e27f.e043c1c2.js => e360e27f.158cd50e.js} | 2 +- assets/js/{e3703649.0f308291.js => e3703649.deb238ea.js} | 2 +- assets/js/{f182954c.53a8635a.js => f182954c.67c31c13.js} | 2 +- assets/js/{f6c5328e.c07cba91.js => f6c5328e.a958af26.js} | 2 +- assets/js/{f905d0fe.e4e807ba.js => f905d0fe.2c295ea7.js} | 2 +- .../js/{runtime~main.a7ad947a.js => runtime~main.c6cfc268.js} | 2 +- blog/2018/03/20/introducing-oclif/index.html | 2 +- blog/2019/02/20/cli-flags-explained/index.html | 2 +- blog/2019/10/31/oclif-node-updates/index.html | 2 +- blog/2019/12/05/oclif-eslint-migration/index.html | 2 +- blog/2020/05/05/introducing-custom-help-classes/index.html | 2 +- blog/2020/07/01/pretty-printable-errors/index.html | 2 +- blog/2020/08/26/summer-update/index.html | 2 +- blog/2021/03/01/introducing-oclif-core/index.html | 2 +- blog/2022/01/12/announcing-oclif-v2/index.html | 2 +- blog/archive/index.html | 2 +- blog/index.html | 2 +- docs/aliases/index.html | 4 ++-- docs/args/index.html | 4 ++-- docs/base_class/index.html | 4 ++-- docs/command_discovery_strategies/index.html | 4 ++-- docs/command_execution/index.html | 4 ++-- docs/commands/index.html | 4 ++-- docs/config/index.html | 4 ++-- docs/debugging/index.html | 4 ++-- docs/error_handling/index.html | 4 ++-- docs/esm/index.html | 4 ++-- docs/examples/index.html | 4 ++-- docs/external_links/index.html | 4 ++-- docs/faqs/index.html | 4 ++-- docs/features/index.html | 4 ++-- docs/feedback/index.html | 4 ++-- docs/flags/index.html | 4 ++-- docs/flexible_taxonomy/index.html | 4 ++-- docs/generator_commands/index.html | 4 ++-- docs/global_flags/index.html | 4 ++-- docs/help_classes/index.html | 4 ++-- docs/hooks/index.html | 4 ++-- docs/how_we_work/index.html | 4 ++-- docs/index.html | 4 ++-- docs/introduction/index.html | 4 ++-- docs/jit_plugins/index.html | 4 ++-- docs/json/index.html | 4 ++-- docs/notifications/index.html | 4 ++-- docs/nsis-installer_customization/index.html | 4 ++-- docs/plugin_loading/index.html | 4 ++-- docs/plugins/index.html | 4 ++-- docs/prompting/index.html | 4 ++-- docs/related_repos/index.html | 4 ++-- docs/releasing/index.html | 4 ++-- docs/running_programmatically/index.html | 4 ++-- docs/single_command_cli/index.html | 4 ++-- docs/spinner/index.html | 4 ++-- docs/table/index.html | 4 ++-- docs/testing/index.html | 4 ++-- docs/themes/index.html | 4 ++-- docs/topic_separator/index.html | 4 ++-- docs/topics/index.html | 4 ++-- index.html | 2 +- search/index.html | 2 +- 97 files changed, 138 insertions(+), 138 deletions(-) rename assets/js/{03a88bad.3fa9ada6.js => 03a88bad.52baa0b3.js} (94%) rename assets/js/{03abeb31.5415b57b.js => 03abeb31.5f9309f2.js} (94%) rename assets/js/{0b218a01.00c2d643.js => 0b218a01.de27cef5.js} (98%) rename assets/js/{104cbb75.c7fb3ef1.js => 104cbb75.c2ce6e10.js} (98%) rename assets/js/{19fd9079.ac45505f.js => 19fd9079.0d5010f9.js} (96%) rename assets/js/{1ed4142b.646b4f19.js => 1ed4142b.a44c3e96.js} (98%) rename assets/js/{1f61ef73.ed364500.js => 1f61ef73.51af529c.js} (97%) rename assets/js/{2486267b.f4424fc4.js => 2486267b.0ba0fb70.js} (96%) rename assets/js/{258a6413.25eadca6.js => 258a6413.15131eb9.js} (94%) rename assets/js/{2a33acc4.376963de.js => 2a33acc4.ed23e4e6.js} (97%) rename assets/js/{2f98ad87.be46cc71.js => 2f98ad87.c0493a32.js} (96%) rename assets/js/{3042343a.8ba035fd.js => 3042343a.6b9057ed.js} (98%) rename assets/js/{30d74566.bf95441d.js => 30d74566.f5a0ed76.js} (98%) rename assets/js/{32060389.1eb0ee8b.js => 32060389.cc2c1970.js} (98%) rename assets/js/{35586d92.f1a1915a.js => 35586d92.a74fcd5f.js} (96%) rename assets/js/{3e452c7e.0139d8d2.js => 3e452c7e.747c7b5b.js} (97%) rename assets/js/{53e18611.cbaa63c9.js => 53e18611.174f50c6.js} (96%) rename assets/js/{5d5620c4.7d436f77.js => 5d5620c4.aa5bafe0.js} (98%) rename assets/js/{6f3bb722.82eaa226.js => 6f3bb722.36477967.js} (99%) rename assets/js/{713bb917.dbd2243e.js => 713bb917.cf149bb6.js} (99%) rename assets/js/{7bd58895.825ec359.js => 7bd58895.bbd59ad7.js} (98%) rename assets/js/{82247a8b.a76eaf65.js => 82247a8b.de433149.js} (99%) rename assets/js/{8705a681.a24a496a.js => 8705a681.eedb41eb.js} (98%) rename assets/js/{935116ff.7148886a.js => 935116ff.dc866d9f.js} (98%) rename assets/js/{9eaa546a.5801dc53.js => 9eaa546a.45d375f7.js} (99%) rename assets/js/{a92e169d.c9dc0b54.js => a92e169d.82f135f1.js} (97%) rename assets/js/{a96ec439.53b19970.js => a96ec439.3b3c006e.js} (97%) rename assets/js/{b3cc73c6.473e1578.js => b3cc73c6.b180e5dd.js} (98%) rename assets/js/{b4a95747.e4ee3a79.js => b4a95747.8bdd8694.js} (95%) rename assets/js/{c5890d18.2ec84b3e.js => c5890d18.1f021986.js} (98%) rename assets/js/{c81fd975.0551bf12.js => c81fd975.02a85bfa.js} (99%) rename assets/js/{c94a68c1.6d6c394a.js => c94a68c1.1dcb0da4.js} (98%) rename assets/js/{d0e73d62.44497857.js => d0e73d62.2de45aa6.js} (96%) rename assets/js/{d665a578.f44b824d.js => d665a578.a0187057.js} (96%) rename assets/js/{d9b0bdb4.243a840b.js => d9b0bdb4.3425f4a7.js} (96%) rename assets/js/{df1cd967.a69943d3.js => df1cd967.28611b4c.js} (97%) rename assets/js/{e360e27f.e043c1c2.js => e360e27f.158cd50e.js} (97%) rename assets/js/{e3703649.0f308291.js => e3703649.deb238ea.js} (99%) rename assets/js/{f182954c.53a8635a.js => f182954c.67c31c13.js} (96%) rename assets/js/{f6c5328e.c07cba91.js => f6c5328e.a958af26.js} (97%) rename assets/js/{f905d0fe.e4e807ba.js => f905d0fe.2c295ea7.js} (93%) rename assets/js/{runtime~main.a7ad947a.js => runtime~main.c6cfc268.js} (82%) 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 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 +"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 ]\n\nARGUMENTS\n NAME name of hook (snake_case)\n\nFLAGS\n --event= [default: init] event to run hook on\n --force overwrite existing files\n\nDESCRIPTION\n add a hook to an existing CLI or plugin\n"})})]})}function m(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(s,{...e})}):s(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>a,x:()=>i});var t=o(6540);const r={},c=t.createContext(r);function a(e){const n=t.useContext(c);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(r):e.components||r:a(e.components),t.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"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:1711121897,formattedLastUpdatedAt:"Mar 22, 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 ]\n\nARGUMENTS\n NAME name of hook (snake_case)\n\nFLAGS\n --event= [default: init] event to run hook on\n --force overwrite existing files\n\nDESCRIPTION\n add a hook to an existing CLI or plugin\n"})})]})}function m(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(s,{...e})}):s(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>a,x:()=>i});var t=o(6540);const r={},c=t.createContext(r);function a(e){const n=t.useContext(c);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(r):e.components||r:a(e.components),t.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3042343a.8ba035fd.js b/assets/js/3042343a.6b9057ed.js similarity index 98% rename from assets/js/3042343a.8ba035fd.js rename to assets/js/3042343a.6b9057ed.js index 391301df..14929472 100644 --- a/assets/js/3042343a.8ba035fd.js +++ b/assets/js/3042343a.6b9057ed.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7777],{2443:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>i,toc:()=>f});var s=a(4848),t=a(8453);const l={title:"Command Flags"},o=void 0,i={id:"flags",title:"Command Flags",description:"Flag options are non-positional arguments passed to the command. Flags can either be option flags which take an argument, or boolean flags which do not. An option flag must have an argument.",source:"@site/../docs/flags.md",sourceDirName:".",slug:"/flags",permalink:"/docs/flags",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/flags.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Command Flags"},sidebar:"docs",previous:{title:"Command Arguments",permalink:"/docs/args"},next:{title:"Configuration",permalink:"/docs/config"}},r={},f=[{value:"Custom Flags",id:"custom-flags",level:2},{value:"Alternative Flag Inputs",id:"alternative-flag-inputs",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"Flag options are non-positional arguments passed to the command. Flags can either be option flags which take an argument, or boolean flags which do not. An option flag must have an argument."}),"\n",(0,s.jsx)(n.p,{children:"For example, if this command was run like this:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ mycli --force --file=./myfile\n"})}),"\n",(0,s.jsx)(n.p,{children:"It would be declared like this:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import {Command, Flags} from '@oclif/core'\n\nexport class MyCLI extends Command {\n static flags = {\n // can pass either --force or -f\n force: Flags.boolean({char: 'f'}),\n file: Flags.string(),\n }\n\n async run() {\n const {flags} = await this.parse(MyCLI)\n if (flags.force) console.log('--force is set')\n if (flags.file) console.log(`--file is: ${flags.file}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.em,{children:["oclif supports a wide range of ",(0,s.jsx)(n.a,{href:"#alternative-flag-inputs",children:"alternative flag inputs"}),"."]})}),"\n",(0,s.jsx)(n.p,{children:"Here are the options flags can have:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"static flags = {\n name: Flags.string({\n char: 'n', // shorter flag version\n summary: 'brief summary', // help summary for flag\n helpGroup: 'THE BEST FLAGS', // Put flag into THE BEST FLAGS group in help\n description: 'in-depth overview', // help description for flag\n hidden: false, // hide from help\n multiple: false, // allow setting this flag multiple times\n env: 'MY_NAME', // default to value of environment variable\n options: ['a', 'b'], // only allow the value to be from a discrete set\n parse: async input => 'output', // instead of the user input, return a different value\n default: 'world', // default value if flag not passed (can be an async function that returns a string or undefined)\n defaultHelp: 'a dynamic value' // dyanmic default value to show in help output (e.g. current working directory). Can be an async function that returns a string or undefined\n required: false, // make flag required\n aliases: ['username', 'u'], // aliases for the flag - can be short char or long flags\n deprecateAliases: false, // emit deprecation warning anytime a flag alias is provided\n dependsOn: ['extra-flag'], // this flag requires another flag\n exclusive: ['extra-flag'], // this flag cannot be specified alongside this other flag\n exactlyOne: ['extra-flag', 'another-flag'], // exactly one of these flags must be provided\n relationships: [ // define complex relationships between flags\n // Make this flag dependent on all of these flags\n {type: 'all', flags: ['flag-one', 'flag-two']}\n // Make this flag dependent on at least one of these flags\n {type: 'some', flags: ['flag-three', 'flag-four']}\n // Make this flag exclusive of all these flags\n {type: 'none', flags: ['flag-five', 'flag-six']}\n\n // Make this flag dependent on all of these flags\n {type: 'all', flags: [\n 'flag-one',\n 'flag-two',\n // Include flag-seven but only when flag-eight is equal to FooBar\n {name: 'flag-seven', when: async (flags) => flags['flag-eight'] === 'FooBar'}\n ]}\n ]\n }),\n\n // flag with no value (-f, --force)\n force: Flags.boolean({\n char: 'f', // short character for flag\n default: true, // default value if flag not passed (can be a function that returns a boolean)\n env: 'MY_NAME', // default value to the value of an environment variable\n // boolean flags may be reversed with `--no-` (in this case: `--no-force`).\n // The flag will be set to false if reversed. This functionality\n // is disabled by default, to enable it:\n // allowNo: true\n }),\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"custom-flags",children:"Custom Flags"}),"\n",(0,s.jsx)(n.p,{children:"For larger CLIs, it can be useful to declare a custom flag that can be shared amongst multiple commands. Here is an example of a custom flag:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"// src/flags.ts\nimport {Flags} from '@oclif/core'\n\nclass Team {\n public name: string;\n // etc...\n}\n\nfunction getTeam(): Promise {\n // imagine this reads a configuration file or something to find the team\n return new Team()\n}\n\nexport const team = Flags.custom({\n char: 't',\n description: 'team to use',\n default: () => getTeam(),\n})\n\n// src/commands/mycommand.ts\nimport {team} from '../flags'\nimport {Command} from '@oclif/core'\n\nexport class MyCLI extends Command {\n static flags = {\n team: team(),\n }\n\n async run() {\n const {flags} = await this.parse(MyCLI)\n if (flags.team) console.log(`--team is ${flags.team.name}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"In the Salesforce CLI we make heavy use of custom flags. For example,"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["A ",(0,s.jsx)(n.a,{href:"https://salesforcecli.github.io/sf-plugins-core/functions/flags_salesforceId.salesforceIdFlag.html",children:(0,s.jsx)(n.code,{children:"salesforceId"})})," flag that ensures the provided string is a valid Salesforce Id."]}),"\n",(0,s.jsxs)(n.li,{children:["A ",(0,s.jsx)(n.a,{href:"https://salesforcecli.github.io/sf-plugins-core/functions/flags_duration.durationFlag.html",children:(0,s.jsx)(n.code,{children:"duration"})})," flag that converts a provided integer into a ",(0,s.jsx)(n.code,{children:"Duration"})," instance that we use for working with time based values."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["These and more are located ",(0,s.jsx)(n.a,{href:"https://github.com/salesforcecli/sf-plugins-core/tree/main/src/flags",children:"here"})," if you want to see more examples. You can also read the ",(0,s.jsx)(n.a,{href:"https://salesforcecli.github.io/sf-plugins-core/",children:"API docs"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"alternative-flag-inputs",children:"Alternative Flag Inputs"}),"\n",(0,s.jsxs)(n.p,{children:["Here are some other ways the user can use input flags. This is assuming the command has flags like ",(0,s.jsx)(n.code,{children:"-f, --file=file"})," and ",(0,s.jsx)(n.code,{children:"-v, --verbose"})," (string and boolean flag):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ mycli --verbose\n$ mycli -v\n$ mycli --file=foo\n$ mycli --file foo\n$ mycli -f foo\n$ mycli -f=foo\n$ mycli -ffoo\n$ mycli -vffoo\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The last one seems a little odd at first glance, but it's relatively standard in unix and makes commands like ",(0,s.jsx)(n.code,{children:"tar -xvzfmytarball.tar.gz"})," possible."]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>o,x:()=>i});var s=a(6540);const t={},l=s.createContext(t);function o(e){const n=s.useContext(l);return s.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(t):e.components||t:o(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7777],{2443:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>i,toc:()=>f});var s=a(4848),t=a(8453);const l={title:"Command Flags"},o=void 0,i={id:"flags",title:"Command Flags",description:"Flag options are non-positional arguments passed to the command. Flags can either be option flags which take an argument, or boolean flags which do not. An option flag must have an argument.",source:"@site/../docs/flags.md",sourceDirName:".",slug:"/flags",permalink:"/docs/flags",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/flags.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Command Flags"},sidebar:"docs",previous:{title:"Command Arguments",permalink:"/docs/args"},next:{title:"Configuration",permalink:"/docs/config"}},r={},f=[{value:"Custom Flags",id:"custom-flags",level:2},{value:"Alternative Flag Inputs",id:"alternative-flag-inputs",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"Flag options are non-positional arguments passed to the command. Flags can either be option flags which take an argument, or boolean flags which do not. An option flag must have an argument."}),"\n",(0,s.jsx)(n.p,{children:"For example, if this command was run like this:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ mycli --force --file=./myfile\n"})}),"\n",(0,s.jsx)(n.p,{children:"It would be declared like this:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import {Command, Flags} from '@oclif/core'\n\nexport class MyCLI extends Command {\n static flags = {\n // can pass either --force or -f\n force: Flags.boolean({char: 'f'}),\n file: Flags.string(),\n }\n\n async run() {\n const {flags} = await this.parse(MyCLI)\n if (flags.force) console.log('--force is set')\n if (flags.file) console.log(`--file is: ${flags.file}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.em,{children:["oclif supports a wide range of ",(0,s.jsx)(n.a,{href:"#alternative-flag-inputs",children:"alternative flag inputs"}),"."]})}),"\n",(0,s.jsx)(n.p,{children:"Here are the options flags can have:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"static flags = {\n name: Flags.string({\n char: 'n', // shorter flag version\n summary: 'brief summary', // help summary for flag\n helpGroup: 'THE BEST FLAGS', // Put flag into THE BEST FLAGS group in help\n description: 'in-depth overview', // help description for flag\n hidden: false, // hide from help\n multiple: false, // allow setting this flag multiple times\n env: 'MY_NAME', // default to value of environment variable\n options: ['a', 'b'], // only allow the value to be from a discrete set\n parse: async input => 'output', // instead of the user input, return a different value\n default: 'world', // default value if flag not passed (can be an async function that returns a string or undefined)\n defaultHelp: 'a dynamic value' // dyanmic default value to show in help output (e.g. current working directory). Can be an async function that returns a string or undefined\n required: false, // make flag required\n aliases: ['username', 'u'], // aliases for the flag - can be short char or long flags\n deprecateAliases: false, // emit deprecation warning anytime a flag alias is provided\n dependsOn: ['extra-flag'], // this flag requires another flag\n exclusive: ['extra-flag'], // this flag cannot be specified alongside this other flag\n exactlyOne: ['extra-flag', 'another-flag'], // exactly one of these flags must be provided\n relationships: [ // define complex relationships between flags\n // Make this flag dependent on all of these flags\n {type: 'all', flags: ['flag-one', 'flag-two']}\n // Make this flag dependent on at least one of these flags\n {type: 'some', flags: ['flag-three', 'flag-four']}\n // Make this flag exclusive of all these flags\n {type: 'none', flags: ['flag-five', 'flag-six']}\n\n // Make this flag dependent on all of these flags\n {type: 'all', flags: [\n 'flag-one',\n 'flag-two',\n // Include flag-seven but only when flag-eight is equal to FooBar\n {name: 'flag-seven', when: async (flags) => flags['flag-eight'] === 'FooBar'}\n ]}\n ]\n }),\n\n // flag with no value (-f, --force)\n force: Flags.boolean({\n char: 'f', // short character for flag\n default: true, // default value if flag not passed (can be a function that returns a boolean)\n env: 'MY_NAME', // default value to the value of an environment variable\n // boolean flags may be reversed with `--no-` (in this case: `--no-force`).\n // The flag will be set to false if reversed. This functionality\n // is disabled by default, to enable it:\n // allowNo: true\n }),\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"custom-flags",children:"Custom Flags"}),"\n",(0,s.jsx)(n.p,{children:"For larger CLIs, it can be useful to declare a custom flag that can be shared amongst multiple commands. Here is an example of a custom flag:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"// src/flags.ts\nimport {Flags} from '@oclif/core'\n\nclass Team {\n public name: string;\n // etc...\n}\n\nfunction getTeam(): Promise {\n // imagine this reads a configuration file or something to find the team\n return new Team()\n}\n\nexport const team = Flags.custom({\n char: 't',\n description: 'team to use',\n default: () => getTeam(),\n})\n\n// src/commands/mycommand.ts\nimport {team} from '../flags'\nimport {Command} from '@oclif/core'\n\nexport class MyCLI extends Command {\n static flags = {\n team: team(),\n }\n\n async run() {\n const {flags} = await this.parse(MyCLI)\n if (flags.team) console.log(`--team is ${flags.team.name}`)\n }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"In the Salesforce CLI we make heavy use of custom flags. For example,"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["A ",(0,s.jsx)(n.a,{href:"https://salesforcecli.github.io/sf-plugins-core/functions/flags_salesforceId.salesforceIdFlag.html",children:(0,s.jsx)(n.code,{children:"salesforceId"})})," flag that ensures the provided string is a valid Salesforce Id."]}),"\n",(0,s.jsxs)(n.li,{children:["A ",(0,s.jsx)(n.a,{href:"https://salesforcecli.github.io/sf-plugins-core/functions/flags_duration.durationFlag.html",children:(0,s.jsx)(n.code,{children:"duration"})})," flag that converts a provided integer into a ",(0,s.jsx)(n.code,{children:"Duration"})," instance that we use for working with time based values."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["These and more are located ",(0,s.jsx)(n.a,{href:"https://github.com/salesforcecli/sf-plugins-core/tree/main/src/flags",children:"here"})," if you want to see more examples. You can also read the ",(0,s.jsx)(n.a,{href:"https://salesforcecli.github.io/sf-plugins-core/",children:"API docs"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"alternative-flag-inputs",children:"Alternative Flag Inputs"}),"\n",(0,s.jsxs)(n.p,{children:["Here are some other ways the user can use input flags. This is assuming the command has flags like ",(0,s.jsx)(n.code,{children:"-f, --file=file"})," and ",(0,s.jsx)(n.code,{children:"-v, --verbose"})," (string and boolean flag):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh-session",children:"$ mycli --verbose\n$ mycli -v\n$ mycli --file=foo\n$ mycli --file foo\n$ mycli -f foo\n$ mycli -f=foo\n$ mycli -ffoo\n$ mycli -vffoo\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The last one seems a little odd at first glance, but it's relatively standard in unix and makes commands like ",(0,s.jsx)(n.code,{children:"tar -xvzfmytarball.tar.gz"})," possible."]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>o,x:()=>i});var s=a(6540);const t={},l=s.createContext(t);function o(e){const n=s.useContext(l);return s.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(t):e.components||t:o(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/30d74566.bf95441d.js b/assets/js/30d74566.f5a0ed76.js similarity index 98% rename from assets/js/30d74566.bf95441d.js rename to assets/js/30d74566.f5a0ed76.js index 2693740e..47d8204f 100644 --- a/assets/js/30d74566.bf95441d.js +++ b/assets/js/30d74566.f5a0ed76.js @@ -1 +1 @@ -"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:1710860746,formattedLastUpdatedAt:"Mar 19, 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 +"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 Flags = Interfaces.InferredFlags\nexport type Args = Interfaces.InferredArgs\n\nexport abstract class BaseCommand extends Command {\n // add the --json flag\n static enableJsonFlag = true\n\n // define flags that can be inherited by any command that extends BaseCommand\n static baseFlags = {\n 'log-level': Flags.custom({\n summary: 'Specify level for logging.',\n options: Object.values(LogLevel),\n helpGroup: 'GLOBAL',\n })(),\n }\n\n protected flags!: Flags\n protected args!: Args\n\n public async init(): Promise {\n await super.init()\n const {args, flags} = await this.parse({\n flags: this.ctor.flags,\n baseFlags: (super.ctor as typeof BaseCommand).baseFlags,\n enableJsonFlag: this.ctor.enableJsonFlag,\n args: this.ctor.args,\n strict: this.ctor.strict,\n })\n this.flags = flags as Flags\n this.args = args as Args\n }\n\n protected async catch(err: Error & {exitCode?: number}): Promise {\n // add any custom logic to handle errors from the command\n // or simply return the parent class error handling\n return super.catch(err)\n }\n\n protected async finally(_: Error | undefined): Promise {\n // called after run and catch regardless of whether or not the command errored\n return super.finally(_)\n }\n}\n\n// src/commands/my-command.ts\n\nexport default class MyCommand extends BaseCommand {\n static summary = 'child class that extends BaseCommand'\n\n static examples = [\n '<%= config.bin %> <%= command.id %>',\n '<%= config.bin %> <%= command.id %> --json',\n '<%= config.bin %> <%= command.id %> --log-level debug',\n ]\n\n static flags = {\n name: Flags.string({\n char: 'n',\n summary: 'Name to print.',\n required: true,\n }),\n }\n\n public async run(): Promise> {\n for (const [flag, value] of Object.entries(this.flags)) {\n this.log(`${flag}: ${value}`)\n }\n\n return this.flags\n }\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["For a more complex example, ",(0,a.jsx)(n.a,{href:"https://github.com/salesforcecli/sf-plugins-core/blob/main/src/sfCommand.ts",children:"here's"})," how we do this for the Salesforce CLI."]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(m,{...e})}):m(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>c});var a=s(6540);const t={},o=a.createContext(t);function r(e){const n=a.useContext(o);return a.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(t):e.components||t:r(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"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:1711121897,formattedLastUpdatedAt:"Mar 22, 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 Flags = Interfaces.InferredFlags\nexport type Args = Interfaces.InferredArgs\n\nexport abstract class BaseCommand extends Command {\n // add the --json flag\n static enableJsonFlag = true\n\n // define flags that can be inherited by any command that extends BaseCommand\n static baseFlags = {\n 'log-level': Flags.custom({\n summary: 'Specify level for logging.',\n options: Object.values(LogLevel),\n helpGroup: 'GLOBAL',\n })(),\n }\n\n protected flags!: Flags\n protected args!: Args\n\n public async init(): Promise {\n await super.init()\n const {args, flags} = await this.parse({\n flags: this.ctor.flags,\n baseFlags: (super.ctor as typeof BaseCommand).baseFlags,\n enableJsonFlag: this.ctor.enableJsonFlag,\n args: this.ctor.args,\n strict: this.ctor.strict,\n })\n this.flags = flags as Flags\n this.args = args as Args\n }\n\n protected async catch(err: Error & {exitCode?: number}): Promise {\n // add any custom logic to handle errors from the command\n // or simply return the parent class error handling\n return super.catch(err)\n }\n\n protected async finally(_: Error | undefined): Promise {\n // called after run and catch regardless of whether or not the command errored\n return super.finally(_)\n }\n}\n\n// src/commands/my-command.ts\n\nexport default class MyCommand extends BaseCommand {\n static summary = 'child class that extends BaseCommand'\n\n static examples = [\n '<%= config.bin %> <%= command.id %>',\n '<%= config.bin %> <%= command.id %> --json',\n '<%= config.bin %> <%= command.id %> --log-level debug',\n ]\n\n static flags = {\n name: Flags.string({\n char: 'n',\n summary: 'Name to print.',\n required: true,\n }),\n }\n\n public async run(): Promise> {\n for (const [flag, value] of Object.entries(this.flags)) {\n this.log(`${flag}: ${value}`)\n }\n\n return this.flags\n }\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["For a more complex example, ",(0,a.jsx)(n.a,{href:"https://github.com/salesforcecli/sf-plugins-core/blob/main/src/sfCommand.ts",children:"here's"})," how we do this for the Salesforce CLI."]})]})}function d(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(m,{...e})}):m(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>c});var a=s(6540);const t={},o=a.createContext(t);function r(e){const n=a.useContext(o);return a.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(t):e.components||t:r(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/53e18611.cbaa63c9.js b/assets/js/53e18611.174f50c6.js similarity index 96% rename from assets/js/53e18611.cbaa63c9.js rename to assets/js/53e18611.174f50c6.js index 99281c36..f6783060 100644 --- a/assets/js/53e18611.cbaa63c9.js +++ b/assets/js/53e18611.174f50c6.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[1777],{1098:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var o=n(4848),i=n(8453);const r={title:"Introduction"},s=void 0,a={id:"introduction",title:"Introduction",description:"oclif is a framework for building CLIs in Node. It can be used like a simple flag parser but is capable of much more. It's designed to be extensible so that you can easily add plugins such as the update warning plugin or build your own for users to install at runtime.",source:"@site/../docs/introduction.md",sourceDirName:".",slug:"/introduction",permalink:"/docs/introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/introduction.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Introduction"},sidebar:"docs",next:{title:"Features",permalink:"/docs/features"}},c={},l=[{value:"Requirements",id:"requirements",level:2},{value:"Quickstart",id:"quickstart",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["oclif is a framework for building CLIs in Node. It can be used like a ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/core#usage",children:"simple flag parser"})," but is capable of much more. It's designed to be extensible so that you can easily add plugins such as the ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/plugin-warn-if-update-available",children:"update warning plugin"})," or build your own for users to install at runtime."]}),"\n",(0,o.jsxs)(t.p,{children:["The oclif generator creates a CLI project in ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/hello-world",children:"TypeScript"})," to get you started quickly. It requires very few runtime dependencies and has extremely minimal overhead."]}),"\n",(0,o.jsx)(t.p,{children:"Everything is customizable in oclif. Even the flag parser and help generation is optional and can be replaced. It's a platform to build upon that provides smart defaults without locking you in to any specific tools or behavior."}),"\n",(0,o.jsx)(t.h2,{id:"requirements",children:"Requirements"}),"\n",(0,o.jsxs)(t.p,{children:["Only ",(0,o.jsx)(t.a,{href:"https://nodejs.org/en/about/previous-releases",children:"LTS Node versions"})," are supported. You can add the ",(0,o.jsx)(t.a,{href:"https://www.npmjs.com/package/node",children:"node"})," package to your CLI to ensure users are on a specific Node version."]}),"\n",(0,o.jsx)(t.h2,{id:"quickstart",children:"Quickstart"}),"\n",(0,o.jsx)(t.p,{children:"Creating a CLI:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-sh-session",children:"$ npx oclif generate mynewcli\n? npm package name (mynewcli): mynewcli\n$ cd mynewcli\n$ ./bin/dev.js hello world\nhello world! (./src/commands/hello/world.ts)\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.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:()=>s,x:()=>a});var o=n(6540);const i={},r=o.createContext(i);function s(e){const t=o.useContext(r);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(i):e.components||i:s(e.components),o.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[1777],{1098:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var o=n(4848),i=n(8453);const r={title:"Introduction"},s=void 0,a={id:"introduction",title:"Introduction",description:"oclif is a framework for building CLIs in Node. It can be used like a simple flag parser but is capable of much more. It's designed to be extensible so that you can easily add plugins such as the update warning plugin or build your own for users to install at runtime.",source:"@site/../docs/introduction.md",sourceDirName:".",slug:"/introduction",permalink:"/docs/introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/introduction.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Introduction"},sidebar:"docs",next:{title:"Features",permalink:"/docs/features"}},c={},l=[{value:"Requirements",id:"requirements",level:2},{value:"Quickstart",id:"quickstart",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["oclif is a framework for building CLIs in Node. It can be used like a ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/core#usage",children:"simple flag parser"})," but is capable of much more. It's designed to be extensible so that you can easily add plugins such as the ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/plugin-warn-if-update-available",children:"update warning plugin"})," or build your own for users to install at runtime."]}),"\n",(0,o.jsxs)(t.p,{children:["The oclif generator creates a CLI project in ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/hello-world",children:"TypeScript"})," to get you started quickly. It requires very few runtime dependencies and has extremely minimal overhead."]}),"\n",(0,o.jsx)(t.p,{children:"Everything is customizable in oclif. Even the flag parser and help generation is optional and can be replaced. It's a platform to build upon that provides smart defaults without locking you in to any specific tools or behavior."}),"\n",(0,o.jsx)(t.h2,{id:"requirements",children:"Requirements"}),"\n",(0,o.jsxs)(t.p,{children:["Only ",(0,o.jsx)(t.a,{href:"https://nodejs.org/en/about/previous-releases",children:"LTS Node versions"})," are supported. You can add the ",(0,o.jsx)(t.a,{href:"https://www.npmjs.com/package/node",children:"node"})," package to your CLI to ensure users are on a specific Node version."]}),"\n",(0,o.jsx)(t.h2,{id:"quickstart",children:"Quickstart"}),"\n",(0,o.jsx)(t.p,{children:"Creating a CLI:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-sh-session",children:"$ npx oclif generate mynewcli\n? npm package name (mynewcli): mynewcli\n$ cd mynewcli\n$ ./bin/dev.js hello world\nhello world! (./src/commands/hello/world.ts)\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.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:()=>s,x:()=>a});var o=n(6540);const i={},r=o.createContext(i);function s(e){const t=o.useContext(r);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(i):e.components||i:s(e.components),o.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5d5620c4.7d436f77.js b/assets/js/5d5620c4.aa5bafe0.js similarity index 98% rename from assets/js/5d5620c4.7d436f77.js rename to assets/js/5d5620c4.aa5bafe0.js index a3191793..96c13625 100644 --- a/assets/js/5d5620c4.7d436f77.js +++ b/assets/js/5d5620c4.aa5bafe0.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8990],{5219:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>r,toc:()=>c});var s=i(4848),t=i(8453);const l={title:"ESM"},o=void 0,r={id:"esm",title:"ESM",description:"Version 3.0.0 of @oclif/core officially supports ESM plugin development and CJS/ESM interoperability, meaning that you can have a root plugin written with CJS and your bundled plugins written in ESM or vice versa.",source:"@site/../docs/esm.md",sourceDirName:".",slug:"/esm",permalink:"/docs/esm",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/esm.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"ESM"},sidebar:"docs",previous:{title:"Single Command CLI",permalink:"/docs/single_command_cli"},next:{title:"Themes",permalink:"/docs/themes"}},d={},c=[{value:"Interoperability Overview",id:"interoperability-overview",level:2},{value:"ESM Root plugin",id:"esm-root-plugin",level:3},{value:"CJS Root plugin",id:"cjs-root-plugin",level:3},{value:"Creating an ESM plugin",id:"creating-an-esm-plugin",level:2},{value:"Migrating a CJS plugin to ESM",id:"migrating-a-cjs-plugin-to-esm",level:2},{value:"Update bin scripts",id:"update-bin-scripts",level:3},{value:"bin/dev \u2192 bin/dev.js",id:"bindev--bindevjs",level:4},{value:"bin/run \u2192 bin/run.js",id:"binrun--binrunjs",level:4},{value:"Update tsconfig.json",id:"update-tsconfigjson",level:3},{value:"Update package.json to "module" type",id:"update-packagejson-to-module-type",level:3},{value:"Update references to bin scripts",id:"update-references-to-bin-scripts",level:3},{value:"Update mocharc settings",id:"update-mocharc-settings",level:3}];function a(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Version 3.0.0 of ",(0,s.jsx)(n.code,{children:"@oclif/core"})," officially supports ESM plugin development and CJS/ESM interoperability, meaning that you can have a root plugin written with CJS and your bundled plugins written in ESM or vice versa."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#interoperability-overview",children:"Interoperability Overview"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#esm-root-plugin",children:"ESM Root plugin"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cjs-root-plugin",children:"CJS Root plugin"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#creating-an-esm-plugin",children:"Creating an ESM plugin"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#migrating-a-cjs-plugin-to-esm",children:"Migrating a CJS plugin to ESM"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#update-bin-scripts",children:"Update bin scripts"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#bindev--bindevjs",children:"bin/dev \u2192 bin/dev.js"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#binrun--binrunjs",children:"bin/run \u2192 bin/run.js"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-tsconfigjson",children:"Update tsconfig.json"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-packagejson-to-module-type",children:'Update package.json to "module" type'})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-references-to-bin-scripts",children:"Update references to bin scripts"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-mocharc-settings",children:"Update mocharc settings"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"interoperability-overview",children:"Interoperability Overview"}),"\n",(0,s.jsx)(n.p,{children:"Here's a high level overview of ESM/CJS interoperability:"}),"\n",(0,s.jsx)(n.h3,{id:"esm-root-plugin",children:"ESM Root plugin"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install ESM plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Link CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u26a0\ufe0f Link ESM plugins"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Auto-compilation will ",(0,s.jsx)(n.strong,{children:"not"})," work with linked ESM plugins. Instead, oclif will use the plugin's compiled source - this means that you must compile the plugin yourself before executing any of the commands. We plan to support this again once the node ecosystem offers more comprehensive native support for ESM."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"cjs-root-plugin",children:"CJS Root plugin"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install ESM plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Link CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u26a0\ufe0f Link ESM plugins"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Auto-compilation will ",(0,s.jsx)(n.strong,{children:"not"})," work with linked ESM plugins. Instead, oclif will use the plugin's compiled source - this means that you must compile the plugin yourself before executing any of the commands. We plan to support this again once the node ecosystem offers more comprehensive native support for ESM."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"creating-an-esm-plugin",children:"Creating an ESM plugin"}),"\n",(0,s.jsxs)(n.p,{children:["To generate a new ESM plugin from the ",(0,s.jsx)(n.a,{href:"https://github.com/oclif/hello-world-esm",children:"hello-world-esm template"})," run the ",(0,s.jsx)(n.code,{children:"oclif generate"})," command and select ",(0,s.jsx)(n.code,{children:"ESM"})," when it prompts you to select a module type:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ npx oclif generate my-esm-plugin\n? Select a module type\n CommonJS\n\u276f ESM\n"})}),"\n",(0,s.jsx)(n.h2,{id:"migrating-a-cjs-plugin-to-esm",children:"Migrating a CJS plugin to ESM"}),"\n",(0,s.jsx)(n.h3,{id:"update-bin-scripts",children:"Update bin scripts"}),"\n",(0,s.jsxs)(n.p,{children:["First you will need to update the bin scripts under the ",(0,s.jsx)(n.code,{children:"bin"})," directory."]}),"\n",(0,s.jsx)(n.h4,{id:"bindev--bindevjs",children:"bin/dev \u2192 bin/dev.js"}),"\n",(0,s.jsxs)(n.p,{children:["Rename ",(0,s.jsx)(n.code,{children:"bin/dev"})," to ",(0,s.jsx)(n.code,{children:"bin/dev.js"})," and replace the existing code with the following:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning\n\nimport {execute} from '@oclif/core'\n\nawait execute({development: true, dir: import.meta.url})\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This leverages oclif's ",(0,s.jsx)(n.code,{children:"execute"})," function which handles all the development setup for you. You no longer need set the ",(0,s.jsx)(n.code,{children:"NODE_ENV"})," env var or register the project with ",(0,s.jsx)(n.code,{children:"ts-node"}),". You can still adjust oclif ",(0,s.jsx)(n.code,{children:"settings"})," before executing the CLI. For example,"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning\n\nimport {execute, settings} from '@oclif/core'\n\nsettings.performanceEnabled = true\n\nawait execute({development: true, dir: import.meta.url})\n"})}),"\n",(0,s.jsx)(n.h4,{id:"binrun--binrunjs",children:"bin/run \u2192 bin/run.js"}),"\n",(0,s.jsxs)(n.p,{children:["Rename ",(0,s.jsx)(n.code,{children:"bin/run"})," to ",(0,s.jsx)(n.code,{children:"bin/run.js"})," and replace the existing code with the following:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"#!/usr/bin/env node\n\nimport {execute} from '@oclif/core'\n\nawait execute({dir: import.meta.url})\n"})}),"\n",(0,s.jsx)(n.h3,{id:"update-tsconfigjson",children:"Update tsconfig.json"}),"\n",(0,s.jsxs)(n.p,{children:["After updating the bin scripts you now need to update the ",(0,s.jsx)(n.code,{children:"tsconfig.json"})," to include the following options:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "compilerOptions": {\n "module": "ES2020",\n "moduleResolution": "node16",\n },\n "ts-node": {\n "esm": true\n }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"update-packagejson-to-module-type",children:'Update package.json to "module" type'}),"\n",(0,s.jsxs)(n.p,{children:["Add ",(0,s.jsx)(n.code,{children:'"type": "module"'})," to your package.json so that your files will be loaded as ESM modules"]}),"\n",(0,s.jsx)(n.h3,{id:"update-references-to-bin-scripts",children:"Update references to bin scripts"}),"\n",(0,s.jsxs)(n.p,{children:["You will need to update the references to your bin scripts to the bin scripts with the ",(0,s.jsx)(n.code,{children:".js"})," extension. In the ",(0,s.jsx)(n.code,{children:"package.json"})," you will need to update the ",(0,s.jsx)(n.code,{children:"bin"})," like so:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:' "bin": {\n "my-cli": "./bin/run"\n },\n'})}),"\n",(0,s.jsx)(n.p,{children:"to"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:' "bin": {\n "my-cli": "./bin/run.js"\n },\n'})}),"\n",(0,s.jsxs)(n.p,{children:["You may have references to the bin scripts in your ",(0,s.jsx)(n.code,{children:".vscode/launch.json"})," or in the ",(0,s.jsx)(n.code,{children:"scripts"})," of your ",(0,s.jsx)(n.code,{children:"package.json"}),". You'll need to update these as well."]}),"\n",(0,s.jsx)(n.h3,{id:"update-mocharc-settings",children:"Update mocharc settings"}),"\n",(0,s.jsx)(n.p,{children:"In order for your mocha tests to run, you'll need to make a couple of changes:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Add the following to the ",(0,s.jsx)(n.code,{children:".mocharc.json"})]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "node-option": [\n "loader=ts-node/esm"\n ]\n}\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"2",children:["\n",(0,s.jsxs)(n.li,{children:["Update ",(0,s.jsx)(n.code,{children:"test/helpers/init.js"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["If your plugin was generated ",(0,s.jsx)(n.code,{children:"oclif generate"})," then you likely have a ",(0,s.jsx)(n.code,{children:"test/helpers/init.js"})," file that needs to be updated. You can either update the file extension to ",(0,s.jsx)(n.code,{children:".cjs"})," or update the ",(0,s.jsx)(n.code,{children:"require"})," at the top of the file to an ",(0,s.jsx)(n.code,{children:"import"}),","]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import path from 'node:path'\n"})}),"\n",(0,s.jsx)(n.p,{children:"Alternatively, you can safely delete this file since it's no longer necessary."})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>r});var s=i(6540);const t={},l=s.createContext(t);function o(e){const n=s.useContext(l);return s.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:o(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8990],{5219:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>r,toc:()=>c});var s=i(4848),t=i(8453);const l={title:"ESM"},o=void 0,r={id:"esm",title:"ESM",description:"Version 3.0.0 of @oclif/core officially supports ESM plugin development and CJS/ESM interoperability, meaning that you can have a root plugin written with CJS and your bundled plugins written in ESM or vice versa.",source:"@site/../docs/esm.md",sourceDirName:".",slug:"/esm",permalink:"/docs/esm",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/esm.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"ESM"},sidebar:"docs",previous:{title:"Single Command CLI",permalink:"/docs/single_command_cli"},next:{title:"Themes",permalink:"/docs/themes"}},d={},c=[{value:"Interoperability Overview",id:"interoperability-overview",level:2},{value:"ESM Root plugin",id:"esm-root-plugin",level:3},{value:"CJS Root plugin",id:"cjs-root-plugin",level:3},{value:"Creating an ESM plugin",id:"creating-an-esm-plugin",level:2},{value:"Migrating a CJS plugin to ESM",id:"migrating-a-cjs-plugin-to-esm",level:2},{value:"Update bin scripts",id:"update-bin-scripts",level:3},{value:"bin/dev \u2192 bin/dev.js",id:"bindev--bindevjs",level:4},{value:"bin/run \u2192 bin/run.js",id:"binrun--binrunjs",level:4},{value:"Update tsconfig.json",id:"update-tsconfigjson",level:3},{value:"Update package.json to "module" type",id:"update-packagejson-to-module-type",level:3},{value:"Update references to bin scripts",id:"update-references-to-bin-scripts",level:3},{value:"Update mocharc settings",id:"update-mocharc-settings",level:3}];function a(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["Version 3.0.0 of ",(0,s.jsx)(n.code,{children:"@oclif/core"})," officially supports ESM plugin development and CJS/ESM interoperability, meaning that you can have a root plugin written with CJS and your bundled plugins written in ESM or vice versa."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#interoperability-overview",children:"Interoperability Overview"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#esm-root-plugin",children:"ESM Root plugin"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#cjs-root-plugin",children:"CJS Root plugin"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#creating-an-esm-plugin",children:"Creating an ESM plugin"})}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#migrating-a-cjs-plugin-to-esm",children:"Migrating a CJS plugin to ESM"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.a,{href:"#update-bin-scripts",children:"Update bin scripts"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#bindev--bindevjs",children:"bin/dev \u2192 bin/dev.js"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#binrun--binrunjs",children:"bin/run \u2192 bin/run.js"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-tsconfigjson",children:"Update tsconfig.json"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-packagejson-to-module-type",children:'Update package.json to "module" type'})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-references-to-bin-scripts",children:"Update references to bin scripts"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"#update-mocharc-settings",children:"Update mocharc settings"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"interoperability-overview",children:"Interoperability Overview"}),"\n",(0,s.jsx)(n.p,{children:"Here's a high level overview of ESM/CJS interoperability:"}),"\n",(0,s.jsx)(n.h3,{id:"esm-root-plugin",children:"ESM Root plugin"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install ESM plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Link CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u26a0\ufe0f Link ESM plugins"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Auto-compilation will ",(0,s.jsx)(n.strong,{children:"not"})," work with linked ESM plugins. Instead, oclif will use the plugin's compiled source - this means that you must compile the plugin yourself before executing any of the commands. We plan to support this again once the node ecosystem offers more comprehensive native support for ESM."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"cjs-root-plugin",children:"CJS Root plugin"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Install ESM plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u2705 Link CJS plugins"}),"\n",(0,s.jsx)(n.p,{children:"\u26a0\ufe0f Link ESM plugins"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Auto-compilation will ",(0,s.jsx)(n.strong,{children:"not"})," work with linked ESM plugins. Instead, oclif will use the plugin's compiled source - this means that you must compile the plugin yourself before executing any of the commands. We plan to support this again once the node ecosystem offers more comprehensive native support for ESM."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"creating-an-esm-plugin",children:"Creating an ESM plugin"}),"\n",(0,s.jsxs)(n.p,{children:["To generate a new ESM plugin from the ",(0,s.jsx)(n.a,{href:"https://github.com/oclif/hello-world-esm",children:"hello-world-esm template"})," run the ",(0,s.jsx)(n.code,{children:"oclif generate"})," command and select ",(0,s.jsx)(n.code,{children:"ESM"})," when it prompts you to select a module type:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"$ npx oclif generate my-esm-plugin\n? Select a module type\n CommonJS\n\u276f ESM\n"})}),"\n",(0,s.jsx)(n.h2,{id:"migrating-a-cjs-plugin-to-esm",children:"Migrating a CJS plugin to ESM"}),"\n",(0,s.jsx)(n.h3,{id:"update-bin-scripts",children:"Update bin scripts"}),"\n",(0,s.jsxs)(n.p,{children:["First you will need to update the bin scripts under the ",(0,s.jsx)(n.code,{children:"bin"})," directory."]}),"\n",(0,s.jsx)(n.h4,{id:"bindev--bindevjs",children:"bin/dev \u2192 bin/dev.js"}),"\n",(0,s.jsxs)(n.p,{children:["Rename ",(0,s.jsx)(n.code,{children:"bin/dev"})," to ",(0,s.jsx)(n.code,{children:"bin/dev.js"})," and replace the existing code with the following:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning\n\nimport {execute} from '@oclif/core'\n\nawait execute({development: true, dir: import.meta.url})\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This leverages oclif's ",(0,s.jsx)(n.code,{children:"execute"})," function which handles all the development setup for you. You no longer need set the ",(0,s.jsx)(n.code,{children:"NODE_ENV"})," env var or register the project with ",(0,s.jsx)(n.code,{children:"ts-node"}),". You can still adjust oclif ",(0,s.jsx)(n.code,{children:"settings"})," before executing the CLI. For example,"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"#!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning\n\nimport {execute, settings} from '@oclif/core'\n\nsettings.performanceEnabled = true\n\nawait execute({development: true, dir: import.meta.url})\n"})}),"\n",(0,s.jsx)(n.h4,{id:"binrun--binrunjs",children:"bin/run \u2192 bin/run.js"}),"\n",(0,s.jsxs)(n.p,{children:["Rename ",(0,s.jsx)(n.code,{children:"bin/run"})," to ",(0,s.jsx)(n.code,{children:"bin/run.js"})," and replace the existing code with the following:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"#!/usr/bin/env node\n\nimport {execute} from '@oclif/core'\n\nawait execute({dir: import.meta.url})\n"})}),"\n",(0,s.jsx)(n.h3,{id:"update-tsconfigjson",children:"Update tsconfig.json"}),"\n",(0,s.jsxs)(n.p,{children:["After updating the bin scripts you now need to update the ",(0,s.jsx)(n.code,{children:"tsconfig.json"})," to include the following options:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "compilerOptions": {\n "module": "ES2020",\n "moduleResolution": "node16",\n },\n "ts-node": {\n "esm": true\n }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"update-packagejson-to-module-type",children:'Update package.json to "module" type'}),"\n",(0,s.jsxs)(n.p,{children:["Add ",(0,s.jsx)(n.code,{children:'"type": "module"'})," to your package.json so that your files will be loaded as ESM modules"]}),"\n",(0,s.jsx)(n.h3,{id:"update-references-to-bin-scripts",children:"Update references to bin scripts"}),"\n",(0,s.jsxs)(n.p,{children:["You will need to update the references to your bin scripts to the bin scripts with the ",(0,s.jsx)(n.code,{children:".js"})," extension. In the ",(0,s.jsx)(n.code,{children:"package.json"})," you will need to update the ",(0,s.jsx)(n.code,{children:"bin"})," like so:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:' "bin": {\n "my-cli": "./bin/run"\n },\n'})}),"\n",(0,s.jsx)(n.p,{children:"to"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:' "bin": {\n "my-cli": "./bin/run.js"\n },\n'})}),"\n",(0,s.jsxs)(n.p,{children:["You may have references to the bin scripts in your ",(0,s.jsx)(n.code,{children:".vscode/launch.json"})," or in the ",(0,s.jsx)(n.code,{children:"scripts"})," of your ",(0,s.jsx)(n.code,{children:"package.json"}),". You'll need to update these as well."]}),"\n",(0,s.jsx)(n.h3,{id:"update-mocharc-settings",children:"Update mocharc settings"}),"\n",(0,s.jsx)(n.p,{children:"In order for your mocha tests to run, you'll need to make a couple of changes:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Add the following to the ",(0,s.jsx)(n.code,{children:".mocharc.json"})]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "node-option": [\n "loader=ts-node/esm"\n ]\n}\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"2",children:["\n",(0,s.jsxs)(n.li,{children:["Update ",(0,s.jsx)(n.code,{children:"test/helpers/init.js"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["If your plugin was generated ",(0,s.jsx)(n.code,{children:"oclif generate"})," then you likely have a ",(0,s.jsx)(n.code,{children:"test/helpers/init.js"})," file that needs to be updated. You can either update the file extension to ",(0,s.jsx)(n.code,{children:".cjs"})," or update the ",(0,s.jsx)(n.code,{children:"require"})," at the top of the file to an ",(0,s.jsx)(n.code,{children:"import"}),","]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-js",children:"import path from 'node:path'\n"})}),"\n",(0,s.jsx)(n.p,{children:"Alternatively, you can safely delete this file since it's no longer necessary."})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>r});var s=i(6540);const t={},l=s.createContext(t);function o(e){const n=s.useContext(l);return s.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:o(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6f3bb722.82eaa226.js b/assets/js/6f3bb722.36477967.js similarity index 99% rename from assets/js/6f3bb722.82eaa226.js rename to assets/js/6f3bb722.36477967.js index a6cc72cc..93ed1c9c 100644 --- a/assets/js/6f3bb722.82eaa226.js +++ b/assets/js/6f3bb722.36477967.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2961],{8976:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>a});var r=s(4848),o=s(8453);const t={title:"Commands"},i=void 0,d={id:"commands",title:"Commands",description:"A basic command looks like the following in TypeScript:",source:"@site/../docs/commands.md",sourceDirName:".",slug:"/commands",permalink:"/docs/commands",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/commands.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Commands"},sidebar:"docs",previous:{title:"Command Discovery Strategies",permalink:"/docs/command_discovery_strategies"},next:{title:"Command Arguments",permalink:"/docs/args"}},c={},a=[{value:"Avoiding Timeouts",id:"avoiding-timeouts",level:3},{value:"Other Command Options",id:"other-command-options",level:3},{value:"Command Methods",id:"command-methods",level:2},{value:"this.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(): Promise {\n console.log('running my command')\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The only part that is required is the run function. Accept user input with ",(0,r.jsx)(n.a,{href:"/docs/args",children:"arguments"})," and ",(0,r.jsx)(n.a,{href:"/docs/flags",children:"flags"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"In JavaScript:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"const {Command} = require('@oclif/core')\n\nclass MyCommand extends Command {\n async run() {\n console.log('running my command')\n }\n}\n\nMyCommand.description = 'description of this example command'\n\nmodule.exports = MyCommand\n"})}),"\n",(0,r.jsx)(n.p,{children:"Note that the following examples will be in TypeScript. As JavaScript does not yet have static class properties, you will have to add them to the class after it is declared like we did with the description above."}),"\n",(0,r.jsx)(n.h3,{id:"avoiding-timeouts",children:"Avoiding Timeouts"}),"\n",(0,r.jsxs)(n.p,{children:["In order to avoid command executions running indefinitely, oclif will terminate the node process 10 seconds after ",(0,r.jsx)(n.code,{children:"Command.run"})," resolves. This means that all command logic inside the ",(0,r.jsx)(n.code,{children:"run"})," method should either run synchronously or should return a ",(0,r.jsx)(n.code,{children:"Promise"}),". This will allow the entire command to run before the 10 second timeout starts."]}),"\n",(0,r.jsxs)(n.p,{children:["In other words, ",(0,r.jsxs)(n.strong,{children:["if you execute a promise in ",(0,r.jsx)(n.code,{children:"Command.run"})," without a awaiting it, then the command will likely timeout before it's completed."]})]}),"\n",(0,r.jsx)(n.h3,{id:"other-command-options",children:"Other Command Options"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/command.ts",children:"See the base class to get an idea of what methods can be called on a command"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"import {Command, Flags} from '@oclif/core'\n\nexport class MyCommand extends Command {\n static summary = 'A brief overview of your command.'\n static description = `\nAn in-depth description of the command.\nIt can be multiline.\n`\n\n // hide the command from help\n static hidden = false\n\n // custom usage string for help\n // this overrides the default usage\n static usage = 'mycommand --myflag'\n\n // examples to add to help\n // <%= config.bin %> resolves to the executable name\n // <%= command.id %> resolves to the command name\n static examples = [\n // Examples can be simple strings\n '<%= config.bin %> <%= command.id %> --help',\n // Or objects that provide a description of the example command\n {\n description: 'Force the command to execute',\n command: '<%= config.bin %> <%= command.id %> --force',\n }\n ]\n\n // this makes the parser not fail when it receives invalid arguments\n // defaults to true\n // set it to false if you need to accept a variable number of arguments\n static strict = false\n\n // define aliases that can execute this command.\n static aliases = ['alternate:name:for:this:command']\n\n // Set to true if you want to add the --json flag to your command.\n // oclif will automatically suppress logs (if you use this.log, this.warn, or this.error) and\n // display the JSON returned by the command's run method.\n static enableJsonFlag = true\n\n async run() {\n // show a warning\n this.warn('uh oh!')\n // exit with an error message\n this.error('uh oh!!!')\n // exit with status code\n this.exit(1)\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"command-methods",children:"Command Methods"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"#command-methods",children:"Command Methods"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thislogmessage-string",children:(0,r.jsx)(n.code,{children:"this.log(message: string)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thiswarnmessage-string--error",children:(0,r.jsx)(n.code,{children:"this.warn(message: string | Error)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thiserrormessage-string--error-options-code-string-exit-number-ref-string-suggestions-string",children:(0,r.jsx)(n.code,{children:"this.error(message: string | Error, options?: {code?: string, exit?: number, ref?: string; suggestions?: string[];})"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thisexitcode-number--0",children:(0,r.jsx)(n.code,{children:"this.exit(code: number = 0)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thislogtostderrmessage-string",children:(0,r.jsx)(n.code,{children:"this.logToStderr(message: string)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thisjsonenabled",children:(0,r.jsx)(n.code,{children:"this.jsonEnabled()"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thistosuccessjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toSuccessJson(result: unknown)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thistoerrorjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toErrorJson(result: unknown)"})})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The following assumes you are in the ",(0,r.jsx)(n.code,{children:"run()"})," method of an oclif ",(0,r.jsx)(n.a,{href:"/docs/commands",children:"command"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thislogmessage-string",children:(0,r.jsx)(n.code,{children:"this.log(message: string)"})}),"\n",(0,r.jsxs)(n.p,{children:["Output message to stdout (non-blocking). ",(0,r.jsx)(n.code,{children:"console.log()"})," works fine too, but that is a blocking call and won't be automatically suppressed when the ",(0,r.jsx)(n.code,{children:"--json"})," flag is present. This uses ",(0,r.jsx)(n.a,{href:"https://nodejs.org/api/util.html#util_util_format_format_args",children:"util.format()"})," which behaves the same as ",(0,r.jsx)(n.code,{children:"console.log()"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.log('hello, world!')\n"})}),"\n",(0,r.jsx)(n.h3,{id:"thiswarnmessage-string--error",children:(0,r.jsx)(n.code,{children:"this.warn(message: string | Error)"})}),"\n",(0,r.jsx)(n.p,{children:"Display an error or message as a warning"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.warn('uh oh!')\nthis.warn(new Error('uh oh!'))\n"})}),"\n",(0,r.jsx)(n.h3,{id:"thiserrormessage-string--error-options-code-string-exit-number-ref-string-suggestions-string",children:(0,r.jsx)(n.code,{children:"this.error(message: string | Error, options?: {code?: string, exit?: number, ref?: string; suggestions?: string[];})"})}),"\n",(0,r.jsx)(n.p,{children:"Display error and exit. Also add a code to error object or exit status."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.error('uh oh!', {exit: 2})\nthis.error(new Error('uh oh!'))\n"})}),"\n",(0,r.jsx)(n.p,{children:"The options object has the following options:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"exit"})," \u2014 exit code to use"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"code"})," \u2014 a unique error code for the type of error"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"suggestions"})," \u2014 an array of suggestions for a user to try next that may be useful or provide additional context"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ref"})," \u2014 a url to documentation related to this error or fixing it"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"message"}),", ",(0,r.jsx)(n.code,{children:"code"}),", ",(0,r.jsx)(n.code,{children:"suggestions"}),", ",(0,r.jsx)(n.code,{children:"ref"})," properties will be displayed when an error is shown. Reusable ",(0,r.jsx)(n.code,{children:"Error"})," classes can be created that display the optional outputs above by implementing the ",(0,r.jsx)(n.code,{children:"PrettyPrintableError"})," interface from the ",(0,r.jsx)(n.code,{children:"Errors"})," namespace from ",(0,r.jsx)(n.code,{children:"@oclif/core"})," and ",(0,r.jsx)(n.code,{children:"this.error"})," will handle them appropriately."]}),"\n",(0,r.jsxs)(n.p,{children:["These errors are friendly and won't show a traceback unless debugging is enabled with ",(0,r.jsx)(n.code,{children:"DEBUG=*"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"import {CLIError} from '@oclif/errors'\n\nthrow new CLIError('my friendly error')\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Any error caught by the command of this ",(0,r.jsx)(n.code,{children:"CLIError"})," type will be shown without traceback."]}),"\n",(0,r.jsx)(n.h3,{id:"thisexitcode-number--0",children:(0,r.jsx)(n.code,{children:"this.exit(code: number = 0)"})}),"\n",(0,r.jsx)(n.p,{children:"Exit process. Defaults to status 0."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.exit()\nthis.exit(1)\n"})}),"\n",(0,r.jsx)(n.h3,{id:"thislogtostderrmessage-string",children:(0,r.jsx)(n.code,{children:"this.logToStderr(message: string)"})}),"\n",(0,r.jsxs)(n.p,{children:["Log a message to the terminal's ",(0,r.jsx)(n.code,{children:"stderr"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thisjsonenabled",children:(0,r.jsx)(n.code,{children:"this.jsonEnabled()"})}),"\n",(0,r.jsxs)(n.p,{children:["Returns to ",(0,r.jsx)(n.code,{children:"true"})," if the ",(0,r.jsx)(n.code,{children:"--json"})," flag is present and ",(0,r.jsx)(n.code,{children:"enableJsonFlag"})," is set to ",(0,r.jsx)(n.code,{children:"true"})]}),"\n",(0,r.jsx)(n.h3,{id:"thistosuccessjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toSuccessJson(result: unknown)"})}),"\n",(0,r.jsx)(n.p,{children:"Modify the command's success JSON output before it's displayed to the user."}),"\n",(0,r.jsx)(n.h3,{id:"thistoerrorjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toErrorJson(result: unknown)"})}),"\n",(0,r.jsx)(n.p,{children:"Modify the command's error JSON output before it's displayed to the user."})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>d});var r=s(6540);const o={},t=r.createContext(o);function i(e){const n=r.useContext(t);return r.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:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2961],{8976:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>t,metadata:()=>d,toc:()=>a});var r=s(4848),o=s(8453);const t={title:"Commands"},i=void 0,d={id:"commands",title:"Commands",description:"A basic command looks like the following in TypeScript:",source:"@site/../docs/commands.md",sourceDirName:".",slug:"/commands",permalink:"/docs/commands",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/commands.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Commands"},sidebar:"docs",previous:{title:"Command Discovery Strategies",permalink:"/docs/command_discovery_strategies"},next:{title:"Command Arguments",permalink:"/docs/args"}},c={},a=[{value:"Avoiding Timeouts",id:"avoiding-timeouts",level:3},{value:"Other Command Options",id:"other-command-options",level:3},{value:"Command Methods",id:"command-methods",level:2},{value:"this.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(): Promise {\n console.log('running my command')\n }\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The only part that is required is the run function. Accept user input with ",(0,r.jsx)(n.a,{href:"/docs/args",children:"arguments"})," and ",(0,r.jsx)(n.a,{href:"/docs/flags",children:"flags"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"In JavaScript:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"const {Command} = require('@oclif/core')\n\nclass MyCommand extends Command {\n async run() {\n console.log('running my command')\n }\n}\n\nMyCommand.description = 'description of this example command'\n\nmodule.exports = MyCommand\n"})}),"\n",(0,r.jsx)(n.p,{children:"Note that the following examples will be in TypeScript. As JavaScript does not yet have static class properties, you will have to add them to the class after it is declared like we did with the description above."}),"\n",(0,r.jsx)(n.h3,{id:"avoiding-timeouts",children:"Avoiding Timeouts"}),"\n",(0,r.jsxs)(n.p,{children:["In order to avoid command executions running indefinitely, oclif will terminate the node process 10 seconds after ",(0,r.jsx)(n.code,{children:"Command.run"})," resolves. This means that all command logic inside the ",(0,r.jsx)(n.code,{children:"run"})," method should either run synchronously or should return a ",(0,r.jsx)(n.code,{children:"Promise"}),". This will allow the entire command to run before the 10 second timeout starts."]}),"\n",(0,r.jsxs)(n.p,{children:["In other words, ",(0,r.jsxs)(n.strong,{children:["if you execute a promise in ",(0,r.jsx)(n.code,{children:"Command.run"})," without a awaiting it, then the command will likely timeout before it's completed."]})]}),"\n",(0,r.jsx)(n.h3,{id:"other-command-options",children:"Other Command Options"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://github.com/oclif/core/blob/main/src/command.ts",children:"See the base class to get an idea of what methods can be called on a command"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"import {Command, Flags} from '@oclif/core'\n\nexport class MyCommand extends Command {\n static summary = 'A brief overview of your command.'\n static description = `\nAn in-depth description of the command.\nIt can be multiline.\n`\n\n // hide the command from help\n static hidden = false\n\n // custom usage string for help\n // this overrides the default usage\n static usage = 'mycommand --myflag'\n\n // examples to add to help\n // <%= config.bin %> resolves to the executable name\n // <%= command.id %> resolves to the command name\n static examples = [\n // Examples can be simple strings\n '<%= config.bin %> <%= command.id %> --help',\n // Or objects that provide a description of the example command\n {\n description: 'Force the command to execute',\n command: '<%= config.bin %> <%= command.id %> --force',\n }\n ]\n\n // this makes the parser not fail when it receives invalid arguments\n // defaults to true\n // set it to false if you need to accept a variable number of arguments\n static strict = false\n\n // define aliases that can execute this command.\n static aliases = ['alternate:name:for:this:command']\n\n // Set to true if you want to add the --json flag to your command.\n // oclif will automatically suppress logs (if you use this.log, this.warn, or this.error) and\n // display the JSON returned by the command's run method.\n static enableJsonFlag = true\n\n async run() {\n // show a warning\n this.warn('uh oh!')\n // exit with an error message\n this.error('uh oh!!!')\n // exit with status code\n this.exit(1)\n }\n}\n"})}),"\n",(0,r.jsx)(n.h2,{id:"command-methods",children:"Command Methods"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"#command-methods",children:"Command Methods"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thislogmessage-string",children:(0,r.jsx)(n.code,{children:"this.log(message: string)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thiswarnmessage-string--error",children:(0,r.jsx)(n.code,{children:"this.warn(message: string | Error)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thiserrormessage-string--error-options-code-string-exit-number-ref-string-suggestions-string",children:(0,r.jsx)(n.code,{children:"this.error(message: string | Error, options?: {code?: string, exit?: number, ref?: string; suggestions?: string[];})"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thisexitcode-number--0",children:(0,r.jsx)(n.code,{children:"this.exit(code: number = 0)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thislogtostderrmessage-string",children:(0,r.jsx)(n.code,{children:"this.logToStderr(message: string)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thisjsonenabled",children:(0,r.jsx)(n.code,{children:"this.jsonEnabled()"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thistosuccessjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toSuccessJson(result: unknown)"})})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#thistoerrorjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toErrorJson(result: unknown)"})})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The following assumes you are in the ",(0,r.jsx)(n.code,{children:"run()"})," method of an oclif ",(0,r.jsx)(n.a,{href:"/docs/commands",children:"command"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thislogmessage-string",children:(0,r.jsx)(n.code,{children:"this.log(message: string)"})}),"\n",(0,r.jsxs)(n.p,{children:["Output message to stdout (non-blocking). ",(0,r.jsx)(n.code,{children:"console.log()"})," works fine too, but that is a blocking call and won't be automatically suppressed when the ",(0,r.jsx)(n.code,{children:"--json"})," flag is present. This uses ",(0,r.jsx)(n.a,{href:"https://nodejs.org/api/util.html#util_util_format_format_args",children:"util.format()"})," which behaves the same as ",(0,r.jsx)(n.code,{children:"console.log()"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.log('hello, world!')\n"})}),"\n",(0,r.jsx)(n.h3,{id:"thiswarnmessage-string--error",children:(0,r.jsx)(n.code,{children:"this.warn(message: string | Error)"})}),"\n",(0,r.jsx)(n.p,{children:"Display an error or message as a warning"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.warn('uh oh!')\nthis.warn(new Error('uh oh!'))\n"})}),"\n",(0,r.jsx)(n.h3,{id:"thiserrormessage-string--error-options-code-string-exit-number-ref-string-suggestions-string",children:(0,r.jsx)(n.code,{children:"this.error(message: string | Error, options?: {code?: string, exit?: number, ref?: string; suggestions?: string[];})"})}),"\n",(0,r.jsx)(n.p,{children:"Display error and exit. Also add a code to error object or exit status."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.error('uh oh!', {exit: 2})\nthis.error(new Error('uh oh!'))\n"})}),"\n",(0,r.jsx)(n.p,{children:"The options object has the following options:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"exit"})," \u2014 exit code to use"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"code"})," \u2014 a unique error code for the type of error"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"suggestions"})," \u2014 an array of suggestions for a user to try next that may be useful or provide additional context"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ref"})," \u2014 a url to documentation related to this error or fixing it"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"message"}),", ",(0,r.jsx)(n.code,{children:"code"}),", ",(0,r.jsx)(n.code,{children:"suggestions"}),", ",(0,r.jsx)(n.code,{children:"ref"})," properties will be displayed when an error is shown. Reusable ",(0,r.jsx)(n.code,{children:"Error"})," classes can be created that display the optional outputs above by implementing the ",(0,r.jsx)(n.code,{children:"PrettyPrintableError"})," interface from the ",(0,r.jsx)(n.code,{children:"Errors"})," namespace from ",(0,r.jsx)(n.code,{children:"@oclif/core"})," and ",(0,r.jsx)(n.code,{children:"this.error"})," will handle them appropriately."]}),"\n",(0,r.jsxs)(n.p,{children:["These errors are friendly and won't show a traceback unless debugging is enabled with ",(0,r.jsx)(n.code,{children:"DEBUG=*"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"import {CLIError} from '@oclif/errors'\n\nthrow new CLIError('my friendly error')\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Any error caught by the command of this ",(0,r.jsx)(n.code,{children:"CLIError"})," type will be shown without traceback."]}),"\n",(0,r.jsx)(n.h3,{id:"thisexitcode-number--0",children:(0,r.jsx)(n.code,{children:"this.exit(code: number = 0)"})}),"\n",(0,r.jsx)(n.p,{children:"Exit process. Defaults to status 0."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"this.exit()\nthis.exit(1)\n"})}),"\n",(0,r.jsx)(n.h3,{id:"thislogtostderrmessage-string",children:(0,r.jsx)(n.code,{children:"this.logToStderr(message: string)"})}),"\n",(0,r.jsxs)(n.p,{children:["Log a message to the terminal's ",(0,r.jsx)(n.code,{children:"stderr"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"thisjsonenabled",children:(0,r.jsx)(n.code,{children:"this.jsonEnabled()"})}),"\n",(0,r.jsxs)(n.p,{children:["Returns to ",(0,r.jsx)(n.code,{children:"true"})," if the ",(0,r.jsx)(n.code,{children:"--json"})," flag is present and ",(0,r.jsx)(n.code,{children:"enableJsonFlag"})," is set to ",(0,r.jsx)(n.code,{children:"true"})]}),"\n",(0,r.jsx)(n.h3,{id:"thistosuccessjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toSuccessJson(result: unknown)"})}),"\n",(0,r.jsx)(n.p,{children:"Modify the command's success JSON output before it's displayed to the user."}),"\n",(0,r.jsx)(n.h3,{id:"thistoerrorjsonresult-unknown",children:(0,r.jsx)(n.code,{children:"this.toErrorJson(result: unknown)"})}),"\n",(0,r.jsx)(n.p,{children:"Modify the command's error JSON output before it's displayed to the user."})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>d});var r=s(6540);const o={},t=r.createContext(o);function i(e){const n=r.useContext(t);return r.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:i(e.components),r.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/713bb917.dbd2243e.js b/assets/js/713bb917.cf149bb6.js similarity index 99% rename from assets/js/713bb917.dbd2243e.js rename to assets/js/713bb917.cf149bb6.js index 5e7e5aaf..0a0189d8 100644 --- a/assets/js/713bb917.dbd2243e.js +++ b/assets/js/713bb917.cf149bb6.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5483],{5678:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>r});var i=t(4848),a=t(8453);const s={title:"Release"},l=void 0,o={id:"releasing",title:"Release",description:"There are 2 main strategies for releasing oclif CLIs: npm and standalone tarballs. You can publish to one or both.",source:"@site/../docs/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/docs/releasing",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/releasing.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Release"},sidebar:"docs",previous:{title:"JSON",permalink:"/docs/json"},next:{title:"Testing",permalink:"/docs/testing"}},c={},r=[{value:"npm",id:"npm",level:2},{value:"Standalone tarballs",id:"standalone-tarballs",level:2},{value:"Brew",id:"brew",level:2},{value:"Autoupdater",id:"autoupdater",level:2},{value:"Autoupdate Channels",id:"autoupdate-channels",level:2},{value:"Windows installer",id:"windows-installer",level:2},{value:"macOS installer",id:"macos-installer",level:2},{value:"Uploading to S3",id:"uploading-to-s3",level:3},{value:"Signing the installer",id:"signing-the-installer",level:3},{value:"Ubuntu/Debian packages",id:"ubuntudebian-packages",level:2},{value:"Snapcraft",id:"snapcraft",level:2}];function d(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"There are 2 main strategies for releasing oclif CLIs: npm and standalone tarballs. You can publish to one or both."}),"\n",(0,i.jsx)(n.h2,{id:"npm",children:"npm"}),"\n",(0,i.jsxs)(n.p,{children:["Just use ",(0,i.jsx)(n.code,{children:"npm publish"})," like any other npm project. This includes a ",(0,i.jsx)(n.code,{children:"run.cmd"})," script that will automatically be used for Windows users."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh-session",children:"$ npm version (major|minor|patch) # bumps version, updates README, adds git tag\n$ npm publish\n$ npm install -g mynewcli\n$ mynewcli\n# OR\n$ npx mynewcli\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You'll need to ",(0,i.jsx)(n.a,{href:"https://www.npmjs.com/signup",children:"register with npm"})," and have verified your email address in order to publish."]}),"\n",(0,i.jsxs)(n.p,{children:["This workflow can be improved slightly by running ",(0,i.jsx)(n.code,{children:"npm version major|minor|patch"})," before publishing which will create a git tag and bump the version automatically."]}),"\n",(0,i.jsx)(n.h2,{id:"standalone-tarballs",children:"Standalone tarballs"}),"\n",(0,i.jsxs)(n.p,{children:["Build standalone tarballs with ",(0,i.jsx)(n.code,{children:"oclif pack tarballs"})," from the root of your CLI. These include the node binary so the user does not have to already have node installed to use the CLI. It won't put this node binary on the PATH so the binary will not conflict with any node installation on the machine."]}),"\n",(0,i.jsxs)(n.p,{children:["To publish, you can copy the files from ",(0,i.jsx)(n.code,{children:"./dist"})," or use ",(0,i.jsx)(n.code,{children:"oclif upload tarballs"})," to copy the files to S3. You'll need to set ",(0,i.jsx)(n.code,{children:"oclif.update.s3.bucket"})," in ",(0,i.jsx)(n.code,{children:"package.json"})," to a valid S3 bucket and have credentials set in ",(0,i.jsx)(n.code,{children:"AWS_ACCESS_KEY_ID"})," and ",(0,i.jsx)(n.code,{children:"AWS_SECRET_ACCESS_KEY"})," environment vars."]}),"\n",(0,i.jsxs)(n.p,{children:["After you've uploaded the tarballs to S3, you can promote the tarballs to a release channel within S3 using ",(0,i.jsx)(n.code,{children:"oclif promote"}),". This allows you to quickly promote and demote a specific version between release channels. For example, the Salesforce CLI has separate ",(0,i.jsx)(n.code,{children:"stable"})," and ",(0,i.jsx)(n.code,{children:"stable-rc"})," channels that are updated weekly."]}),"\n",(0,i.jsx)(n.h2,{id:"brew",children:"Brew"}),"\n",(0,i.jsxs)(n.p,{children:["Your formula can be distributed through Brew. The main caveat is you must set the ",(0,i.jsx)(n.code,{children:"CLIENT_HOME"})," variable when you ship, otherwise it will break the update cycle. An example of this can be found in the ",(0,i.jsx)(n.a,{href:"https://github.com/heroku/homebrew-brew/blob/master/Formula/heroku.rb#L9",children:"heroku cli formula"}),". By exporting a variable of the form ",(0,i.jsx)(n.code,{children:"CLI_NAME_OCLIF_CLIENT_HOME"})," (where ",(0,i.jsx)(n.code,{children:"CLI_NAME"})," is the name of your CLI), you force the update mechanism to look at the brew install location instead of the default (which is ",(0,i.jsx)(n.code,{children:"$XDG_DATA_HOME/.local/share/package_name/client"}),")."]}),"\n",(0,i.jsx)(n.h2,{id:"autoupdater",children:"Autoupdater"}),"\n",(0,i.jsxs)(n.p,{children:["These tarballs as well as the installers below can be made autoupdatable by adding the ",(0,i.jsx)(n.code,{children:"@oclif/plugin-update"})," plugin. Just add this plugin and the CLI will autoupdate in the background or when ",(0,i.jsx)(n.code,{children:"mycli update"})," is run."]}),"\n",(0,i.jsxs)(n.p,{children:["If you don't want to use S3, you can still run ",(0,i.jsx)(n.code,{children:"oclif pack"})," and it will build tarballs. To get the updater to work, set ",(0,i.jsx)(n.code,{children:"oclif.update.s3.host"})," in ",(0,i.jsx)(n.code,{children:"package.json"})," to a host that has the files built in ",(0,i.jsx)(n.code,{children:"./dist"})," from ",(0,i.jsx)(n.code,{children:"oclif pack"}),". This host does not need to be an S3 host. To customize the URL paths, see the S3 templates in ",(0,i.jsx)(n.code,{children:"@oclif/core"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"autoupdate-channels",children:"Autoupdate Channels"}),"\n",(0,i.jsxs)(n.p,{children:["You can have separate channels for releases that work like Google Chrome Channels (such as beta, dev, canary). To create a channel, just change the version in ",(0,i.jsx)(n.code,{children:"package.json"})," from ",(0,i.jsx)(n.code,{children:"1.0.0"})," to ",(0,i.jsx)(n.code,{children:"1.0.0-beta"}),' (where "beta" is any string you like). Then when you pack with ',(0,i.jsx)(n.code,{children:"oclif pack"}),", it will create beta tarballs. The user can change their channel with ",(0,i.jsx)(n.code,{children:"mycli update beta"})," and will receive all the future releases on that channel."]}),"\n",(0,i.jsx)(n.p,{children:"In the Heroku CLI, we have it automatically build and release the beta channel on every commit to the master branch. Then we have it build and release stable channel whenever a git tag is created in our CI."}),"\n",(0,i.jsx)(n.h2,{id:"windows-installer",children:"Windows installer"}),"\n",(0,i.jsxs)(n.p,{children:["Build a windows installer with ",(0,i.jsx)(n.code,{children:"oclif pack win"}),". It will build into ",(0,i.jsx)(n.code,{children:"./dist/win"}),". This can be uploaded to S3 with ",(0,i.jsx)(n.code,{children:"oclif upload win"})," and promoted within S3 with ",(0,i.jsx)(n.code,{children:"oclif promote --win"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The installer uses 7zip and nsis. If you're in a mac or unix environment and don't have them, you can use homebrew to insall them."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"brew install nsis\nbrew install p7zip\n"})}),"\n",(0,i.jsx)(n.h2,{id:"macos-installer",children:"macOS installer"}),"\n",(0,i.jsxs)(n.p,{children:["Build a macOS .pkg installer with ",(0,i.jsx)(n.code,{children:"oclif pack macos"}),". It will build into ",(0,i.jsx)(n.code,{children:"./dist/macos"}),". This can be uploaded to S3 with ",(0,i.jsx)(n.code,{children:"oclif upload macos"})," and promoted within S3 with ",(0,i.jsx)(n.code,{children:"oclif promote --macos"}),". You need to set the macOS identifier at ",(0,i.jsx)(n.code,{children:"oclif.macos.identifier"})," in ",(0,i.jsx)(n.code,{children:"package.json"}),' (we use "com.heroku.cli" and "com.salesforce.cli" as the identifiers for the Heroku CLI and the Salesforce CLI, respectively).']}),"\n",(0,i.jsx)(n.h3,{id:"uploading-to-s3",children:"Uploading to S3"}),"\n",(0,i.jsxs)(n.p,{children:["The upload command defaults to using the ACL setting ",(0,i.jsx)(n.code,{children:"public-read"})," unless another policy is specified under ",(0,i.jsx)(n.code,{children:"oclif.update.s3.acl"})," in ",(0,i.jsx)(n.code,{children:"package.json"}),". However, when creating new S3 buckets, AWS's default recommendation can result in an access error (Code: AccessControlListNotSupported) when trying to upload with the ",(0,i.jsx)(n.code,{children:"public-read"})," setting."]}),"\n",(0,i.jsx)(n.p,{children:"To address this, consider updating the oclif section of your package.json with the desired ACL setting. The example below demonstrates how to set the acl to bucket-owner-full-control:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"oclif": {\n "bin": "myOclifApp",\n "dirname": "myOclifApp-cli-data",\n "update": {\n "s3": {\n "host": "https://s3.console.aws.amazon.com/",\n "bucket": "myOclifApp-cli",\n "acl": "bucket-owner-full-control"\n }\n },\n "macos": {\n "identifier": "com.myOclifApp.cli"\n },\n\n...\n\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Amazon has a userguide ",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/ensure-object-ownership.html#ensure-object-ownership-bucket-policy",children:"here"})," for help how to configure Bucket Policy settings."]}),"\n",(0,i.jsx)(n.h3,{id:"signing-the-installer",children:"Signing the installer"}),"\n",(0,i.jsxs)(n.p,{children:['To be able to sign an "installer signing identity" has to be available on the build machine (read more on certificates ',(0,i.jsx)(n.a,{href:"https://developer.apple.com/help/account/create-certificates/certificates-overview",children:"here"}),").",(0,i.jsx)(n.br,{}),"\n","Make sure such a certificate is created in developer.apple.com and that the certificate is downloaded and installed in the KeyChain of the build machine.",(0,i.jsx)(n.br,{}),"\n","The certificate name has to be specified in the ",(0,i.jsx)(n.code,{children:"oclif.macos.sign"})," in ",(0,i.jsx)(n.code,{children:"package.json"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:' "macos": {\n "identifier": "com.myOclifApp",\n "sign": "\\"3rd Party Mac Developer Installer: myOclifCompany (R2315646)\\""\n },\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Pay attention to the escaped quotation marks, the certificate name is passed on as an argument to the ",(0,i.jsx)(n.code,{children:"pkgbuild"})," command so without quotation marks it might break.",(0,i.jsx)(n.br,{}),"\n",'For the Heroku CLI the certificate name is "Developer ID Installer: Heroku INC". And optionally set the keychain with ',(0,i.jsx)(n.code,{children:"OSX_KEYCHAIN"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Installed certificates on the build machine can be viewed in the Keychain Access app."}),"\n",(0,i.jsx)(n.h2,{id:"ubuntudebian-packages",children:"Ubuntu/Debian packages"}),"\n",(0,i.jsxs)(n.p,{children:["Build a deb package with ",(0,i.jsx)(n.code,{children:"oclif pack deb"}),". Set the ",(0,i.jsx)(n.code,{children:"MYCLI_DEB_KEY"})," to a gpg key id to create the gpg files. This will include all the files needed for an apt repository in ",(0,i.jsx)(n.code,{children:"./dist/deb"}),". They can be uploaded to S3 with ",(0,i.jsx)(n.code,{children:"oclif upload deb"})," and promoted within S3 using ",(0,i.jsx)(n.code,{children:"oclif promote --deb"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Once it's published to S3, users can install with the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh-session",children:'$ wget -qO- https://mys3bucket.s3.amazonaws.com/apt/release.key | apt-key add - # you will need to upload this file manually\n$ sudo echo "deb https://mys3bucket.s3.amazonaws.com/apt ./" > /etc/apt/sources.list.d/mycli.list\n$ sudo apt update\n$ sudo apt install -y mycli\n'})}),"\n",(0,i.jsxs)(n.p,{children:["This can be placed in a ",(0,i.jsx)(n.a,{href:"https://cli-assets.heroku.com/install-ubuntu.sh",children:"script"})," for users to install with ",(0,i.jsx)(n.code,{children:"curl https://pathto/myscript | sh"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"These will not autoupdate as Ubuntu already has a reliable way for users to update their package."}),"\n",(0,i.jsx)(n.h2,{id:"snapcraft",children:"Snapcraft"}),"\n",(0,i.jsxs)(n.p,{children:["Snap is a great way to distribute Linux CLIs and comes built into Ubuntu 16+. The Heroku CLI's ",(0,i.jsx)(n.a,{href:"https://github.com/heroku/cli/blob/master/snap/snapcraft.yaml",children:"snapcraft.yml"})," file can be easily modified to work with any oclif CLI."]})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>o});var i=t(6540);const a={},s=i.createContext(a);function l(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:l(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5483],{5678:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>r});var i=t(4848),a=t(8453);const s={title:"Release"},l=void 0,o={id:"releasing",title:"Release",description:"There are 2 main strategies for releasing oclif CLIs: npm and standalone tarballs. You can publish to one or both.",source:"@site/../docs/releasing.md",sourceDirName:".",slug:"/releasing",permalink:"/docs/releasing",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/releasing.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Release"},sidebar:"docs",previous:{title:"JSON",permalink:"/docs/json"},next:{title:"Testing",permalink:"/docs/testing"}},c={},r=[{value:"npm",id:"npm",level:2},{value:"Standalone tarballs",id:"standalone-tarballs",level:2},{value:"Brew",id:"brew",level:2},{value:"Autoupdater",id:"autoupdater",level:2},{value:"Autoupdate Channels",id:"autoupdate-channels",level:2},{value:"Windows installer",id:"windows-installer",level:2},{value:"macOS installer",id:"macos-installer",level:2},{value:"Uploading to S3",id:"uploading-to-s3",level:3},{value:"Signing the installer",id:"signing-the-installer",level:3},{value:"Ubuntu/Debian packages",id:"ubuntudebian-packages",level:2},{value:"Snapcraft",id:"snapcraft",level:2}];function d(e){const n={a:"a",br:"br",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"There are 2 main strategies for releasing oclif CLIs: npm and standalone tarballs. You can publish to one or both."}),"\n",(0,i.jsx)(n.h2,{id:"npm",children:"npm"}),"\n",(0,i.jsxs)(n.p,{children:["Just use ",(0,i.jsx)(n.code,{children:"npm publish"})," like any other npm project. This includes a ",(0,i.jsx)(n.code,{children:"run.cmd"})," script that will automatically be used for Windows users."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh-session",children:"$ npm version (major|minor|patch) # bumps version, updates README, adds git tag\n$ npm publish\n$ npm install -g mynewcli\n$ mynewcli\n# OR\n$ npx mynewcli\n"})}),"\n",(0,i.jsxs)(n.p,{children:["You'll need to ",(0,i.jsx)(n.a,{href:"https://www.npmjs.com/signup",children:"register with npm"})," and have verified your email address in order to publish."]}),"\n",(0,i.jsxs)(n.p,{children:["This workflow can be improved slightly by running ",(0,i.jsx)(n.code,{children:"npm version major|minor|patch"})," before publishing which will create a git tag and bump the version automatically."]}),"\n",(0,i.jsx)(n.h2,{id:"standalone-tarballs",children:"Standalone tarballs"}),"\n",(0,i.jsxs)(n.p,{children:["Build standalone tarballs with ",(0,i.jsx)(n.code,{children:"oclif pack tarballs"})," from the root of your CLI. These include the node binary so the user does not have to already have node installed to use the CLI. It won't put this node binary on the PATH so the binary will not conflict with any node installation on the machine."]}),"\n",(0,i.jsxs)(n.p,{children:["To publish, you can copy the files from ",(0,i.jsx)(n.code,{children:"./dist"})," or use ",(0,i.jsx)(n.code,{children:"oclif upload tarballs"})," to copy the files to S3. You'll need to set ",(0,i.jsx)(n.code,{children:"oclif.update.s3.bucket"})," in ",(0,i.jsx)(n.code,{children:"package.json"})," to a valid S3 bucket and have credentials set in ",(0,i.jsx)(n.code,{children:"AWS_ACCESS_KEY_ID"})," and ",(0,i.jsx)(n.code,{children:"AWS_SECRET_ACCESS_KEY"})," environment vars."]}),"\n",(0,i.jsxs)(n.p,{children:["After you've uploaded the tarballs to S3, you can promote the tarballs to a release channel within S3 using ",(0,i.jsx)(n.code,{children:"oclif promote"}),". This allows you to quickly promote and demote a specific version between release channels. For example, the Salesforce CLI has separate ",(0,i.jsx)(n.code,{children:"stable"})," and ",(0,i.jsx)(n.code,{children:"stable-rc"})," channels that are updated weekly."]}),"\n",(0,i.jsx)(n.h2,{id:"brew",children:"Brew"}),"\n",(0,i.jsxs)(n.p,{children:["Your formula can be distributed through Brew. The main caveat is you must set the ",(0,i.jsx)(n.code,{children:"CLIENT_HOME"})," variable when you ship, otherwise it will break the update cycle. An example of this can be found in the ",(0,i.jsx)(n.a,{href:"https://github.com/heroku/homebrew-brew/blob/master/Formula/heroku.rb#L9",children:"heroku cli formula"}),". By exporting a variable of the form ",(0,i.jsx)(n.code,{children:"CLI_NAME_OCLIF_CLIENT_HOME"})," (where ",(0,i.jsx)(n.code,{children:"CLI_NAME"})," is the name of your CLI), you force the update mechanism to look at the brew install location instead of the default (which is ",(0,i.jsx)(n.code,{children:"$XDG_DATA_HOME/.local/share/package_name/client"}),")."]}),"\n",(0,i.jsx)(n.h2,{id:"autoupdater",children:"Autoupdater"}),"\n",(0,i.jsxs)(n.p,{children:["These tarballs as well as the installers below can be made autoupdatable by adding the ",(0,i.jsx)(n.code,{children:"@oclif/plugin-update"})," plugin. Just add this plugin and the CLI will autoupdate in the background or when ",(0,i.jsx)(n.code,{children:"mycli update"})," is run."]}),"\n",(0,i.jsxs)(n.p,{children:["If you don't want to use S3, you can still run ",(0,i.jsx)(n.code,{children:"oclif pack"})," and it will build tarballs. To get the updater to work, set ",(0,i.jsx)(n.code,{children:"oclif.update.s3.host"})," in ",(0,i.jsx)(n.code,{children:"package.json"})," to a host that has the files built in ",(0,i.jsx)(n.code,{children:"./dist"})," from ",(0,i.jsx)(n.code,{children:"oclif pack"}),". This host does not need to be an S3 host. To customize the URL paths, see the S3 templates in ",(0,i.jsx)(n.code,{children:"@oclif/core"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"autoupdate-channels",children:"Autoupdate Channels"}),"\n",(0,i.jsxs)(n.p,{children:["You can have separate channels for releases that work like Google Chrome Channels (such as beta, dev, canary). To create a channel, just change the version in ",(0,i.jsx)(n.code,{children:"package.json"})," from ",(0,i.jsx)(n.code,{children:"1.0.0"})," to ",(0,i.jsx)(n.code,{children:"1.0.0-beta"}),' (where "beta" is any string you like). Then when you pack with ',(0,i.jsx)(n.code,{children:"oclif pack"}),", it will create beta tarballs. The user can change their channel with ",(0,i.jsx)(n.code,{children:"mycli update beta"})," and will receive all the future releases on that channel."]}),"\n",(0,i.jsx)(n.p,{children:"In the Heroku CLI, we have it automatically build and release the beta channel on every commit to the master branch. Then we have it build and release stable channel whenever a git tag is created in our CI."}),"\n",(0,i.jsx)(n.h2,{id:"windows-installer",children:"Windows installer"}),"\n",(0,i.jsxs)(n.p,{children:["Build a windows installer with ",(0,i.jsx)(n.code,{children:"oclif pack win"}),". It will build into ",(0,i.jsx)(n.code,{children:"./dist/win"}),". This can be uploaded to S3 with ",(0,i.jsx)(n.code,{children:"oclif upload win"})," and promoted within S3 with ",(0,i.jsx)(n.code,{children:"oclif promote --win"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"The installer uses 7zip and nsis. If you're in a mac or unix environment and don't have them, you can use homebrew to insall them."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"brew install nsis\nbrew install p7zip\n"})}),"\n",(0,i.jsx)(n.h2,{id:"macos-installer",children:"macOS installer"}),"\n",(0,i.jsxs)(n.p,{children:["Build a macOS .pkg installer with ",(0,i.jsx)(n.code,{children:"oclif pack macos"}),". It will build into ",(0,i.jsx)(n.code,{children:"./dist/macos"}),". This can be uploaded to S3 with ",(0,i.jsx)(n.code,{children:"oclif upload macos"})," and promoted within S3 with ",(0,i.jsx)(n.code,{children:"oclif promote --macos"}),". You need to set the macOS identifier at ",(0,i.jsx)(n.code,{children:"oclif.macos.identifier"})," in ",(0,i.jsx)(n.code,{children:"package.json"}),' (we use "com.heroku.cli" and "com.salesforce.cli" as the identifiers for the Heroku CLI and the Salesforce CLI, respectively).']}),"\n",(0,i.jsx)(n.h3,{id:"uploading-to-s3",children:"Uploading to S3"}),"\n",(0,i.jsxs)(n.p,{children:["The upload command defaults to using the ACL setting ",(0,i.jsx)(n.code,{children:"public-read"})," unless another policy is specified under ",(0,i.jsx)(n.code,{children:"oclif.update.s3.acl"})," in ",(0,i.jsx)(n.code,{children:"package.json"}),". However, when creating new S3 buckets, AWS's default recommendation can result in an access error (Code: AccessControlListNotSupported) when trying to upload with the ",(0,i.jsx)(n.code,{children:"public-read"})," setting."]}),"\n",(0,i.jsx)(n.p,{children:"To address this, consider updating the oclif section of your package.json with the desired ACL setting. The example below demonstrates how to set the acl to bucket-owner-full-control:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:'"oclif": {\n "bin": "myOclifApp",\n "dirname": "myOclifApp-cli-data",\n "update": {\n "s3": {\n "host": "https://s3.console.aws.amazon.com/",\n "bucket": "myOclifApp-cli",\n "acl": "bucket-owner-full-control"\n }\n },\n "macos": {\n "identifier": "com.myOclifApp.cli"\n },\n\n...\n\n}\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Amazon has a userguide ",(0,i.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/ensure-object-ownership.html#ensure-object-ownership-bucket-policy",children:"here"})," for help how to configure Bucket Policy settings."]}),"\n",(0,i.jsx)(n.h3,{id:"signing-the-installer",children:"Signing the installer"}),"\n",(0,i.jsxs)(n.p,{children:['To be able to sign an "installer signing identity" has to be available on the build machine (read more on certificates ',(0,i.jsx)(n.a,{href:"https://developer.apple.com/help/account/create-certificates/certificates-overview",children:"here"}),").",(0,i.jsx)(n.br,{}),"\n","Make sure such a certificate is created in developer.apple.com and that the certificate is downloaded and installed in the KeyChain of the build machine.",(0,i.jsx)(n.br,{}),"\n","The certificate name has to be specified in the ",(0,i.jsx)(n.code,{children:"oclif.macos.sign"})," in ",(0,i.jsx)(n.code,{children:"package.json"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:' "macos": {\n "identifier": "com.myOclifApp",\n "sign": "\\"3rd Party Mac Developer Installer: myOclifCompany (R2315646)\\""\n },\n'})}),"\n",(0,i.jsxs)(n.p,{children:["Pay attention to the escaped quotation marks, the certificate name is passed on as an argument to the ",(0,i.jsx)(n.code,{children:"pkgbuild"})," command so without quotation marks it might break.",(0,i.jsx)(n.br,{}),"\n",'For the Heroku CLI the certificate name is "Developer ID Installer: Heroku INC". And optionally set the keychain with ',(0,i.jsx)(n.code,{children:"OSX_KEYCHAIN"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Installed certificates on the build machine can be viewed in the Keychain Access app."}),"\n",(0,i.jsx)(n.h2,{id:"ubuntudebian-packages",children:"Ubuntu/Debian packages"}),"\n",(0,i.jsxs)(n.p,{children:["Build a deb package with ",(0,i.jsx)(n.code,{children:"oclif pack deb"}),". Set the ",(0,i.jsx)(n.code,{children:"MYCLI_DEB_KEY"})," to a gpg key id to create the gpg files. This will include all the files needed for an apt repository in ",(0,i.jsx)(n.code,{children:"./dist/deb"}),". They can be uploaded to S3 with ",(0,i.jsx)(n.code,{children:"oclif upload deb"})," and promoted within S3 using ",(0,i.jsx)(n.code,{children:"oclif promote --deb"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Once it's published to S3, users can install with the following:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh-session",children:'$ wget -qO- https://mys3bucket.s3.amazonaws.com/apt/release.key | apt-key add - # you will need to upload this file manually\n$ sudo echo "deb https://mys3bucket.s3.amazonaws.com/apt ./" > /etc/apt/sources.list.d/mycli.list\n$ sudo apt update\n$ sudo apt install -y mycli\n'})}),"\n",(0,i.jsxs)(n.p,{children:["This can be placed in a ",(0,i.jsx)(n.a,{href:"https://cli-assets.heroku.com/install-ubuntu.sh",children:"script"})," for users to install with ",(0,i.jsx)(n.code,{children:"curl https://pathto/myscript | sh"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"These will not autoupdate as Ubuntu already has a reliable way for users to update their package."}),"\n",(0,i.jsx)(n.h2,{id:"snapcraft",children:"Snapcraft"}),"\n",(0,i.jsxs)(n.p,{children:["Snap is a great way to distribute Linux CLIs and comes built into Ubuntu 16+. The Heroku CLI's ",(0,i.jsx)(n.a,{href:"https://github.com/heroku/cli/blob/master/snap/snapcraft.yaml",children:"snapcraft.yml"})," file can be easily modified to work with any oclif CLI."]})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>l,x:()=>o});var i=t(6540);const a={},s=i.createContext(a);function l(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:l(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7bd58895.825ec359.js b/assets/js/7bd58895.bbd59ad7.js similarity index 98% rename from assets/js/7bd58895.825ec359.js rename to assets/js/7bd58895.bbd59ad7.js index a201c7a4..7f973d20 100644 --- a/assets/js/7bd58895.825ec359.js +++ b/assets/js/7bd58895.bbd59ad7.js @@ -1 +1 @@ -"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:1710860746,formattedLastUpdatedAt:"Mar 19, 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 +"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 p # will list all commands starting with 'p' for completion\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.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:()=>a,x:()=>l});var o=n(6540);const i={},s=o.createContext(i);function a(e){const t=o.useContext(s);return o.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(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"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:1711121897,formattedLastUpdatedAt:"Mar 22, 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 p # will list all commands starting with 'p' for completion\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.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:()=>a,x:()=>l});var o=n(6540);const i={},s=o.createContext(i);function a(e){const t=o.useContext(s);return o.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(i):e.components||i:a(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a92e169d.c9dc0b54.js b/assets/js/a92e169d.82f135f1.js similarity index 97% rename from assets/js/a92e169d.c9dc0b54.js rename to assets/js/a92e169d.82f135f1.js index a8d99850..8e398cd8 100644 --- a/assets/js/a92e169d.c9dc0b54.js +++ b/assets/js/a92e169d.82f135f1.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5924],{1177:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>c,toc:()=>i});var t=a(4848),o=a(8453);const s={title:"Global Flags"},l=void 0,c={id:"global_flags",title:"Global Flags",description:"There are some instances where you might want to define a flag once for all of your commands. In this case you can add a global flag to an abstract base Command class. For example,",source:"@site/../docs/global_flags.md",sourceDirName:".",slug:"/global_flags",permalink:"/docs/global_flags",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/global_flags.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Global Flags"},sidebar:"docs",previous:{title:"Flexible Taxonomy",permalink:"/docs/flexible_taxonomy"},next:{title:"Single Command CLI",permalink:"/docs/single_command_cli"}},r={},i=[];function d(e){const n={code:"code",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["There are some instances where you might want to define a flag once for all of your commands. In this case you can add a global flag to an abstract base ",(0,t.jsx)(n.code,{children:"Command"})," class. For example,"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import { Command, Flags } from '@oclif/core';\n\nexport abstract class BaseCommand extends Command {\n static baseFlags = {\n interactive: Flags.boolean({\n char: 'i',\n description: 'Run command in interactive mode',\n }),\n };\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Any command that extends ",(0,t.jsx)(n.code,{children:"BaseCommand"})," will now have an ",(0,t.jsx)(n.code,{children:"--interactive"})," flag on it."]})]})}function m(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>l,x:()=>c});var t=a(6540);const o={},s=t.createContext(o);function l(e){const n=t.useContext(s);return t.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(o):e.components||o:l(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5924],{1177:(e,n,a)=>{a.r(n),a.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>c,toc:()=>i});var t=a(4848),o=a(8453);const s={title:"Global Flags"},l=void 0,c={id:"global_flags",title:"Global Flags",description:"There are some instances where you might want to define a flag once for all of your commands. In this case you can add a global flag to an abstract base Command class. For example,",source:"@site/../docs/global_flags.md",sourceDirName:".",slug:"/global_flags",permalink:"/docs/global_flags",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/global_flags.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Global Flags"},sidebar:"docs",previous:{title:"Flexible Taxonomy",permalink:"/docs/flexible_taxonomy"},next:{title:"Single Command CLI",permalink:"/docs/single_command_cli"}},r={},i=[];function d(e){const n={code:"code",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["There are some instances where you might want to define a flag once for all of your commands. In this case you can add a global flag to an abstract base ",(0,t.jsx)(n.code,{children:"Command"})," class. For example,"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import { Command, Flags } from '@oclif/core';\n\nexport abstract class BaseCommand extends Command {\n static baseFlags = {\n interactive: Flags.boolean({\n char: 'i',\n description: 'Run command in interactive mode',\n }),\n };\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Any command that extends ",(0,t.jsx)(n.code,{children:"BaseCommand"})," will now have an ",(0,t.jsx)(n.code,{children:"--interactive"})," flag on it."]})]})}function m(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,a)=>{a.d(n,{R:()=>l,x:()=>c});var t=a(6540);const o={},s=t.createContext(o);function l(e){const n=t.useContext(s);return t.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(o):e.components||o:l(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a96ec439.53b19970.js b/assets/js/a96ec439.3b3c006e.js similarity index 97% rename from assets/js/a96ec439.53b19970.js rename to assets/js/a96ec439.3b3c006e.js index 0b8e6124..6baff4e1 100644 --- a/assets/js/a96ec439.53b19970.js +++ b/assets/js/a96ec439.3b3c006e.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[1595],{1204:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>f,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var i=e(4848),o=e(8453);const s={title:"Notifications"},r=void 0,c={id:"notifications",title:"Notifications",description:"Use node-notifier for cross-platform OS notifications.",source:"@site/../docs/notifications.md",sourceDirName:".",slug:"/notifications",permalink:"/docs/notifications",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/notifications.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Notifications"},sidebar:"docs",previous:{title:"Table",permalink:"/docs/table"},next:{title:"Debugging",permalink:"/docs/debugging"}},a={},d=[];function l(t){const n={a:"a",code:"code",img:"img",p:"p",pre:"pre",...(0,o.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["Use ",(0,i.jsx)(n.a,{href:"https://github.com/mikaelbr/node-notifier",children:"node-notifier"})," for cross-platform OS notifications."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"import {Command} from '@oclif/core'\nimport * as notifier from 'node-notifier'\n\nexport class MyCommand extends Command {\n async run() {\n notifier.notify({\n title: 'My notification',\n message: 'Hello!'\n })\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Demo:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"notification demo",src:e(3521).A+"",width:"1028",height:"803"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://github.com/mikaelbr/node-notifier",children:"node-notifier"})," is capable of much more such as adding images, sounds, and even buttons and user input."]})]})}function f(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(l,{...t})}):l(t)}},3521:(t,n,e)=>{e.d(n,{A:()=>i});const i=e.p+"assets/images/notification_demo-4cc045397623e249062842eb4b8afab0.gif"},8453:(t,n,e)=>{e.d(n,{R:()=>r,x:()=>c});var i=e(6540);const o={},s=i.createContext(o);function r(t){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function c(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:r(t.components),i.createElement(s.Provider,{value:n},t.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[1595],{1204:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>f,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var i=e(4848),o=e(8453);const s={title:"Notifications"},r=void 0,c={id:"notifications",title:"Notifications",description:"Use node-notifier for cross-platform OS notifications.",source:"@site/../docs/notifications.md",sourceDirName:".",slug:"/notifications",permalink:"/docs/notifications",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/notifications.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Notifications"},sidebar:"docs",previous:{title:"Table",permalink:"/docs/table"},next:{title:"Debugging",permalink:"/docs/debugging"}},a={},d=[];function l(t){const n={a:"a",code:"code",img:"img",p:"p",pre:"pre",...(0,o.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["Use ",(0,i.jsx)(n.a,{href:"https://github.com/mikaelbr/node-notifier",children:"node-notifier"})," for cross-platform OS notifications."]}),"\n",(0,i.jsx)(n.p,{children:"Example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-typescript",children:"import {Command} from '@oclif/core'\nimport * as notifier from 'node-notifier'\n\nexport class MyCommand extends Command {\n async run() {\n notifier.notify({\n title: 'My notification',\n message: 'Hello!'\n })\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Demo:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"notification demo",src:e(3521).A+"",width:"1028",height:"803"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.a,{href:"https://github.com/mikaelbr/node-notifier",children:"node-notifier"})," is capable of much more such as adding images, sounds, and even buttons and user input."]})]})}function f(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(l,{...t})}):l(t)}},3521:(t,n,e)=>{e.d(n,{A:()=>i});const i=e.p+"assets/images/notification_demo-4cc045397623e249062842eb4b8afab0.gif"},8453:(t,n,e)=>{e.d(n,{R:()=>r,x:()=>c});var i=e(6540);const o={},s=i.createContext(o);function r(t){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function c(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:r(t.components),i.createElement(s.Provider,{value:n},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/b3cc73c6.473e1578.js b/assets/js/b3cc73c6.b180e5dd.js similarity index 98% rename from assets/js/b3cc73c6.473e1578.js rename to assets/js/b3cc73c6.b180e5dd.js index cadd94df..02a27525 100644 --- a/assets/js/b3cc73c6.473e1578.js +++ b/assets/js/b3cc73c6.b180e5dd.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2381],{6957:(e,o,s)=>{s.r(o),s.d(o,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var n=s(4848),t=s(8453);const i={title:"How We Work"},r=void 0,a={id:"how_we_work",title:"How We Work",description:"oclif is an open-source project built and maintained by Salesforce and an essential component of Salesforce's developer experiences, powering millions of users' CLIs a day via the Salesforce CLI, the Heroku CLI and others.",source:"@site/../docs/how_we_work.md",sourceDirName:".",slug:"/how_we_work",permalink:"/docs/how_we_work",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/how_we_work.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"How We Work"},sidebar:"docs",previous:{title:"Related Repositories",permalink:"/docs/related_repos"},next:{title:"Feedback",permalink:"/docs/feedback"}},l={},c=[{value:"Code of Conduct & Community Guidelines",id:"code-of-conduct--community-guidelines",level:2},{value:"Work Tracking",id:"work-tracking",level:2},{value:"Issues",id:"issues",level:2},{value:"Pull Requests",id:"pull-requests",level:2},{value:"Deprecations",id:"deprecations",level:2},{value:"Blog Posts",id:"blog-posts",level:2},{value:"Feedback",id:"feedback",level:2},{value:"Updates to How We Work",id:"updates-to-how-we-work",level:2}];function d(e){const o={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["oclif is an open-source project built and maintained by Salesforce and an essential component of Salesforce's developer experiences, powering millions of users' CLIs a day via the Salesforce CLI, the Heroku CLI and ",(0,n.jsx)(o.a,{href:"https://www.npmjs.com/browse/depended/@oclif/core",children:"others"}),"."]}),"\n",(0,n.jsxs)(o.p,{children:["As an open-source project, ",(0,n.jsx)(o.a,{href:"https://github.com/oclif",children:"oclif repos live on GitHub"})," and are published to ",(0,n.jsx)(o.a,{href:"https://www.npmjs.com/search?q=oclif",children:"npmjs.com"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"code-of-conduct--community-guidelines",children:"Code of Conduct & Community Guidelines"}),"\n",(0,n.jsxs)(o.p,{children:["We are thrilled to offer oclif as open-source. As such, please review our project ",(0,n.jsx)(o.a,{href:"https://github.com/salesforce/oss-template/blob/master/CODE_OF_CONDUCT.md",children:"Code of Conduct"}),". If you have any questions or concerns, please ",(0,n.jsx)(o.a,{href:"/docs/feedback",children:"contact us"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"work-tracking",children:"Work Tracking"}),"\n",(0,n.jsxs)(o.p,{children:["We use a ",(0,n.jsx)(o.a,{href:"https://github.com/orgs/oclif/projects/1",children:"GitHub Project board"})," to manage our work across all oclif repos. This board is used kanban style, in which, cards (i.e. work items) move left to right as they progress towards \u201cDone\u201d and higher priority cards sit towards the top of the columns, with lower priority cards sitting further below."]}),"\n",(0,n.jsx)(o.h2,{id:"issues",children:"Issues"}),"\n",(0,n.jsxs)(o.p,{children:["Issues are made in their corresponding repo as appropriate. If you are unsure which repo an issue might belong to, make an ",(0,n.jsx)(o.a,{href:"https://github.com/oclif/oclif/issues",children:"issue in the oclif repo"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"We triage issues as we can, usually with a week of when it was created (unfortunately, we can make no commitment to when an issue will be triaged)."}),"\n",(0,n.jsx)(o.p,{children:"Issues triaged by an our team will be marked with one of the following labels :"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:"\u201cbug\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cenhancement\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cdocs\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cwont-fix\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cinvalid\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cduplicate\u201d"}),"\n"]}),"\n",(0,n.jsx)(o.p,{children:"An issue will be considered stale after a month has passed with no further feedback or input from the author after input from an oclif team member. Stale issues will be notified with a comment of its stale state and any actions needed to take to keep it alive."}),"\n",(0,n.jsx)(o.p,{children:"An issue will be closed if:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:"It has been fixed via a PR"}),"\n",(0,n.jsx)(o.li,{children:"Has a \u201cwont-fix\u201d, \u201cinvalid\u201d or \u201cduplicate\u201d label"}),"\n",(0,n.jsx)(o.li,{children:"A week has passed after a stale issue notification has been posted with no further feedback or input from the author"}),"\n"]}),"\n",(0,n.jsx)(o.h2,{id:"pull-requests",children:"Pull Requests"}),"\n",(0,n.jsx)(o.p,{children:"We review repo PRs as we can, usually with two weeks of when it was created (unfortunately, we can make no commitment to when a PR will be reviewed)."}),"\n",(0,n.jsx)(o.p,{children:"PRs reviewers may seek additional changes or clarifying input from the author as appropriate."}),"\n",(0,n.jsx)(o.p,{children:"Note: It is often more conducive to first open an issue and solicit feedback on possible solutions for your PR. We hate to see PR\u2019s we don\u2019t end up accepting and this helps to avoid that!"}),"\n",(0,n.jsx)(o.p,{children:"A PR will be considered stale after a month has passed with no further feedback or input from the author after input from an oclif team member. Stale PRs will be notified with a comment of its stale state and any actions needed to take to keep it alive."}),"\n",(0,n.jsx)(o.p,{children:"A PR will be closed if:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:"It has been merged"}),"\n",(0,n.jsx)(o.li,{children:"After a dialogue with the author informing them why the PR cannot be accepted"}),"\n",(0,n.jsx)(o.li,{children:"A week has passed after a stale PR notification has been posted with no further feedback or input from the author"}),"\n"]}),"\n",(0,n.jsx)(o.h2,{id:"deprecations",children:"Deprecations"}),"\n",(0,n.jsx)(o.p,{children:"oclif packages follow semantic versioning and therefore only deprecate features in new major version releases."}),"\n",(0,n.jsx)(o.p,{children:"In the exceptional case a deprecation needs to happen outside a new major version, we will notify users via our blog or, as appropriate, with deprecation warnings in the tooling itself."}),"\n",(0,n.jsx)(o.h2,{id:"blog-posts",children:"Blog Posts"}),"\n",(0,n.jsxs)(o.p,{children:["We aim to announce most features via ",(0,n.jsx)(o.a,{href:"/blog",children:"our blog"}),". Be sure to check back regularly to see new announcements!"]}),"\n",(0,n.jsx)(o.h2,{id:"feedback",children:"Feedback"}),"\n",(0,n.jsxs)(o.p,{children:["See our ",(0,n.jsx)(o.a,{href:"/docs/feedback",children:"Feedback page"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"updates-to-how-we-work",children:"Updates to How We Work"}),"\n",(0,n.jsx)(o.p,{children:"Please check back periodically to review any updates to this page."})]})}function h(e={}){const{wrapper:o}={...(0,t.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,o,s)=>{s.d(o,{R:()=>r,x:()=>a});var n=s(6540);const t={},i=n.createContext(t);function r(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),n.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2381],{6957:(e,o,s)=>{s.r(o),s.d(o,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var n=s(4848),t=s(8453);const i={title:"How We Work"},r=void 0,a={id:"how_we_work",title:"How We Work",description:"oclif is an open-source project built and maintained by Salesforce and an essential component of Salesforce's developer experiences, powering millions of users' CLIs a day via the Salesforce CLI, the Heroku CLI and others.",source:"@site/../docs/how_we_work.md",sourceDirName:".",slug:"/how_we_work",permalink:"/docs/how_we_work",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/how_we_work.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"How We Work"},sidebar:"docs",previous:{title:"Related Repositories",permalink:"/docs/related_repos"},next:{title:"Feedback",permalink:"/docs/feedback"}},l={},c=[{value:"Code of Conduct & Community Guidelines",id:"code-of-conduct--community-guidelines",level:2},{value:"Work Tracking",id:"work-tracking",level:2},{value:"Issues",id:"issues",level:2},{value:"Pull Requests",id:"pull-requests",level:2},{value:"Deprecations",id:"deprecations",level:2},{value:"Blog Posts",id:"blog-posts",level:2},{value:"Feedback",id:"feedback",level:2},{value:"Updates to How We Work",id:"updates-to-how-we-work",level:2}];function d(e){const o={a:"a",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(o.p,{children:["oclif is an open-source project built and maintained by Salesforce and an essential component of Salesforce's developer experiences, powering millions of users' CLIs a day via the Salesforce CLI, the Heroku CLI and ",(0,n.jsx)(o.a,{href:"https://www.npmjs.com/browse/depended/@oclif/core",children:"others"}),"."]}),"\n",(0,n.jsxs)(o.p,{children:["As an open-source project, ",(0,n.jsx)(o.a,{href:"https://github.com/oclif",children:"oclif repos live on GitHub"})," and are published to ",(0,n.jsx)(o.a,{href:"https://www.npmjs.com/search?q=oclif",children:"npmjs.com"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"code-of-conduct--community-guidelines",children:"Code of Conduct & Community Guidelines"}),"\n",(0,n.jsxs)(o.p,{children:["We are thrilled to offer oclif as open-source. As such, please review our project ",(0,n.jsx)(o.a,{href:"https://github.com/salesforce/oss-template/blob/master/CODE_OF_CONDUCT.md",children:"Code of Conduct"}),". If you have any questions or concerns, please ",(0,n.jsx)(o.a,{href:"/docs/feedback",children:"contact us"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"work-tracking",children:"Work Tracking"}),"\n",(0,n.jsxs)(o.p,{children:["We use a ",(0,n.jsx)(o.a,{href:"https://github.com/orgs/oclif/projects/1",children:"GitHub Project board"})," to manage our work across all oclif repos. This board is used kanban style, in which, cards (i.e. work items) move left to right as they progress towards \u201cDone\u201d and higher priority cards sit towards the top of the columns, with lower priority cards sitting further below."]}),"\n",(0,n.jsx)(o.h2,{id:"issues",children:"Issues"}),"\n",(0,n.jsxs)(o.p,{children:["Issues are made in their corresponding repo as appropriate. If you are unsure which repo an issue might belong to, make an ",(0,n.jsx)(o.a,{href:"https://github.com/oclif/oclif/issues",children:"issue in the oclif repo"}),"."]}),"\n",(0,n.jsx)(o.p,{children:"We triage issues as we can, usually with a week of when it was created (unfortunately, we can make no commitment to when an issue will be triaged)."}),"\n",(0,n.jsx)(o.p,{children:"Issues triaged by an our team will be marked with one of the following labels :"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:"\u201cbug\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cenhancement\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cdocs\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cwont-fix\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cinvalid\u201d"}),"\n",(0,n.jsx)(o.li,{children:"\u201cduplicate\u201d"}),"\n"]}),"\n",(0,n.jsx)(o.p,{children:"An issue will be considered stale after a month has passed with no further feedback or input from the author after input from an oclif team member. Stale issues will be notified with a comment of its stale state and any actions needed to take to keep it alive."}),"\n",(0,n.jsx)(o.p,{children:"An issue will be closed if:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:"It has been fixed via a PR"}),"\n",(0,n.jsx)(o.li,{children:"Has a \u201cwont-fix\u201d, \u201cinvalid\u201d or \u201cduplicate\u201d label"}),"\n",(0,n.jsx)(o.li,{children:"A week has passed after a stale issue notification has been posted with no further feedback or input from the author"}),"\n"]}),"\n",(0,n.jsx)(o.h2,{id:"pull-requests",children:"Pull Requests"}),"\n",(0,n.jsx)(o.p,{children:"We review repo PRs as we can, usually with two weeks of when it was created (unfortunately, we can make no commitment to when a PR will be reviewed)."}),"\n",(0,n.jsx)(o.p,{children:"PRs reviewers may seek additional changes or clarifying input from the author as appropriate."}),"\n",(0,n.jsx)(o.p,{children:"Note: It is often more conducive to first open an issue and solicit feedback on possible solutions for your PR. We hate to see PR\u2019s we don\u2019t end up accepting and this helps to avoid that!"}),"\n",(0,n.jsx)(o.p,{children:"A PR will be considered stale after a month has passed with no further feedback or input from the author after input from an oclif team member. Stale PRs will be notified with a comment of its stale state and any actions needed to take to keep it alive."}),"\n",(0,n.jsx)(o.p,{children:"A PR will be closed if:"}),"\n",(0,n.jsxs)(o.ul,{children:["\n",(0,n.jsx)(o.li,{children:"It has been merged"}),"\n",(0,n.jsx)(o.li,{children:"After a dialogue with the author informing them why the PR cannot be accepted"}),"\n",(0,n.jsx)(o.li,{children:"A week has passed after a stale PR notification has been posted with no further feedback or input from the author"}),"\n"]}),"\n",(0,n.jsx)(o.h2,{id:"deprecations",children:"Deprecations"}),"\n",(0,n.jsx)(o.p,{children:"oclif packages follow semantic versioning and therefore only deprecate features in new major version releases."}),"\n",(0,n.jsx)(o.p,{children:"In the exceptional case a deprecation needs to happen outside a new major version, we will notify users via our blog or, as appropriate, with deprecation warnings in the tooling itself."}),"\n",(0,n.jsx)(o.h2,{id:"blog-posts",children:"Blog Posts"}),"\n",(0,n.jsxs)(o.p,{children:["We aim to announce most features via ",(0,n.jsx)(o.a,{href:"/blog",children:"our blog"}),". Be sure to check back regularly to see new announcements!"]}),"\n",(0,n.jsx)(o.h2,{id:"feedback",children:"Feedback"}),"\n",(0,n.jsxs)(o.p,{children:["See our ",(0,n.jsx)(o.a,{href:"/docs/feedback",children:"Feedback page"}),"."]}),"\n",(0,n.jsx)(o.h2,{id:"updates-to-how-we-work",children:"Updates to How We Work"}),"\n",(0,n.jsx)(o.p,{children:"Please check back periodically to review any updates to this page."})]})}function h(e={}){const{wrapper:o}={...(0,t.R)(),...e.components};return o?(0,n.jsx)(o,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,o,s)=>{s.d(o,{R:()=>r,x:()=>a});var n=s(6540);const t={},i=n.createContext(t);function r(e){const o=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),n.createElement(i.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b4a95747.e4ee3a79.js b/assets/js/b4a95747.8bdd8694.js similarity index 95% rename from assets/js/b4a95747.e4ee3a79.js rename to assets/js/b4a95747.8bdd8694.js index d9e715df..a285b145 100644 --- a/assets/js/b4a95747.e4ee3a79.js +++ b/assets/js/b4a95747.8bdd8694.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8908],{3424:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>l,metadata:()=>c,toc:()=>i});var t=o(4848),s=o(8453);const l={title:"JSON"},r=void 0,c={id:"json",title:"JSON",description:"If you want to use the --json flag to return JSON output to the user, then you can set the enableJsonFlag property on the Command class.",source:"@site/../docs/json.md",sourceDirName:".",slug:"/json",permalink:"/docs/json",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/json.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"JSON"},sidebar:"docs",previous:{title:"Error Handling",permalink:"/docs/error_handling"},next:{title:"Release",permalink:"/docs/releasing"}},a={},i=[];function d(e){const n={code:"code",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["If you want to use the ",(0,t.jsx)(n.code,{children:"--json"})," flag to return JSON output to the user, then you can set the ",(0,t.jsx)(n.code,{children:"enableJsonFlag"})," property on the ",(0,t.jsx)(n.code,{children:"Command"})," class."]}),"\n",(0,t.jsxs)(n.p,{children:["When this property is set and the user supplies the ",(0,t.jsx)(n.code,{children:"--json"})," flag, the command will suppress all logs and instead log the return value to the console in JSON format. ",(0,t.jsx)(n.strong,{children:"Note"})," log suppression will only work if you use the logging methods on the ",(0,t.jsx)(n.code,{children:"Command"})," class instance. In other words, ",(0,t.jsx)(n.code,{children:"this.log"})," will be automatically suppressed but ",(0,t.jsx)(n.code,{children:"console.log"})," will not be."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Command} from '@oclif/core'\nexport class HelloCommand extends Command {\n public static enableJsonFlag = true\n public async run(): Promise<{ message: string }> {\n console.log('hello, world!')\n return { message: 'hello, world!' }\n }\n}\n\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"$ my-cli hello\nhello, world!\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'$ my-cli hello --json\n{\n "message": "hello, world!"\n}\n'})})]})}function u(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:()=>r,x:()=>c});var t=o(6540);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.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(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[8908],{3424:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>l,metadata:()=>c,toc:()=>i});var t=o(4848),s=o(8453);const l={title:"JSON"},r=void 0,c={id:"json",title:"JSON",description:"If you want to use the --json flag to return JSON output to the user, then you can set the enableJsonFlag property on the Command class.",source:"@site/../docs/json.md",sourceDirName:".",slug:"/json",permalink:"/docs/json",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/json.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"JSON"},sidebar:"docs",previous:{title:"Error Handling",permalink:"/docs/error_handling"},next:{title:"Release",permalink:"/docs/releasing"}},a={},i=[];function d(e){const n={code:"code",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(n.p,{children:["If you want to use the ",(0,t.jsx)(n.code,{children:"--json"})," flag to return JSON output to the user, then you can set the ",(0,t.jsx)(n.code,{children:"enableJsonFlag"})," property on the ",(0,t.jsx)(n.code,{children:"Command"})," class."]}),"\n",(0,t.jsxs)(n.p,{children:["When this property is set and the user supplies the ",(0,t.jsx)(n.code,{children:"--json"})," flag, the command will suppress all logs and instead log the return value to the console in JSON format. ",(0,t.jsx)(n.strong,{children:"Note"})," log suppression will only work if you use the logging methods on the ",(0,t.jsx)(n.code,{children:"Command"})," class instance. In other words, ",(0,t.jsx)(n.code,{children:"this.log"})," will be automatically suppressed but ",(0,t.jsx)(n.code,{children:"console.log"})," will not be."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Command} from '@oclif/core'\nexport class HelloCommand extends Command {\n public static enableJsonFlag = true\n public async run(): Promise<{ message: string }> {\n console.log('hello, world!')\n return { message: 'hello, world!' }\n }\n}\n\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"$ my-cli hello\nhello, world!\n"})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'$ my-cli hello --json\n{\n "message": "hello, world!"\n}\n'})})]})}function u(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:()=>r,x:()=>c});var t=o(6540);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.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(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c5890d18.2ec84b3e.js b/assets/js/c5890d18.1f021986.js similarity index 98% rename from assets/js/c5890d18.2ec84b3e.js rename to assets/js/c5890d18.1f021986.js index b8ee060e..07124313 100644 --- a/assets/js/c5890d18.2ec84b3e.js +++ b/assets/js/c5890d18.1f021986.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5069],{1588:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>a,frontMatter:()=>o,metadata:()=>r,toc:()=>c});var t=s(4848),i=s(8453);const o={title:"Themes"},l=void 0,r={id:"themes",title:"Themes",description:"oclif supports themes that users can either define for themselves or select from a variety of themes you ship with your CLI.",source:"@site/../docs/themes.md",sourceDirName:".",slug:"/themes",permalink:"/docs/themes",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/themes.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Themes"},sidebar:"docs",previous:{title:"ESM",permalink:"/docs/esm"},next:{title:"Examples",permalink:"/docs/examples"}},d={},c=[{value:"theme.json",id:"themejson",level:2},{value:"Supported Theme Properties",id:"supported-theme-properties",level:3},{value:"Disabling Themes",id:"disabling-themes",level:2},{value:"Extending Themes",id:"extending-themes",level:2}];function h(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"oclif supports themes that users can either define for themselves or select from a variety of themes you ship with your CLI."}),"\n",(0,t.jsxs)(n.p,{children:["By default, the theme only applies to help output but you can extend the theme for your own purposes if you want. See ",(0,t.jsx)(n.a,{href:"#extending-themes",children:"Extending Themes"})," section below."]}),"\n",(0,t.jsx)(n.h2,{id:"themejson",children:"theme.json"}),"\n",(0,t.jsxs)(n.p,{children:["By default oclif will read themes from ",(0,t.jsx)(n.code,{children:"~/.config//theme.json"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"This file takes the following shape:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "bin": "white",\n "command": "cyan",\n "commandSummary": "white",\n "dollarSign": "white",\n "flag": "white",\n "flagDefaultValue": "blue",\n "flagOptions": "white",\n "flagRequired": "red",\n "flagSeparator": "white",\n "sectionDescription": "white",\n "sectionHeader": "underline",\n "topic": "white",\n "version": "white"\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"supported-theme-properties",children:"Supported Theme Properties"}),"\n",(0,t.jsx)(n.p,{children:"As mentioned, the theme only applies to help output by default. The following properties can be used:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"alias"}),": the aliases under the ",(0,t.jsx)(n.code,{children:"ALIASES"})," section"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"bin"}),": the name of your CLI's executable (e.g. ",(0,t.jsx)(n.code,{children:"sf"}),", ",(0,t.jsx)(n.code,{children:"heroku"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"command"}),": the command's name"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"commandSummary"}),": the command's summary"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"dollarSign"}),": the ",(0,t.jsx)(n.code,{children:"$"})," printed before ",(0,t.jsx)(n.code,{children:"examples"})," and ",(0,t.jsx)(n.code,{children:"usage"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flag"}),": flag names and short characters"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagDefaultValue"}),": the ",(0,t.jsx)(n.code,{children:"[default: X]"})," shown on flags with a default"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagOptions"}),": the valid options for a flag"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagRequired"}),": the ",(0,t.jsx)(n.code,{children:"(required)"})," that shows on required flags"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagSeparator"}),": the ",(0,t.jsx)(n.code,{children:","})," that separates the short char and long flag names (e.g. ",(0,t.jsx)(n.code,{children:"-f, --foo"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"sectionDescription"}),": the text inside of each section (e.g. everything under ",(0,t.jsx)(n.code,{children:"DESCRIPTION"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"sectionHeader"}),": the section header (e.g. ",(0,t.jsx)(n.code,{children:"DESCRIPTION"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"topic"}),": the topics under the ",(0,t.jsx)(n.code,{children:"TOPICS"})," section"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"version"}),": the ",(0,t.jsx)(n.code,{children:"VERSION"})," section that shows under the root help (e.g. ",(0,t.jsx)(n.code,{children:"sf --help"}),")"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"The values for each of these must be one of the following:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["a hex code, e.g. ",(0,t.jsx)(n.code,{children:"#FF0000"})]}),"\n",(0,t.jsxs)(n.li,{children:["a rgb, e.g. ",(0,t.jsx)(n.code,{children:"rgb(255,255,255)"})]}),"\n",(0,t.jsxs)(n.li,{children:["a style supported by ",(0,t.jsx)(n.code,{children:"chalk"})," (see ",(0,t.jsx)(n.a,{href:"https://github.com/chalk/chalk/#styles",children:"https://github.com/chalk/chalk/#styles"}),")"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Any invalid values will be ignored."}),"\n",(0,t.jsx)(n.h2,{id:"disabling-themes",children:"Disabling Themes"}),"\n",(0,t.jsxs)(n.p,{children:["Themes can be disabled by using ",(0,t.jsx)(n.code,{children:"_DISABLE_THEME"})," environment variable."]}),"\n",(0,t.jsx)(n.h2,{id:"extending-themes",children:"Extending Themes"}),"\n",(0,t.jsxs)(n.p,{children:["By default oclif only uses the theme for the help output but you can use the theme for other purposes if you desire. For instance maybe you'd like to log colorized ",(0,t.jsx)(n.code,{children:"info:"})," logs to the user during a command:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\n\nexport default class Hello extends Command {\n public async run(): Promise {\n this.info('starting process!')\n // do some stuff...\n this.info('still making progress!')\n // do some more stuff...\n this.info('process complete!')\n }\n\n public info(msg: string): void {\n this.log(ux.colorize(this.config.theme?.info, 'info:'), msg)\n }\n}\n"})})]})}function a(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>r});var t=s(6540);const i={},o=t.createContext(i);function l(e){const n=t.useContext(o);return t.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(i):e.components||i:l(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5069],{1588:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>a,frontMatter:()=>o,metadata:()=>r,toc:()=>c});var t=s(4848),i=s(8453);const o={title:"Themes"},l=void 0,r={id:"themes",title:"Themes",description:"oclif supports themes that users can either define for themselves or select from a variety of themes you ship with your CLI.",source:"@site/../docs/themes.md",sourceDirName:".",slug:"/themes",permalink:"/docs/themes",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/themes.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Themes"},sidebar:"docs",previous:{title:"ESM",permalink:"/docs/esm"},next:{title:"Examples",permalink:"/docs/examples"}},d={},c=[{value:"theme.json",id:"themejson",level:2},{value:"Supported Theme Properties",id:"supported-theme-properties",level:3},{value:"Disabling Themes",id:"disabling-themes",level:2},{value:"Extending Themes",id:"extending-themes",level:2}];function h(e){const n={a:"a",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"oclif supports themes that users can either define for themselves or select from a variety of themes you ship with your CLI."}),"\n",(0,t.jsxs)(n.p,{children:["By default, the theme only applies to help output but you can extend the theme for your own purposes if you want. See ",(0,t.jsx)(n.a,{href:"#extending-themes",children:"Extending Themes"})," section below."]}),"\n",(0,t.jsx)(n.h2,{id:"themejson",children:"theme.json"}),"\n",(0,t.jsxs)(n.p,{children:["By default oclif will read themes from ",(0,t.jsx)(n.code,{children:"~/.config//theme.json"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"This file takes the following shape:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "bin": "white",\n "command": "cyan",\n "commandSummary": "white",\n "dollarSign": "white",\n "flag": "white",\n "flagDefaultValue": "blue",\n "flagOptions": "white",\n "flagRequired": "red",\n "flagSeparator": "white",\n "sectionDescription": "white",\n "sectionHeader": "underline",\n "topic": "white",\n "version": "white"\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"supported-theme-properties",children:"Supported Theme Properties"}),"\n",(0,t.jsx)(n.p,{children:"As mentioned, the theme only applies to help output by default. The following properties can be used:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"alias"}),": the aliases under the ",(0,t.jsx)(n.code,{children:"ALIASES"})," section"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"bin"}),": the name of your CLI's executable (e.g. ",(0,t.jsx)(n.code,{children:"sf"}),", ",(0,t.jsx)(n.code,{children:"heroku"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"command"}),": the command's name"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"commandSummary"}),": the command's summary"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"dollarSign"}),": the ",(0,t.jsx)(n.code,{children:"$"})," printed before ",(0,t.jsx)(n.code,{children:"examples"})," and ",(0,t.jsx)(n.code,{children:"usage"})]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flag"}),": flag names and short characters"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagDefaultValue"}),": the ",(0,t.jsx)(n.code,{children:"[default: X]"})," shown on flags with a default"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagOptions"}),": the valid options for a flag"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagRequired"}),": the ",(0,t.jsx)(n.code,{children:"(required)"})," that shows on required flags"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"flagSeparator"}),": the ",(0,t.jsx)(n.code,{children:","})," that separates the short char and long flag names (e.g. ",(0,t.jsx)(n.code,{children:"-f, --foo"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"sectionDescription"}),": the text inside of each section (e.g. everything under ",(0,t.jsx)(n.code,{children:"DESCRIPTION"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"sectionHeader"}),": the section header (e.g. ",(0,t.jsx)(n.code,{children:"DESCRIPTION"}),")"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"topic"}),": the topics under the ",(0,t.jsx)(n.code,{children:"TOPICS"})," section"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"version"}),": the ",(0,t.jsx)(n.code,{children:"VERSION"})," section that shows under the root help (e.g. ",(0,t.jsx)(n.code,{children:"sf --help"}),")"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"The values for each of these must be one of the following:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["a hex code, e.g. ",(0,t.jsx)(n.code,{children:"#FF0000"})]}),"\n",(0,t.jsxs)(n.li,{children:["a rgb, e.g. ",(0,t.jsx)(n.code,{children:"rgb(255,255,255)"})]}),"\n",(0,t.jsxs)(n.li,{children:["a style supported by ",(0,t.jsx)(n.code,{children:"chalk"})," (see ",(0,t.jsx)(n.a,{href:"https://github.com/chalk/chalk/#styles",children:"https://github.com/chalk/chalk/#styles"}),")"]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Any invalid values will be ignored."}),"\n",(0,t.jsx)(n.h2,{id:"disabling-themes",children:"Disabling Themes"}),"\n",(0,t.jsxs)(n.p,{children:["Themes can be disabled by using ",(0,t.jsx)(n.code,{children:"_DISABLE_THEME"})," environment variable."]}),"\n",(0,t.jsx)(n.h2,{id:"extending-themes",children:"Extending Themes"}),"\n",(0,t.jsxs)(n.p,{children:["By default oclif only uses the theme for the help output but you can use the theme for other purposes if you desire. For instance maybe you'd like to log colorized ",(0,t.jsx)(n.code,{children:"info:"})," logs to the user during a command:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"import {Command, ux} from '@oclif/core'\n\nexport default class Hello extends Command {\n public async run(): Promise {\n this.info('starting process!')\n // do some stuff...\n this.info('still making progress!')\n // do some more stuff...\n this.info('process complete!')\n }\n\n public info(msg: string): void {\n this.log(ux.colorize(this.config.theme?.info, 'info:'), msg)\n }\n}\n"})})]})}function a(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>l,x:()=>r});var t=s(6540);const i={},o=t.createContext(i);function l(e){const n=t.useContext(o);return t.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(i):e.components||i:l(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c81fd975.0551bf12.js b/assets/js/c81fd975.02a85bfa.js similarity index 99% rename from assets/js/c81fd975.0551bf12.js rename to assets/js/c81fd975.02a85bfa.js index d04afc2f..833a3238 100644 --- a/assets/js/c81fd975.0551bf12.js +++ b/assets/js/c81fd975.02a85bfa.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[218],{4240:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>i,metadata:()=>a,toc:()=>h});var o=n(4848),s=n(8453);const i={title:"Testing"},r=void 0,a={id:"testing",title:"Testing",description:"Testing in oclif can be done with any testing framework. You can run commands with MyCommand.run() which returns a promise you can wait on.",source:"@site/../docs/testing.md",sourceDirName:".",slug:"/testing",permalink:"/docs/testing",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/testing.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Testing"},sidebar:"docs",previous:{title:"Release",permalink:"/docs/releasing"},next:{title:"Running Commands Programmatically",permalink:"/docs/running_programmatically"}},c={},h=[{value:"stdout/stderr",id:"stdoutstderr",level:2},{value:"Code Coverage",id:"code-coverage",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["Testing in oclif can be done with any testing framework. You can run commands with ",(0,o.jsx)(t.code,{children:"MyCommand.run()"})," which returns a promise you can wait on."]}),"\n",(0,o.jsxs)(t.p,{children:["There are common tasks however when writing CLI tools. For this, we have a conventional set of tools that we suggest using to test your CLI. These are based on ",(0,o.jsx)(t.a,{href:"https://mochajs.org",children:"mocha"})," and ",(0,o.jsx)(t.a,{href:"https://github.com/jdxcode/fancy-test",children:"fancy-test"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Mocha is the top JavaScript testing framework and a solid choice for any project. fancy-test is a tool we developed that builds on top of mocha to make it easy to repeat patterns and write concise mocha tests. There is also a library ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/test",children:"@oclif/test"})," that extends fancy-test with helpers specific to testing oclif CLIs. These are things like running a command or hook or checking if an exit status code is set, for example."]}),"\n",(0,o.jsxs)(t.p,{children:["Any CLI built with oclif will come preloaded with these tools and an example test that should work out of the box with ",(0,o.jsx)(t.code,{children:"npm test"})," or ",(0,o.jsx)(t.code,{children:"yarn test"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["As an example, let's look at the ",(0,o.jsx)(t.code,{children:"heroku whoami"})," command which makes an API call to get the current logged in user. If the user is not logged in, it exits with status 100. (This is a simplified example, here is ",(0,o.jsx)(t.a,{href:"https://github.com/heroku/heroku-cli-plugin-auth",children:"the actual code"}),".)"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"src/commands/whoami.ts"})}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-js",children:"import Command from '@heroku-cli/command'\n\nexport class Whoami extends Command {\n async run() {\n try {\n let {body: account} = await this.heroku.get('/account')\n this.log(account.email)\n } catch (err) {\n if (err.statusCode === 401) {\n this.error('not logged in', {exit: 100})\n }\n throw err\n }\n }\n}\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Another common tool we like to use in testing oclif CLIs is ",(0,o.jsx)(t.a,{href:"https://github.com/node-nock/nock",children:"nock"}),". Install the ",(0,o.jsx)(t.code,{children:"nock"})," package as a devDependency."]}),"\n",(0,o.jsx)(t.p,{children:"Here is the test code"}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"test/commands/whoami.test.ts"})}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-typescript",children:"import {expect, test} from '@oclif/test'\n\ndescribe('auth:whoami', () => {\n test\n .nock('https://api.heroku.com', api => api\n .get('/account')\n // user is logged in, return their name\n .reply(200, {email: 'jeff@example.com'})\n )\n .stdout()\n .command(['auth:whoami'])\n .it('shows user email when logged in', ctx => {\n expect(ctx.stdout).to.equal('jeff@example.com\\n')\n })\n\n test\n .nock('https://api.heroku.com', api => api\n .get('/account')\n // HTTP 401 means the user is not logged in with valid credentials\n .reply(401)\n )\n .command(['auth:whoami'])\n // checks to ensure the command exits with status 100\n .exit(100)\n .it('exits with status 100 when not logged in')\n})\n"})}),"\n",(0,o.jsxs)(t.p,{children:["These tools are setup to not only mock out the stdout/stderr and HTTP calls, but they're setup to ensure they automatically reset after the test. A common issue we've had when building CLIs with simpler ",(0,o.jsx)(t.code,{children:"beforeEach/afterEach"})," filters is that if the ",(0,o.jsx)(t.code,{children:"afterEach"})," filters aren't setup correctly, a failing test can leave mocks around that make later tests fail. Using fancy-test, we avoid this problem and only have to declare our mocks once."]}),"\n",(0,o.jsxs)(t.p,{children:["For more on how to test with oclif, check out the docs for ",(0,o.jsx)(t.a,{href:"https://github.com/jdxcode/fancy-test",children:"fancy-test"})," and ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/test",children:"@oclif/test"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"stdoutstderr",children:"stdout/stderr"}),"\n",(0,o.jsxs)(t.p,{children:["The stdout/stderr mocks use ",(0,o.jsx)(t.a,{href:"https://github.com/jdxcode/stdout-stderr",children:"stdout-stderr"})," under the hood. This library can be used standalone if you'd prefer to use jest or want a different testing setup but still have the ability to mock out stdout and stderr."]}),"\n",(0,o.jsxs)(t.p,{children:["If you want to see the output but leave it mocked, you can either pass in ",(0,o.jsx)(t.code,{children:"{print: true}"})," to the options, or set ",(0,o.jsx)(t.code,{children:"TEST_OUTPUT=1"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"code-coverage",children:"Code Coverage"}),"\n",(0,o.jsxs)(t.p,{children:["Code coverage is provided automatically for JavaScript and TypeScript projects via ",(0,o.jsx)(t.a,{href:"https://npm.im/nyc",children:"nyc"}),". Just run ",(0,o.jsx)(t.code,{children:"yarn test"})," and it will show the code coverage. The coverage can optionally be sent to ",(0,o.jsx)(t.a,{href:"https://codecov.io",children:"codecov"})," in the CI scripts as well."]})]})}function l(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:()=>r,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function r(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:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[218],{4240:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>l,frontMatter:()=>i,metadata:()=>a,toc:()=>h});var o=n(4848),s=n(8453);const i={title:"Testing"},r=void 0,a={id:"testing",title:"Testing",description:"Testing in oclif can be done with any testing framework. You can run commands with MyCommand.run() which returns a promise you can wait on.",source:"@site/../docs/testing.md",sourceDirName:".",slug:"/testing",permalink:"/docs/testing",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/testing.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Testing"},sidebar:"docs",previous:{title:"Release",permalink:"/docs/releasing"},next:{title:"Running Commands Programmatically",permalink:"/docs/running_programmatically"}},c={},h=[{value:"stdout/stderr",id:"stdoutstderr",level:2},{value:"Code Coverage",id:"code-coverage",level:2}];function d(e){const t={a:"a",code:"code",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["Testing in oclif can be done with any testing framework. You can run commands with ",(0,o.jsx)(t.code,{children:"MyCommand.run()"})," which returns a promise you can wait on."]}),"\n",(0,o.jsxs)(t.p,{children:["There are common tasks however when writing CLI tools. For this, we have a conventional set of tools that we suggest using to test your CLI. These are based on ",(0,o.jsx)(t.a,{href:"https://mochajs.org",children:"mocha"})," and ",(0,o.jsx)(t.a,{href:"https://github.com/jdxcode/fancy-test",children:"fancy-test"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Mocha is the top JavaScript testing framework and a solid choice for any project. fancy-test is a tool we developed that builds on top of mocha to make it easy to repeat patterns and write concise mocha tests. There is also a library ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/test",children:"@oclif/test"})," that extends fancy-test with helpers specific to testing oclif CLIs. These are things like running a command or hook or checking if an exit status code is set, for example."]}),"\n",(0,o.jsxs)(t.p,{children:["Any CLI built with oclif will come preloaded with these tools and an example test that should work out of the box with ",(0,o.jsx)(t.code,{children:"npm test"})," or ",(0,o.jsx)(t.code,{children:"yarn test"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["As an example, let's look at the ",(0,o.jsx)(t.code,{children:"heroku whoami"})," command which makes an API call to get the current logged in user. If the user is not logged in, it exits with status 100. (This is a simplified example, here is ",(0,o.jsx)(t.a,{href:"https://github.com/heroku/heroku-cli-plugin-auth",children:"the actual code"}),".)"]}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"src/commands/whoami.ts"})}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-js",children:"import Command from '@heroku-cli/command'\n\nexport class Whoami extends Command {\n async run() {\n try {\n let {body: account} = await this.heroku.get('/account')\n this.log(account.email)\n } catch (err) {\n if (err.statusCode === 401) {\n this.error('not logged in', {exit: 100})\n }\n throw err\n }\n }\n}\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Another common tool we like to use in testing oclif CLIs is ",(0,o.jsx)(t.a,{href:"https://github.com/node-nock/nock",children:"nock"}),". Install the ",(0,o.jsx)(t.code,{children:"nock"})," package as a devDependency."]}),"\n",(0,o.jsx)(t.p,{children:"Here is the test code"}),"\n",(0,o.jsx)(t.p,{children:(0,o.jsx)(t.strong,{children:"test/commands/whoami.test.ts"})}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-typescript",children:"import {expect, test} from '@oclif/test'\n\ndescribe('auth:whoami', () => {\n test\n .nock('https://api.heroku.com', api => api\n .get('/account')\n // user is logged in, return their name\n .reply(200, {email: 'jeff@example.com'})\n )\n .stdout()\n .command(['auth:whoami'])\n .it('shows user email when logged in', ctx => {\n expect(ctx.stdout).to.equal('jeff@example.com\\n')\n })\n\n test\n .nock('https://api.heroku.com', api => api\n .get('/account')\n // HTTP 401 means the user is not logged in with valid credentials\n .reply(401)\n )\n .command(['auth:whoami'])\n // checks to ensure the command exits with status 100\n .exit(100)\n .it('exits with status 100 when not logged in')\n})\n"})}),"\n",(0,o.jsxs)(t.p,{children:["These tools are setup to not only mock out the stdout/stderr and HTTP calls, but they're setup to ensure they automatically reset after the test. A common issue we've had when building CLIs with simpler ",(0,o.jsx)(t.code,{children:"beforeEach/afterEach"})," filters is that if the ",(0,o.jsx)(t.code,{children:"afterEach"})," filters aren't setup correctly, a failing test can leave mocks around that make later tests fail. Using fancy-test, we avoid this problem and only have to declare our mocks once."]}),"\n",(0,o.jsxs)(t.p,{children:["For more on how to test with oclif, check out the docs for ",(0,o.jsx)(t.a,{href:"https://github.com/jdxcode/fancy-test",children:"fancy-test"})," and ",(0,o.jsx)(t.a,{href:"https://github.com/oclif/test",children:"@oclif/test"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"stdoutstderr",children:"stdout/stderr"}),"\n",(0,o.jsxs)(t.p,{children:["The stdout/stderr mocks use ",(0,o.jsx)(t.a,{href:"https://github.com/jdxcode/stdout-stderr",children:"stdout-stderr"})," under the hood. This library can be used standalone if you'd prefer to use jest or want a different testing setup but still have the ability to mock out stdout and stderr."]}),"\n",(0,o.jsxs)(t.p,{children:["If you want to see the output but leave it mocked, you can either pass in ",(0,o.jsx)(t.code,{children:"{print: true}"})," to the options, or set ",(0,o.jsx)(t.code,{children:"TEST_OUTPUT=1"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"code-coverage",children:"Code Coverage"}),"\n",(0,o.jsxs)(t.p,{children:["Code coverage is provided automatically for JavaScript and TypeScript projects via ",(0,o.jsx)(t.a,{href:"https://npm.im/nyc",children:"nyc"}),". Just run ",(0,o.jsx)(t.code,{children:"yarn test"})," and it will show the code coverage. The coverage can optionally be sent to ",(0,o.jsx)(t.a,{href:"https://codecov.io",children:"codecov"})," in the CI scripts as well."]})]})}function l(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:()=>r,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function r(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:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c94a68c1.6d6c394a.js b/assets/js/c94a68c1.1dcb0da4.js similarity index 98% rename from assets/js/c94a68c1.6d6c394a.js rename to assets/js/c94a68c1.1dcb0da4.js index 454ae92e..a0fb0ca8 100644 --- a/assets/js/c94a68c1.6d6c394a.js +++ b/assets/js/c94a68c1.1dcb0da4.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9604],{2391:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var r=t(4848),s=t(8453);const a={title:"Command Arguments"},i=void 0,o={id:"args",title:"Command Arguments",description:"Arguments are positional arguments passed to the command. For example, if this command was run with mycli arg1 arg2 it would be declared like this:",source:"@site/../docs/args.md",sourceDirName:".",slug:"/args",permalink:"/docs/args",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/args.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Command Arguments"},sidebar:"docs",previous:{title:"Commands",permalink:"/docs/commands"},next:{title:"Command Flags",permalink:"/docs/flags"}},c={},l=[];function d(e){const n={code:"code",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Arguments are positional arguments passed to the command. For example, if this command was run with ",(0,r.jsx)(n.code,{children:"mycli arg1 arg2"})," it would be declared like this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"import {Args, Command} from '@oclif/core'\n\nexport class MyCLI extends Command {\n static args = {\n firstArg: Args.string(),\n secondArg: Args.string(),\n }\n\n async run() {\n // can get args as an object\n const {args} = await this.parse(MyCLI)\n this.log(`running my command with args: ${args.firstArg}, ${args.secondArg}`)\n // can also get the args as an array\n const {argv} = await this.parse(MyCLI)\n this.log(`running my command with args: ${argv[0]}, ${argv[1]}`)\n }\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"Here are the options arguments can have:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"static args = {\n firstArg: Args.string(\n {\n name: 'file', // name of arg to show in help and reference with args[name]\n required: false, // make the arg required with `required: true`\n description: 'output file', // help description\n hidden: true, // hide this arg from help\n parse: input => 'output', // instead of the user input, return a different value\n default: 'world', // default value if no arg input\n options: ['a', 'b'], // only allow input to be from a discrete set\n }\n ),\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Here are the types of args that ",(0,r.jsx)(n.code,{children:"Args"})," exports:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"string"}),"\n",(0,r.jsx)(n.li,{children:"integer"}),"\n",(0,r.jsx)(n.li,{children:"boolean"}),"\n",(0,r.jsx)(n.li,{children:"url"}),"\n",(0,r.jsx)(n.li,{children:"file"}),"\n",(0,r.jsx)(n.li,{children:"directory"}),"\n",(0,r.jsx)(n.li,{children:"custom"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["For variable length arguments, disable argument validation with ",(0,r.jsx)(n.code,{children:"static strict = false"})," on the command."]})]})}function m(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>o});var r=t(6540);const s={},a=r.createContext(s);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9604],{2391:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>l});var r=t(4848),s=t(8453);const a={title:"Command Arguments"},i=void 0,o={id:"args",title:"Command Arguments",description:"Arguments are positional arguments passed to the command. For example, if this command was run with mycli arg1 arg2 it would be declared like this:",source:"@site/../docs/args.md",sourceDirName:".",slug:"/args",permalink:"/docs/args",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/args.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Command Arguments"},sidebar:"docs",previous:{title:"Commands",permalink:"/docs/commands"},next:{title:"Command Flags",permalink:"/docs/flags"}},c={},l=[];function d(e){const n={code:"code",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(n.p,{children:["Arguments are positional arguments passed to the command. For example, if this command was run with ",(0,r.jsx)(n.code,{children:"mycli arg1 arg2"})," it would be declared like this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-typescript",children:"import {Args, Command} from '@oclif/core'\n\nexport class MyCLI extends Command {\n static args = {\n firstArg: Args.string(),\n secondArg: Args.string(),\n }\n\n async run() {\n // can get args as an object\n const {args} = await this.parse(MyCLI)\n this.log(`running my command with args: ${args.firstArg}, ${args.secondArg}`)\n // can also get the args as an array\n const {argv} = await this.parse(MyCLI)\n this.log(`running my command with args: ${argv[0]}, ${argv[1]}`)\n }\n}\n"})}),"\n",(0,r.jsx)(n.p,{children:"Here are the options arguments can have:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"static args = {\n firstArg: Args.string(\n {\n name: 'file', // name of arg to show in help and reference with args[name]\n required: false, // make the arg required with `required: true`\n description: 'output file', // help description\n hidden: true, // hide this arg from help\n parse: input => 'output', // instead of the user input, return a different value\n default: 'world', // default value if no arg input\n options: ['a', 'b'], // only allow input to be from a discrete set\n }\n ),\n}\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Here are the types of args that ",(0,r.jsx)(n.code,{children:"Args"})," exports:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"string"}),"\n",(0,r.jsx)(n.li,{children:"integer"}),"\n",(0,r.jsx)(n.li,{children:"boolean"}),"\n",(0,r.jsx)(n.li,{children:"url"}),"\n",(0,r.jsx)(n.li,{children:"file"}),"\n",(0,r.jsx)(n.li,{children:"directory"}),"\n",(0,r.jsx)(n.li,{children:"custom"}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["For variable length arguments, disable argument validation with ",(0,r.jsx)(n.code,{children:"static strict = false"})," on the command."]})]})}function m(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>o});var r=t(6540);const s={},a=r.createContext(s);function i(e){const n=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d0e73d62.44497857.js b/assets/js/d0e73d62.2de45aa6.js similarity index 96% rename from assets/js/d0e73d62.44497857.js rename to assets/js/d0e73d62.2de45aa6.js index f71fceb1..66b51374 100644 --- a/assets/js/d0e73d62.44497857.js +++ b/assets/js/d0e73d62.2de45aa6.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7642],{6158:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>a});var n=s(4848),i=s(8453);const o={title:"NSIS Installer Customization"},r=void 0,c={id:"nsis-installer_customization",title:"NSIS Installer Customization",description:"Sometimes you need to verify some dependencies, ensure there are no conflicting CLIs installed, or do some other custom logic before installing your CLI. For npm-scenarios, simply specify a preinstall script. But Windows installers don't include this script. You must instead write your own nsis modification to do these checks. See where this custom script gets placed in the installer in the oclif/oclif repo.",source:"@site/../docs/nsis-installer_customization.md",sourceDirName:".",slug:"/nsis-installer_customization",permalink:"/docs/nsis-installer_customization",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/nsis-installer_customization.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"NSIS Installer Customization"},sidebar:"docs",previous:{title:"Aliases",permalink:"/docs/aliases"},next:{title:"Custom Base Class",permalink:"/docs/base_class"}},l={},a=[];function d(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["Sometimes you need to verify some dependencies, ensure there are no conflicting CLIs installed, or do some other custom logic before installing your CLI. For npm-scenarios, simply specify a ",(0,n.jsx)(t.code,{children:"preinstall"})," script. But Windows installers don't include this script. You must instead write your own nsis modification to do these checks. See where this custom script gets placed in the installer in the ",(0,n.jsx)(t.a,{href:"https://github.com/oclif/oclif/blob/b8d76af9290716ef69d8d1026f98041268306dfd/src/commands/pack/win.ts#L60",children:"oclif/oclif"})," repo."]}),"\n",(0,n.jsxs)(t.p,{children:["See how ",(0,n.jsx)(t.a,{href:"https://github.com/salesforcecli/cli",children:"Salesforce CLI"})," did this to prevent their new major version being installed on top of an older, and incompatible, version. In that ",(0,n.jsx)(t.code,{children:"package.json"}),", they specified an nsis installer like this:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-json",children:'\n{\n "name": "mycli",\n "version": "0.0.0",\n "description": "My CLI",\n "main": "bin/run.js",\n "bin": "./bin/run.js",\n "oclif": {\n "nsisCustomization": "scripts/nsis.nsi"\n }\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"And then their custom script was loaded into the installer during the packing phase of the CLI."})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>c});var n=s(6540);const i={},o=n.createContext(i);function r(e){const t=n.useContext(o);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(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[7642],{6158:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>a});var n=s(4848),i=s(8453);const o={title:"NSIS Installer Customization"},r=void 0,c={id:"nsis-installer_customization",title:"NSIS Installer Customization",description:"Sometimes you need to verify some dependencies, ensure there are no conflicting CLIs installed, or do some other custom logic before installing your CLI. For npm-scenarios, simply specify a preinstall script. But Windows installers don't include this script. You must instead write your own nsis modification to do these checks. See where this custom script gets placed in the installer in the oclif/oclif repo.",source:"@site/../docs/nsis-installer_customization.md",sourceDirName:".",slug:"/nsis-installer_customization",permalink:"/docs/nsis-installer_customization",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/nsis-installer_customization.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"NSIS Installer Customization"},sidebar:"docs",previous:{title:"Aliases",permalink:"/docs/aliases"},next:{title:"Custom Base Class",permalink:"/docs/base_class"}},l={},a=[];function d(e){const t={a:"a",code:"code",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.p,{children:["Sometimes you need to verify some dependencies, ensure there are no conflicting CLIs installed, or do some other custom logic before installing your CLI. For npm-scenarios, simply specify a ",(0,n.jsx)(t.code,{children:"preinstall"})," script. But Windows installers don't include this script. You must instead write your own nsis modification to do these checks. See where this custom script gets placed in the installer in the ",(0,n.jsx)(t.a,{href:"https://github.com/oclif/oclif/blob/b8d76af9290716ef69d8d1026f98041268306dfd/src/commands/pack/win.ts#L60",children:"oclif/oclif"})," repo."]}),"\n",(0,n.jsxs)(t.p,{children:["See how ",(0,n.jsx)(t.a,{href:"https://github.com/salesforcecli/cli",children:"Salesforce CLI"})," did this to prevent their new major version being installed on top of an older, and incompatible, version. In that ",(0,n.jsx)(t.code,{children:"package.json"}),", they specified an nsis installer like this:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-json",children:'\n{\n "name": "mycli",\n "version": "0.0.0",\n "description": "My CLI",\n "main": "bin/run.js",\n "bin": "./bin/run.js",\n "oclif": {\n "nsisCustomization": "scripts/nsis.nsi"\n }\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"And then their custom script was loaded into the installer during the packing phase of the CLI."})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>c});var n=s(6540);const i={},o=n.createContext(i);function r(e){const t=n.useContext(o);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(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d665a578.f44b824d.js b/assets/js/d665a578.a0187057.js similarity index 96% rename from assets/js/d665a578.f44b824d.js rename to assets/js/d665a578.a0187057.js index 7ce2aeae..ae3e1de6 100644 --- a/assets/js/d665a578.f44b824d.js +++ b/assets/js/d665a578.a0187057.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6337],{1973:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>i,contentTitle:()=>r,default:()=>p,frontMatter:()=>l,metadata:()=>a,toc:()=>c});var n=s(4848),o=s(8453);const l={title:"Examples"},r=void 0,a={id:"examples",title:"Examples",description:"Here are some examples to get an idea of how to use oclif in various setups.",source:"@site/../docs/examples.md",sourceDirName:".",slug:"/examples",permalink:"/docs/examples",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/examples.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Examples"},sidebar:"docs",previous:{title:"Themes",permalink:"/docs/themes"},next:{title:"External Links",permalink:"/docs/external_links"}},i={},c=[];function d(e){const t={a:"a",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"Here are some examples to get an idea of how to use oclif in various setups."}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/oclif/hello-world",children:"Hello World Example"})}),"\n"]})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>a});var n=s(6540);const o={},l=n.createContext(o);function r(e){const t=n.useContext(l);return n.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(o):e.components||o:r(e.components),n.createElement(l.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6337],{1973:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>i,contentTitle:()=>r,default:()=>p,frontMatter:()=>l,metadata:()=>a,toc:()=>c});var n=s(4848),o=s(8453);const l={title:"Examples"},r=void 0,a={id:"examples",title:"Examples",description:"Here are some examples to get an idea of how to use oclif in various setups.",source:"@site/../docs/examples.md",sourceDirName:".",slug:"/examples",permalink:"/docs/examples",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/examples.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Examples"},sidebar:"docs",previous:{title:"Themes",permalink:"/docs/themes"},next:{title:"External Links",permalink:"/docs/external_links"}},i={},c=[];function d(e){const t={a:"a",li:"li",p:"p",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.p,{children:"Here are some examples to get an idea of how to use oclif in various setups."}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.a,{href:"https://github.com/oclif/hello-world",children:"Hello World Example"})}),"\n"]})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>a});var n=s(6540);const o={},l=n.createContext(o);function r(e){const t=n.useContext(l);return n.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(o):e.components||o:r(e.components),n.createElement(l.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d9b0bdb4.243a840b.js b/assets/js/d9b0bdb4.3425f4a7.js similarity index 96% rename from assets/js/d9b0bdb4.243a840b.js rename to assets/js/d9b0bdb4.3425f4a7.js index 18ba34f4..a9891519 100644 --- a/assets/js/d9b0bdb4.243a840b.js +++ b/assets/js/d9b0bdb4.3425f4a7.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[908],{7949:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>i,contentTitle:()=>c,default:()=>d,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var s=o(4848),n=o(8453);const a={title:"Feedback"},c=void 0,r={id:"feedback",title:"Feedback",description:"If you have any suggestions or just want to let us know what you think of oclif, send us a message at alm-cli@salesforce.com or file an issue in our repos.",source:"@site/../docs/feedback.md",sourceDirName:".",slug:"/feedback",permalink:"/docs/feedback",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/feedback.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Feedback"},sidebar:"docs",previous:{title:"How We Work",permalink:"/docs/how_we_work"}},i={},l=[];function u(e){const t={a:"a",p:"p",...(0,n.R)(),...e.components};return(0,s.jsxs)(t.p,{children:["If you have any suggestions or just want to let us know what you think of oclif, send us a message at ",(0,s.jsx)(t.a,{href:"mailto:alm-cli@salesforce.com",children:"alm-cli@salesforce.com"})," or file an issue in ",(0,s.jsx)(t.a,{href:"https://github.com/oclif",children:"our repos"}),"."]})}function d(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>c,x:()=>r});var s=o(6540);const n={},a=s.createContext(n);function c(e){const t=s.useContext(a);return s.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(n):e.components||n:c(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[908],{7949:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>i,contentTitle:()=>c,default:()=>d,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var s=o(4848),n=o(8453);const a={title:"Feedback"},c=void 0,r={id:"feedback",title:"Feedback",description:"If you have any suggestions or just want to let us know what you think of oclif, send us a message at alm-cli@salesforce.com or file an issue in our repos.",source:"@site/../docs/feedback.md",sourceDirName:".",slug:"/feedback",permalink:"/docs/feedback",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/feedback.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Feedback"},sidebar:"docs",previous:{title:"How We Work",permalink:"/docs/how_we_work"}},i={},l=[];function u(e){const t={a:"a",p:"p",...(0,n.R)(),...e.components};return(0,s.jsxs)(t.p,{children:["If you have any suggestions or just want to let us know what you think of oclif, send us a message at ",(0,s.jsx)(t.a,{href:"mailto:alm-cli@salesforce.com",children:"alm-cli@salesforce.com"})," or file an issue in ",(0,s.jsx)(t.a,{href:"https://github.com/oclif",children:"our repos"}),"."]})}function d(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,o)=>{o.d(t,{R:()=>c,x:()=>r});var s=o(6540);const n={},a=s.createContext(n);function c(e){const t=s.useContext(a);return s.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(n):e.components||n:c(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/df1cd967.a69943d3.js b/assets/js/df1cd967.28611b4c.js similarity index 97% rename from assets/js/df1cd967.a69943d3.js rename to assets/js/df1cd967.28611b4c.js index a17d743a..1c7c706b 100644 --- a/assets/js/df1cd967.a69943d3.js +++ b/assets/js/df1cd967.28611b4c.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2977],{5391:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>i,contentTitle:()=>c,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>p});var s=t(4848),n=t(8453);const r={title:"Topic Separators"},c=void 0,a={id:"topic_separator",title:"Topic Separators",description:"By default, topics will be separated with colons, e.g. mycommand. However, you have the option to use spaces if you prefer, e.g. my awesome command.",source:"@site/../docs/topic_separator.md",sourceDirName:".",slug:"/topic_separator",permalink:"/docs/topic_separator",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/topic_separator.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Topic Separators"},sidebar:"docs",previous:{title:"Topics",permalink:"/docs/topics"},next:{title:"Hooks",permalink:"/docs/hooks"}},i={},p=[];function d(e){const o={code:"code",p:"p",pre:"pre",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(o.p,{children:["By default, topics will be separated with colons, e.g. ",(0,s.jsx)(o.code,{children:"my:awesome:command"}),". However, you have the option to use spaces if you prefer, e.g. ",(0,s.jsx)(o.code,{children:"my awesome command"}),"."]}),"\n",(0,s.jsxs)(o.p,{children:["To do this, simply set the ",(0,s.jsx)(o.code,{children:"topicSeparator"})," property in the oclif section of your package.json"]}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-json",children:'{\n "oclif": {\n "topicSeparator": " "\n }\n}\n'})}),"\n",(0,s.jsxs)(o.p,{children:["Currently colons (",(0,s.jsx)(o.code,{children:'":"'}),") and spaces (",(0,s.jsx)(o.code,{children:'" "'}),") are the only supported topic separators."]})]})}function l(e={}){const{wrapper:o}={...(0,n.R)(),...e.components};return o?(0,s.jsx)(o,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>c,x:()=>a});var s=t(6540);const n={},r=s.createContext(n);function c(e){const o=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),s.createElement(r.Provider,{value:o},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[2977],{5391:(e,o,t)=>{t.r(o),t.d(o,{assets:()=>i,contentTitle:()=>c,default:()=>l,frontMatter:()=>r,metadata:()=>a,toc:()=>p});var s=t(4848),n=t(8453);const r={title:"Topic Separators"},c=void 0,a={id:"topic_separator",title:"Topic Separators",description:"By default, topics will be separated with colons, e.g. mycommand. However, you have the option to use spaces if you prefer, e.g. my awesome command.",source:"@site/../docs/topic_separator.md",sourceDirName:".",slug:"/topic_separator",permalink:"/docs/topic_separator",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/topic_separator.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Topic Separators"},sidebar:"docs",previous:{title:"Topics",permalink:"/docs/topics"},next:{title:"Hooks",permalink:"/docs/hooks"}},i={},p=[];function d(e){const o={code:"code",p:"p",pre:"pre",...(0,n.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(o.p,{children:["By default, topics will be separated with colons, e.g. ",(0,s.jsx)(o.code,{children:"my:awesome:command"}),". However, you have the option to use spaces if you prefer, e.g. ",(0,s.jsx)(o.code,{children:"my awesome command"}),"."]}),"\n",(0,s.jsxs)(o.p,{children:["To do this, simply set the ",(0,s.jsx)(o.code,{children:"topicSeparator"})," property in the oclif section of your package.json"]}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-json",children:'{\n "oclif": {\n "topicSeparator": " "\n }\n}\n'})}),"\n",(0,s.jsxs)(o.p,{children:["Currently colons (",(0,s.jsx)(o.code,{children:'":"'}),") and spaces (",(0,s.jsx)(o.code,{children:'" "'}),") are the only supported topic separators."]})]})}function l(e={}){const{wrapper:o}={...(0,n.R)(),...e.components};return o?(0,s.jsx)(o,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,o,t)=>{t.d(o,{R:()=>c,x:()=>a});var s=t(6540);const n={},r=s.createContext(n);function c(e){const o=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),s.createElement(r.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e360e27f.e043c1c2.js b/assets/js/e360e27f.158cd50e.js similarity index 97% rename from assets/js/e360e27f.e043c1c2.js rename to assets/js/e360e27f.158cd50e.js index d9013049..eab005d0 100644 --- a/assets/js/e360e27f.e043c1c2.js +++ b/assets/js/e360e27f.158cd50e.js @@ -1 +1 @@ -"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[191],{8504:(n,i,e)=>{e.r(i),e.d(i,{assets:()=>u,contentTitle:()=>t,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var l=e(4848),o=e(8453);const s={title:"Plugins"},t=void 0,c={id:"plugins",title:"Plugins",description:"Plugins are a great way to offer experimental functionality, allow users to extend your CLI, break up a CLI into modular components, or share functionality between CLIs.",source:"@site/../docs/plugins.md",sourceDirName:".",slug:"/plugins",permalink:"/docs/plugins",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/plugins.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1710860746,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{title:"Plugins"},sidebar:"docs",previous:{title:"Hooks",permalink:"/docs/hooks"},next:{title:"Help Classes",permalink:"/docs/help_classes"}},u={},a=[{value:"Useful Plugins",id:"useful-plugins",level:2},{value:"Community Plugins",id:"community-plugins",level:2},{value:"Building your own plugin",id:"building-your-own-plugin",level:2}];function r(n){const i={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...n.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(i.p,{children:"Plugins are a great way to offer experimental functionality, allow users to extend your CLI, break up a CLI into modular components, or share functionality between CLIs."}),"\n",(0,l.jsxs)(i.p,{children:["Plugins can have commands or hooks just like a CLI. To add a plugin such as the ",(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-not-found",children:"not-found plugin"})," plugin, first add it to your CLI with ",(0,l.jsx)(i.code,{children:"yarn add @oclif/plugin-not-found"}),", then add the following to your ",(0,l.jsx)(i.code,{children:"package.json"}),":"]}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-js",children:'{\n "name": "mycli",\n "version": "0.0.0",\n // ...\n "oclif": {\n "plugins": [\n "@oclif/plugin-help",\n "@oclif/plugin-not-found"\n ]\n }\n}\n'})}),"\n",(0,l.jsxs)(i.p,{children:["If you want users to be able to install their own plugins into your CLI, use the ",(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-plugins",children:"plugins plugin"}),"."]}),"\n",(0,l.jsx)(i.h2,{id:"useful-plugins",children:"Useful Plugins"}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-not-found",children:"@oclif/plugin-not-found"}),' - Display a friendly "did you mean" message if a command is not found.']}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-plugins",children:"@oclif/plugin-plugins"})," - Allow users to add plugins to extend your CLI."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-update",children:"@oclif/plugin-update"})," - Add autoupdate support to the CLI."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-help",children:"@oclif/plugin-help"})," - Help plugin for oclif."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-warn-if-update-available",children:"@oclif/plugin-warn-if-update-available"})," - Show a warning message if user is running an out of date CLI."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-which",children:"@oclif/plugin-which"})," - Show which plugin a command comes from."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-commands",children:"@oclif/plugin-commands"})," - Add a ",(0,l.jsx)(i.code,{children:"commands"})," command to list all the commands."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-autocomplete",children:"@oclif/plugin-autocomplete"})," - Add bash/zsh autocomplete."]}),"\n"]}),"\n",(0,l.jsx)(i.h2,{id:"community-plugins",children:"Community Plugins"}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/natzcam/conf-cli",children:"conf-cli"})," - Adds a ",(0,l.jsx)(i.code,{children:"conf"})," command to share state/configuration between commands. Uses ",(0,l.jsx)(i.a,{href:"https://github.com/sindresorhus/conf",children:"sindresorhus/conf"}),"."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://www.npmjs.com/package/oclif-dynamic-commands",children:"dynamic-commands"})," - Load commands dynamically based on commands found under the current working directory."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/oclif.github.io/blob/docs/docs/plugins.md",children:"Add yours here"}),"!"]}),"\n"]}),"\n",(0,l.jsx)(i.h2,{id:"building-your-own-plugin",children:"Building your own plugin"}),"\n",(0,l.jsx)(i.p,{children:"Writing code for plugins is essentially the same as writing within a CLI. They can export 3 different types: commands, hooks, and other plugins."}),"\n",(0,l.jsxs)(i.p,{children:["Run ",(0,l.jsx)(i.code,{children:"npx oclif generate mynewplugin"})," to create a plugin in a new directory. This will come with a sample command called ",(0,l.jsx)(i.code,{children:"hello"}),"."]})]})}function d(n={}){const{wrapper:i}={...(0,o.R)(),...n.components};return i?(0,l.jsx)(i,{...n,children:(0,l.jsx)(r,{...n})}):r(n)}},8453:(n,i,e)=>{e.d(i,{R:()=>t,x:()=>c});var l=e(6540);const o={},s=l.createContext(o);function t(n){const i=l.useContext(s);return l.useMemo((function(){return"function"==typeof n?n(i):{...i,...n}}),[i,n])}function c(n){let i;return i=n.disableParentContext?"function"==typeof n.components?n.components(o):n.components||o:t(n.components),l.createElement(s.Provider,{value:i},n.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[191],{8504:(n,i,e)=>{e.r(i),e.d(i,{assets:()=>u,contentTitle:()=>t,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var l=e(4848),o=e(8453);const s={title:"Plugins"},t=void 0,c={id:"plugins",title:"Plugins",description:"Plugins are a great way to offer experimental functionality, allow users to extend your CLI, break up a CLI into modular components, or share functionality between CLIs.",source:"@site/../docs/plugins.md",sourceDirName:".",slug:"/plugins",permalink:"/docs/plugins",draft:!1,unlisted:!1,editUrl:"https://github.com/oclif/oclif.github.io/tree/docs/docs/../docs/plugins.md",tags:[],version:"current",lastUpdatedBy:"Mike Donnalley",lastUpdatedAt:1711121897,formattedLastUpdatedAt:"Mar 22, 2024",frontMatter:{title:"Plugins"},sidebar:"docs",previous:{title:"Hooks",permalink:"/docs/hooks"},next:{title:"Help Classes",permalink:"/docs/help_classes"}},u={},a=[{value:"Useful Plugins",id:"useful-plugins",level:2},{value:"Community Plugins",id:"community-plugins",level:2},{value:"Building your own plugin",id:"building-your-own-plugin",level:2}];function r(n){const i={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...n.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(i.p,{children:"Plugins are a great way to offer experimental functionality, allow users to extend your CLI, break up a CLI into modular components, or share functionality between CLIs."}),"\n",(0,l.jsxs)(i.p,{children:["Plugins can have commands or hooks just like a CLI. To add a plugin such as the ",(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-not-found",children:"not-found plugin"})," plugin, first add it to your CLI with ",(0,l.jsx)(i.code,{children:"yarn add @oclif/plugin-not-found"}),", then add the following to your ",(0,l.jsx)(i.code,{children:"package.json"}),":"]}),"\n",(0,l.jsx)(i.pre,{children:(0,l.jsx)(i.code,{className:"language-js",children:'{\n "name": "mycli",\n "version": "0.0.0",\n // ...\n "oclif": {\n "plugins": [\n "@oclif/plugin-help",\n "@oclif/plugin-not-found"\n ]\n }\n}\n'})}),"\n",(0,l.jsxs)(i.p,{children:["If you want users to be able to install their own plugins into your CLI, use the ",(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-plugins",children:"plugins plugin"}),"."]}),"\n",(0,l.jsx)(i.h2,{id:"useful-plugins",children:"Useful Plugins"}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-not-found",children:"@oclif/plugin-not-found"}),' - Display a friendly "did you mean" message if a command is not found.']}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-plugins",children:"@oclif/plugin-plugins"})," - Allow users to add plugins to extend your CLI."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-update",children:"@oclif/plugin-update"})," - Add autoupdate support to the CLI."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-help",children:"@oclif/plugin-help"})," - Help plugin for oclif."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-warn-if-update-available",children:"@oclif/plugin-warn-if-update-available"})," - Show a warning message if user is running an out of date CLI."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-which",children:"@oclif/plugin-which"})," - Show which plugin a command comes from."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-commands",children:"@oclif/plugin-commands"})," - Add a ",(0,l.jsx)(i.code,{children:"commands"})," command to list all the commands."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/plugin-autocomplete",children:"@oclif/plugin-autocomplete"})," - Add bash/zsh autocomplete."]}),"\n"]}),"\n",(0,l.jsx)(i.h2,{id:"community-plugins",children:"Community Plugins"}),"\n",(0,l.jsxs)(i.ul,{children:["\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/natzcam/conf-cli",children:"conf-cli"})," - Adds a ",(0,l.jsx)(i.code,{children:"conf"})," command to share state/configuration between commands. Uses ",(0,l.jsx)(i.a,{href:"https://github.com/sindresorhus/conf",children:"sindresorhus/conf"}),"."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://www.npmjs.com/package/oclif-dynamic-commands",children:"dynamic-commands"})," - Load commands dynamically based on commands found under the current working directory."]}),"\n",(0,l.jsxs)(i.li,{children:[(0,l.jsx)(i.a,{href:"https://github.com/oclif/oclif.github.io/blob/docs/docs/plugins.md",children:"Add yours here"}),"!"]}),"\n"]}),"\n",(0,l.jsx)(i.h2,{id:"building-your-own-plugin",children:"Building your own plugin"}),"\n",(0,l.jsx)(i.p,{children:"Writing code for plugins is essentially the same as writing within a CLI. They can export 3 different types: commands, hooks, and other plugins."}),"\n",(0,l.jsxs)(i.p,{children:["Run ",(0,l.jsx)(i.code,{children:"npx oclif generate mynewplugin"})," to create a plugin in a new directory. This will come with a sample command called ",(0,l.jsx)(i.code,{children:"hello"}),"."]})]})}function d(n={}){const{wrapper:i}={...(0,o.R)(),...n.components};return i?(0,l.jsx)(i,{...n,children:(0,l.jsx)(r,{...n})}):r(n)}},8453:(n,i,e)=>{e.d(i,{R:()=>t,x:()=>c});var l=e(6540);const o={},s=l.createContext(o);function t(n){const i=l.useContext(s);return l.useMemo((function(){return"function"==typeof n?n(i):{...i,...n}}),[i,n])}function c(n){let i;return i=n.disableParentContext?"function"==typeof n.components?n.components(o):n.components||o:t(n.components),l.createElement(s.Provider,{value:i},n.children)}}}]); \ No newline at end of file diff --git a/assets/js/e3703649.0f308291.js b/assets/js/e3703649.deb238ea.js similarity index 99% rename from assets/js/e3703649.0f308291.js rename to assets/js/e3703649.deb238ea.js index 5dae5ed6..f2598482 100644 --- a/assets/js/e3703649.0f308291.js +++ b/assets/js/e3703649.deb238ea.js @@ -1 +1 @@ -"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:1710860746,formattedLastUpdatedAt:"Mar 19, 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 +"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;i=f)&&Object.keys(r.O).every((e=>r.O[e](c[o])))?c.splice(o--,1):(t=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[c,d,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,c({}),c([]),c(c)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=c(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var c in a)r.o(a,c)&&!r.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,c)=>(r.f[c](e,a),a)),[])),r.u=e=>"assets/js/"+({55:"3e452c7e",125:"8705a681",172:"3bc14f20",191:"e360e27f",218:"c81fd975",285:"6de0e435",407:"b439faf3",411:"5f98988e",607:"f182954c",844:"03abeb31",908:"d9b0bdb4",1035:"4fdccd00",1139:"28395ba4",1427:"2a33acc4",1595:"a96ec439",1777:"53e18611",1979:"c637b865",1991:"b2b675dd",2106:"253cd3dc",2138:"1a4e3797",2381:"b3cc73c6",2634:"c4f5d8e4",2711:"9e4087bc",2961:"6f3bb722",2977:"df1cd967",3056:"f85046f2",3249:"ccc49370",3454:"0b218a01",3651:"258a6413",3782:"1ed4142b",3868:"c4b40215",4059:"04855d6d",4119:"0085e091",4157:"958c0a42",4260:"30d74566",4295:"765c6b61",4711:"9eaa546a",5069:"c5890d18",5082:"1f61ef73",5483:"713bb917",5894:"b2f554cd",5924:"a92e169d",6122:"f905d0fe",6332:"3ba497c2",6337:"d665a578",6471:"104cbb75",6485:"49140ced",7071:"7bd58895",7098:"a7bd4aaa",7187:"35586d92",7199:"e2e9d59a",7386:"7b0e8dfa",7472:"814f3328",7642:"d0e73d62",7643:"a6aa9e1f",7777:"3042343a",7996:"32060389",8078:"03a88bad",8080:"19fd9079",8138:"bc0981ca",8161:"169e66bc",8204:"853133bb",8212:"935116ff",8401:"17896441",8467:"1d5c88f5",8581:"935f2afb",8664:"2f98ad87",8908:"b4a95747",8990:"5d5620c4",9e3:"2486267b",9036:"e3703649",9048:"a94703ab",9181:"f6c5328e",9409:"82247a8b",9604:"c94a68c1",9647:"5e95c892"}[e]||e)+"."+{55:"0139d8d2",125:"a24a496a",172:"69214213",191:"e043c1c2",218:"0551bf12",285:"047e5c30",407:"20c41093",411:"39b57c87",416:"b444750d",607:"53a8635a",844:"5415b57b",908:"243a840b",1035:"64bbde21",1139:"883753a5",1427:"376963de",1595:"53b19970",1777:"cbaa63c9",1979:"ea600c9b",1991:"b7e8cf7c",2106:"9ffd2ef4",2138:"eb1836aa",2237:"d1a6696c",2381:"473e1578",2634:"31dd602b",2711:"22abea8e",2961:"82eaa226",2977:"a69943d3",3056:"9fc26724",3249:"59e6173a",3454:"00c2d643",3651:"25eadca6",3782:"646b4f19",3868:"5a593349",4059:"9fadc1b6",4119:"d96359e9",4157:"1d740ba0",4260:"bf95441d",4295:"0fd2060a",4711:"5801dc53",5069:"2ec84b3e",5082:"ed364500",5463:"d6ba8b87",5483:"dbd2243e",5894:"a21b80b6",5924:"c9dc0b54",6122:"e4e807ba",6332:"2776bb8a",6337:"f44b824d",6471:"c7fb3ef1",6485:"5df72a3d",7071:"825ec359",7098:"a795c7ce",7187:"f1a1915a",7199:"c30a2429",7386:"f8398dac",7472:"924a4440",7642:"44497857",7643:"05773597",7777:"8ba035fd",7996:"1eb0ee8b",8078:"3fa9ada6",8080:"ac45505f",8138:"4fd4a77c",8161:"d97dd0dd",8204:"0473d247",8212:"7148886a",8401:"d4e8a563",8467:"1b5cf92d",8544:"aa238dd5",8581:"18fa4e0a",8664:"be46cc71",8908:"e4ee3a79",8913:"b6f04e6e",8990:"7d436f77",9e3:"f4424fc4",9036:"0f308291",9048:"f7743c53",9181:"c07cba91",9409:"a76eaf65",9462:"9f77d8a2",9604:"6d6c394a",9647:"305f062e"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},r.l=(e,a,c,f)=>{if(d[e])d[e].push(a);else{var b,t;if(void 0!==c)for(var o=document.getElementsByTagName("script"),n=0;n{b.onerror=b.onload=null,clearTimeout(u);var f=d[e];if(delete d[e],b.parentNode&&b.parentNode.removeChild(b),f&&f.forEach((e=>e(c))),a)return a(c)},u=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),t&&document.head.appendChild(b)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",32060389:"7996","3e452c7e":"55","8705a681":"125","3bc14f20":"172",e360e27f:"191",c81fd975:"218","6de0e435":"285",b439faf3:"407","5f98988e":"411",f182954c:"607","03abeb31":"844",d9b0bdb4:"908","4fdccd00":"1035","28395ba4":"1139","2a33acc4":"1427",a96ec439:"1595","53e18611":"1777",c637b865:"1979",b2b675dd:"1991","253cd3dc":"2106","1a4e3797":"2138",b3cc73c6:"2381",c4f5d8e4:"2634","9e4087bc":"2711","6f3bb722":"2961",df1cd967:"2977",f85046f2:"3056",ccc49370:"3249","0b218a01":"3454","258a6413":"3651","1ed4142b":"3782",c4b40215:"3868","04855d6d":"4059","0085e091":"4119","958c0a42":"4157","30d74566":"4260","765c6b61":"4295","9eaa546a":"4711",c5890d18:"5069","1f61ef73":"5082","713bb917":"5483",b2f554cd:"5894",a92e169d:"5924",f905d0fe:"6122","3ba497c2":"6332",d665a578:"6337","104cbb75":"6471","49140ced":"6485","7bd58895":"7071",a7bd4aaa:"7098","35586d92":"7187",e2e9d59a:"7199","7b0e8dfa":"7386","814f3328":"7472",d0e73d62:"7642",a6aa9e1f:"7643","3042343a":"7777","03a88bad":"8078","19fd9079":"8080",bc0981ca:"8138","169e66bc":"8161","853133bb":"8204","935116ff":"8212","1d5c88f5":"8467","935f2afb":"8581","2f98ad87":"8664",b4a95747:"8908","5d5620c4":"8990","2486267b":"9000",e3703649:"9036",a94703ab:"9048",f6c5328e:"9181","82247a8b":"9409",c94a68c1:"9604","5e95c892":"9647"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,c)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)c.push(d[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var f=new Promise(((c,f)=>d=e[a]=[c,f]));c.push(d[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(c=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var f=c&&("load"===c.type?"missing":c.type),b=c&&c.target&&c.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,c)=>{var d,f,[b,t,o]=c,n=0;if(b.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(c);n{"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;i=f)&&Object.keys(r.O).every((e=>r.O[e](c[o])))?c.splice(o--,1):(t=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[c,d,f]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},c=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var f=Object.create(null);r.r(f);var b={};a=a||[null,c({}),c([]),c(c)];for(var t=2&d&&e;"object"==typeof t&&!~a.indexOf(t);t=c(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(f,b),f},r.d=(e,a)=>{for(var c in a)r.o(a,c)&&!r.o(e,c)&&Object.defineProperty(e,c,{enumerable:!0,get:a[c]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,c)=>(r.f[c](e,a),a)),[])),r.u=e=>"assets/js/"+({55:"3e452c7e",125:"8705a681",172:"3bc14f20",191:"e360e27f",218:"c81fd975",285:"6de0e435",407:"b439faf3",411:"5f98988e",607:"f182954c",844:"03abeb31",908:"d9b0bdb4",1035:"4fdccd00",1139:"28395ba4",1427:"2a33acc4",1595:"a96ec439",1777:"53e18611",1979:"c637b865",1991:"b2b675dd",2106:"253cd3dc",2138:"1a4e3797",2381:"b3cc73c6",2634:"c4f5d8e4",2711:"9e4087bc",2961:"6f3bb722",2977:"df1cd967",3056:"f85046f2",3249:"ccc49370",3454:"0b218a01",3651:"258a6413",3782:"1ed4142b",3868:"c4b40215",4059:"04855d6d",4119:"0085e091",4157:"958c0a42",4260:"30d74566",4295:"765c6b61",4711:"9eaa546a",5069:"c5890d18",5082:"1f61ef73",5483:"713bb917",5894:"b2f554cd",5924:"a92e169d",6122:"f905d0fe",6332:"3ba497c2",6337:"d665a578",6471:"104cbb75",6485:"49140ced",7071:"7bd58895",7098:"a7bd4aaa",7187:"35586d92",7199:"e2e9d59a",7386:"7b0e8dfa",7472:"814f3328",7642:"d0e73d62",7643:"a6aa9e1f",7777:"3042343a",7996:"32060389",8078:"03a88bad",8080:"19fd9079",8138:"bc0981ca",8161:"169e66bc",8204:"853133bb",8212:"935116ff",8401:"17896441",8467:"1d5c88f5",8581:"935f2afb",8664:"2f98ad87",8908:"b4a95747",8990:"5d5620c4",9e3:"2486267b",9036:"e3703649",9048:"a94703ab",9181:"f6c5328e",9409:"82247a8b",9604:"c94a68c1",9647:"5e95c892"}[e]||e)+"."+{55:"747c7b5b",125:"eedb41eb",172:"69214213",191:"158cd50e",218:"02a85bfa",285:"047e5c30",407:"20c41093",411:"39b57c87",416:"b444750d",607:"67c31c13",844:"5f9309f2",908:"3425f4a7",1035:"64bbde21",1139:"883753a5",1427:"ed23e4e6",1595:"3b3c006e",1777:"174f50c6",1979:"ea600c9b",1991:"b7e8cf7c",2106:"9ffd2ef4",2138:"eb1836aa",2237:"d1a6696c",2381:"b180e5dd",2634:"31dd602b",2711:"22abea8e",2961:"36477967",2977:"28611b4c",3056:"9fc26724",3249:"59e6173a",3454:"de27cef5",3651:"15131eb9",3782:"a44c3e96",3868:"5a593349",4059:"9fadc1b6",4119:"d96359e9",4157:"1d740ba0",4260:"f5a0ed76",4295:"0fd2060a",4711:"45d375f7",5069:"1f021986",5082:"51af529c",5463:"d6ba8b87",5483:"cf149bb6",5894:"a21b80b6",5924:"82f135f1",6122:"2c295ea7",6332:"2776bb8a",6337:"a0187057",6471:"c2ce6e10",6485:"5df72a3d",7071:"bbd59ad7",7098:"a795c7ce",7187:"a74fcd5f",7199:"c30a2429",7386:"f8398dac",7472:"924a4440",7642:"2de45aa6",7643:"05773597",7777:"6b9057ed",7996:"cc2c1970",8078:"52baa0b3",8080:"0d5010f9",8138:"4fd4a77c",8161:"d97dd0dd",8204:"0473d247",8212:"dc866d9f",8401:"d4e8a563",8467:"1b5cf92d",8544:"aa238dd5",8581:"18fa4e0a",8664:"c0493a32",8908:"8bdd8694",8913:"b6f04e6e",8990:"aa5bafe0",9e3:"0ba0fb70",9036:"deb238ea",9048:"f7743c53",9181:"a958af26",9409:"de433149",9462:"9f77d8a2",9604:"1dcb0da4",9647:"305f062e"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},r.l=(e,a,c,f)=>{if(d[e])d[e].push(a);else{var b,t;if(void 0!==c)for(var o=document.getElementsByTagName("script"),n=0;n{b.onerror=b.onload=null,clearTimeout(u);var f=d[e];if(delete d[e],b.parentNode&&b.parentNode.removeChild(b),f&&f.forEach((e=>e(c))),a)return a(c)},u=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),t&&document.head.appendChild(b)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"8401",32060389:"7996","3e452c7e":"55","8705a681":"125","3bc14f20":"172",e360e27f:"191",c81fd975:"218","6de0e435":"285",b439faf3:"407","5f98988e":"411",f182954c:"607","03abeb31":"844",d9b0bdb4:"908","4fdccd00":"1035","28395ba4":"1139","2a33acc4":"1427",a96ec439:"1595","53e18611":"1777",c637b865:"1979",b2b675dd:"1991","253cd3dc":"2106","1a4e3797":"2138",b3cc73c6:"2381",c4f5d8e4:"2634","9e4087bc":"2711","6f3bb722":"2961",df1cd967:"2977",f85046f2:"3056",ccc49370:"3249","0b218a01":"3454","258a6413":"3651","1ed4142b":"3782",c4b40215:"3868","04855d6d":"4059","0085e091":"4119","958c0a42":"4157","30d74566":"4260","765c6b61":"4295","9eaa546a":"4711",c5890d18:"5069","1f61ef73":"5082","713bb917":"5483",b2f554cd:"5894",a92e169d:"5924",f905d0fe:"6122","3ba497c2":"6332",d665a578:"6337","104cbb75":"6471","49140ced":"6485","7bd58895":"7071",a7bd4aaa:"7098","35586d92":"7187",e2e9d59a:"7199","7b0e8dfa":"7386","814f3328":"7472",d0e73d62:"7642",a6aa9e1f:"7643","3042343a":"7777","03a88bad":"8078","19fd9079":"8080",bc0981ca:"8138","169e66bc":"8161","853133bb":"8204","935116ff":"8212","1d5c88f5":"8467","935f2afb":"8581","2f98ad87":"8664",b4a95747:"8908","5d5620c4":"8990","2486267b":"9000",e3703649:"9036",a94703ab:"9048",f6c5328e:"9181","82247a8b":"9409",c94a68c1:"9604","5e95c892":"9647"}[e]||e,r.p+r.u(e)},(()=>{var e={5354:0,1869:0};r.f.j=(a,c)=>{var d=r.o(e,a)?e[a]:void 0;if(0!==d)if(d)c.push(d[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var f=new Promise(((c,f)=>d=e[a]=[c,f]));c.push(d[2]=f);var b=r.p+r.u(a),t=new Error;r.l(b,(c=>{if(r.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var f=c&&("load"===c.type?"missing":c.type),b=c&&c.target&&c.target.src;t.message="Loading chunk "+a+" failed.\n("+f+": "+b+")",t.name="ChunkLoadError",t.type=f,t.request=b,d[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,c)=>{var d,f,[b,t,o]=c,n=0;if(b.some((a=>0!==e[a]))){for(d in t)r.o(t,d)&&(r.m[d]=t[d]);if(o)var i=o(r)}for(a&&a(c);n