@shopify/cli-kit 3.94.3 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +2 -2
  2. package/dist/private/node/api/headers.js +2 -2
  3. package/dist/private/node/api/headers.js.map +1 -1
  4. package/dist/private/node/conf-store.d.ts +3 -2
  5. package/dist/private/node/conf-store.js +3 -2
  6. package/dist/private/node/conf-store.js.map +1 -1
  7. package/dist/private/node/constants.d.ts +1 -1
  8. package/dist/private/node/constants.js +1 -1
  9. package/dist/private/node/constants.js.map +1 -1
  10. package/dist/private/node/ui/components/Alert.test.js +29 -0
  11. package/dist/private/node/ui/components/Alert.test.js.map +1 -1
  12. package/dist/private/node/ui/components/AutocompletePrompt.d.ts +8 -1
  13. package/dist/private/node/ui/components/AutocompletePrompt.js +3 -2
  14. package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
  15. package/dist/private/node/ui/components/AutocompletePrompt.test.js +16 -0
  16. package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
  17. package/dist/private/node/ui/components/FatalError.js +6 -1
  18. package/dist/private/node/ui/components/FatalError.js.map +1 -1
  19. package/dist/private/node/ui/components/FatalError.test.js +28 -0
  20. package/dist/private/node/ui/components/FatalError.test.js.map +1 -1
  21. package/dist/private/node/ui/components/Link.js +8 -4
  22. package/dist/private/node/ui/components/Link.js.map +1 -1
  23. package/dist/private/node/ui/components/Link.test.js +45 -0
  24. package/dist/private/node/ui/components/Link.test.js.map +1 -1
  25. package/dist/private/node/ui/components/TokenizedText.js +61 -2
  26. package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
  27. package/dist/private/node/ui/components/TokenizedText.test.js +109 -2
  28. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
  29. package/dist/public/common/string.js +22 -25
  30. package/dist/public/common/string.js.map +1 -1
  31. package/dist/public/common/version.d.ts +1 -1
  32. package/dist/public/common/version.js +1 -1
  33. package/dist/public/common/version.js.map +1 -1
  34. package/dist/public/node/base-command.js +23 -14
  35. package/dist/public/node/base-command.js.map +1 -1
  36. package/dist/public/node/cli-launcher.d.ts +2 -0
  37. package/dist/public/node/cli-launcher.js +7 -3
  38. package/dist/public/node/cli-launcher.js.map +1 -1
  39. package/dist/public/node/cli.d.ts +5 -1
  40. package/dist/public/node/cli.js +3 -3
  41. package/dist/public/node/cli.js.map +1 -1
  42. package/dist/public/node/context/local.d.ts +1 -8
  43. package/dist/public/node/context/local.js +34 -15
  44. package/dist/public/node/context/local.js.map +1 -1
  45. package/dist/public/node/custom-oclif-loader.d.ts +31 -0
  46. package/dist/public/node/custom-oclif-loader.js +45 -0
  47. package/dist/public/node/custom-oclif-loader.js.map +1 -0
  48. package/dist/public/node/error.d.ts +1 -1
  49. package/dist/public/node/error.js +1 -1
  50. package/dist/public/node/error.js.map +1 -1
  51. package/dist/public/node/fs.js +12 -16
  52. package/dist/public/node/fs.js.map +1 -1
  53. package/dist/public/node/git.js +9 -3
  54. package/dist/public/node/git.js.map +1 -1
  55. package/dist/public/node/hooks/postrun.d.ts +15 -0
  56. package/dist/public/node/hooks/postrun.js +75 -14
  57. package/dist/public/node/hooks/postrun.js.map +1 -1
  58. package/dist/public/node/hooks/prerun.d.ts +1 -1
  59. package/dist/public/node/hooks/prerun.js +17 -10
  60. package/dist/public/node/hooks/prerun.js.map +1 -1
  61. package/dist/public/node/import-extractor.js +4 -3
  62. package/dist/public/node/import-extractor.js.map +1 -1
  63. package/dist/public/node/is-global.d.ts +1 -1
  64. package/dist/public/node/is-global.js +27 -11
  65. package/dist/public/node/is-global.js.map +1 -1
  66. package/dist/public/node/monorail.d.ts +2 -1
  67. package/dist/public/node/monorail.js +1 -1
  68. package/dist/public/node/monorail.js.map +1 -1
  69. package/dist/public/node/node-package-manager.d.ts +2 -2
  70. package/dist/public/node/node-package-manager.js +10 -10
  71. package/dist/public/node/node-package-manager.js.map +1 -1
  72. package/dist/public/node/notifications-system.d.ts +6 -6
  73. package/dist/public/node/output.js +2 -0
  74. package/dist/public/node/output.js.map +1 -1
  75. package/dist/public/node/path.js +0 -2
  76. package/dist/public/node/path.js.map +1 -1
  77. package/dist/public/node/session.d.ts +6 -0
  78. package/dist/public/node/session.js +8 -0
  79. package/dist/public/node/session.js.map +1 -1
  80. package/dist/public/node/system.js +19 -42
  81. package/dist/public/node/system.js.map +1 -1
  82. package/dist/public/node/tree-kill.js +17 -5
  83. package/dist/public/node/tree-kill.js.map +1 -1
  84. package/dist/public/node/ui.js +6 -0
  85. package/dist/public/node/ui.js.map +1 -1
  86. package/dist/public/node/upgrade.d.ts +27 -8
  87. package/dist/public/node/upgrade.js +50 -21
  88. package/dist/public/node/upgrade.js.map +1 -1
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +3 -3
@@ -7,6 +7,14 @@ import * as sessionStore from '../../private/node/session/store.js';
7
7
  import { exchangeCustomPartnerToken, exchangeAppAutomationTokenForAppManagementAccessToken, exchangeAppAutomationTokenForBusinessPlatformAccessToken, } from '../../private/node/session/exchange.js';
8
8
  import { ensureAuthenticated, setLastSeenAuthMethod, setLastSeenUserIdAfterAuth, } from '../../private/node/session.js';
9
9
  import { isThemeAccessSession } from '../../private/node/api/rest.js';
10
+ /**
11
+ * Records the user ID that should be attached to command analytics for this process.
12
+ *
13
+ * @param userId - User identifier to report on the command analytics event.
14
+ */
15
+ export function setLastSeenUserId(userId) {
16
+ setLastSeenUserIdAfterAuth(userId);
17
+ }
10
18
  /**
11
19
  * Type guard to check if an account is a UserAccount.
12
20
  *
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/public/node/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAC,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,YAAY,MAAM,qCAAqC,CAAA;AACnE,OAAO,EACL,0BAA0B,EAC1B,qDAAqD,EACrD,wDAAwD,GACzD,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAOL,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAC,oBAAoB,EAAC,MAAM,gCAAgC,CAAA;AAoCnE;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,OAAO,OAAO,CAAC,IAAI,KAAK,aAAa,CAAA;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACnD,OAAO,OAAO,CAAC,IAAI,KAAK,gBAAgB,CAAA;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAG,GAAG,OAAO,CAAC,GAAG,EACjB,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA,mEAAmE,CAAC,CAAA;IAC7F,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC1D,OAAO,EAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAA;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,SAA6B,EAAE,EAC/B,GAAG,GAAG,OAAO,CAAC,GAAG,EACjB,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAA;QACzD,OAAO,EAAC,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAA;IAC3D,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,WAAW,EAAE,EAAC,MAAM,EAAC,EAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC/E,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,QAAQ,CAAC,sDAAsD,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,EAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAA;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mDAAmD,CACvE,UAAgD,EAAE,EAClD,sBAA+C,EAAE,EACjD,yBAAkD,EAAE,EACpD,GAAG,GAAG,OAAO,CAAC,GAAG;IAEjB,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC;CACtC,CAAC,CAAA;IAEA,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,iBAAiB,GAAG,MAAM,qDAAqD,CAAC,QAAQ,CAAC,CAAA;QAC/F,MAAM,qBAAqB,GAAG,MAAM,wDAAwD,CAAC,QAAQ,CAAC,CAAA;QAEtG,OAAO;YACL,kBAAkB,EAAE,iBAAiB,CAAC,WAAW;YACjD,MAAM,EAAE,iBAAiB,CAAC,MAAM;YAChC,qBAAqB,EAAE,qBAAqB,CAAC,WAAW;SACzD,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAC,gBAAgB,EAAE,EAAC,MAAM,EAAE,mBAAmB,EAAC,EAAE,mBAAmB,EAAE,EAAC,MAAM,EAAE,sBAAsB,EAAC,EAAC,EACxG,GAAG,EACH,OAAO,CACR,CAAA;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACtD,MAAM,IAAI,QAAQ,CAAC,iFAAiF,CAAC,CAAA;IACvG,CAAC;IAED,OAAO;QACL,kBAAkB,EAAE,MAAM,CAAC,aAAa;QACxC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,qBAAqB,EAAE,MAAM,CAAC,gBAAgB;KAC/C,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,SAAoC,EAAE,EACtC,WAA+B,SAAS,EACxC,UAAgD,EAAE;IAElD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,EAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAC,CAAA;QAChD,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAC5F,qBAAqB,CAAC,UAAU,CAAC,CAAA;QACjC,0BAA0B,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnD,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,qBAAqB,EAAE,EAAC,MAAM,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACjG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,wDAAwD,CAAC,CAAA;IAC9E,CAAC;IACD,OAAO,MAAM,CAAC,UAAU,CAAA;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAAa,EACb,SAA0B,EAAE,EAC5B,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA,sGAAsG,WAAW,CAAC,GAAG,CAC5I,KAAK,CACN;EACD,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,QAAQ,EAAE,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,EAAE;QAC5F,GAAG,OAAO;KACX,CAAC,CAAA;IACF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,QAAQ,CAAC,mDAAmD,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAA;AACrB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAa,EACb,QAA4B,EAC5B,SAA0B,EAAE,EAC5B,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,EAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAC,CAAA;QACnD,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAC5F,qBAAqB,CAAC,UAAU,CAAC,CAAA;QACjC,0BAA0B,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnD,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,OAAO,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mCAAmC,CAAC,SAAkC,EAAE;IAC5F,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,mBAAmB,EAAE,EAAC,MAAM,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IACtF,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7B,MAAM,IAAI,QAAQ,CAAC,+DAA+D,CAAC,CAAA;IACrF,CAAC;IACD,OAAO,MAAM,CAAC,gBAAgB,CAAA;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO,YAAY,CAAC,MAAM,EAAE,CAAA;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,SAAiB,EACjB,QAAgB,EAChB,YAAoB;IAEpB,MAAM,QAAQ,GAAG;QACf,SAAS,EAAE,QAAQ;QACnB,aAAa,EAAE,YAAY;QAC3B,UAAU,EAAE,oBAAoB;KACjC,CAAA;IACD,MAAM,aAAa,GAAG,MAAM,YAAY,CACtC,WAAW,SAAS,2BAA2B,EAC/C;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;KAC/B,EACD,cAAc,CACf,CAAA;IAED,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAA;IAEvC,IAAI,aAAa,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,UAAU,CAClB,aAAa,CAAA,2BAA2B,WAAW,CAAC,KAAK,CACvD,SAAS,CACV,iBAAiB,WAAW,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,mCAAmC,CACxG,CAAA;QACH,CAAC;QACD,MAAM,IAAI,UAAU,CAClB,sCAAsC,QAAQ,aAAa,SAAS,KAAK,aAAa,CAAC,UAAU,EAAE,CACpG,CAAA;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAA;QAC5D,OAAO,EAAC,KAAK,EAAE,SAAS,CAAC,YAAY,EAAE,SAAS,EAAC,CAAA;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,UAAU,CAClB,qEAAqE,aAAa,CAAC,MAAM,IAAI,EAC7F,yGAAyG,CAC1G,CAAA;QACH,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC","sourcesContent":["import {shopifyFetch} from './http.js'\nimport {nonRandomUUID} from './crypto.js'\nimport {getAppAutomationToken} from './environment.js'\nimport {AbortError, BugError} from './error.js'\nimport {outputContent, outputToken, outputDebug} from './output.js'\nimport * as sessionStore from '../../private/node/session/store.js'\nimport {\n exchangeCustomPartnerToken,\n exchangeAppAutomationTokenForAppManagementAccessToken,\n exchangeAppAutomationTokenForBusinessPlatformAccessToken,\n} from '../../private/node/session/exchange.js'\nimport {\n AdminAPIScope,\n AppManagementAPIScope,\n BusinessPlatformScope,\n EnsureAuthenticatedAdditionalOptions,\n PartnersAPIScope,\n StorefrontRendererScope,\n ensureAuthenticated,\n setLastSeenAuthMethod,\n setLastSeenUserIdAfterAuth,\n} from '../../private/node/session.js'\nimport {isThemeAccessSession} from '../../private/node/api/rest.js'\n\n/**\n * Session Object to access the Admin API, includes the token and the store FQDN.\n */\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\n/**\n * Session Object for Partners API and App Management API access.\n */\nexport interface Session {\n token: string\n businessPlatformToken: string\n accountInfo: AccountInfo\n userId: string\n}\n\nexport type AccountInfo = UserAccountInfo | ServiceAccountInfo | UnknownAccountInfo\n\ninterface UserAccountInfo {\n type: 'UserAccount'\n email: string\n}\n\ninterface ServiceAccountInfo {\n type: 'ServiceAccount'\n orgName: string\n}\n\ninterface UnknownAccountInfo {\n type: 'UnknownAccount'\n}\n\n/**\n * Type guard to check if an account is a UserAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a UserAccount.\n */\nexport function isUserAccount(account: AccountInfo): account is UserAccountInfo {\n return account.type === 'UserAccount'\n}\n\n/**\n * Type guard to check if an account is a ServiceAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a ServiceAccount.\n */\nexport function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo {\n return account.type === 'ServiceAccount'\n}\n\n/**\n * Ensure that we have a valid session with no particular scopes.\n *\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The user ID.\n */\nexport async function ensureAuthenticatedUser(\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with no particular scopes`)\n const tokens = await ensureAuthenticated({}, env, options)\n return {userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(\n scopes: PartnersAPIScope[] = [],\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{token: string; userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const envToken = getAppAutomationToken()\n if (envToken) {\n const result = await exchangeCustomPartnerToken(envToken)\n return {token: result.accessToken, userId: result.userId}\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}}, env, options)\n if (!tokens.partners) {\n throw new BugError('No partners token found after ensuring authenticated')\n }\n return {token: tokens.partners, userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the App Management API.\n *\n * @param options - Optional extra options to use.\n * @param appManagementScopes - Optional array of extra scopes to authenticate with.\n * @param businessPlatformScopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @returns The access token for the App Management API.\n */\nexport async function ensureAuthenticatedAppManagementAndBusinessPlatform(\n options: EnsureAuthenticatedAdditionalOptions = {},\n appManagementScopes: AppManagementAPIScope[] = [],\n businessPlatformScopes: BusinessPlatformScope[] = [],\n env = process.env,\n): Promise<{appManagementToken: string; userId: string; businessPlatformToken: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the App Management API with the following scopes:\n${outputToken.json(appManagementScopes)}\n`)\n\n const envToken = getAppAutomationToken()\n if (envToken) {\n const appManagmentToken = await exchangeAppAutomationTokenForAppManagementAccessToken(envToken)\n const businessPlatformToken = await exchangeAppAutomationTokenForBusinessPlatformAccessToken(envToken)\n\n return {\n appManagementToken: appManagmentToken.accessToken,\n userId: appManagmentToken.userId,\n businessPlatformToken: businessPlatformToken.accessToken,\n }\n }\n\n const tokens = await ensureAuthenticated(\n {appManagementApi: {scopes: appManagementScopes}, businessPlatformApi: {scopes: businessPlatformScopes}},\n env,\n options,\n )\n if (!tokens.appManagement || !tokens.businessPlatform) {\n throw new BugError('No App Management or Business Platform token found after ensuring authenticated')\n }\n\n return {\n appManagementToken: tokens.appManagement,\n userId: tokens.userId,\n businessPlatformToken: tokens.businessPlatform,\n }\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param password - Optional password to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(\n scopes: StorefrontRendererScope[] = [],\n password: string | undefined = undefined,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<string> {\n if (password) {\n const session = {token: password, storeFqdn: ''}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return password\n }\n\n outputDebug(outputContent`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}}, process.env, options)\n if (!tokens.storefront) {\n throw new BugError('No storefront token found after ensuring authenticated')\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n *\n * @param store - Store fqdn to request auth for.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdmin(\n store: string,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${outputToken.raw(\n store,\n )}:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}}, process.env, {\n ...options,\n })\n if (!tokens.admin) {\n throw new BugError('No admin token found after ensuring authenticated')\n }\n return tokens.admin\n}\n\n/**\n * Ensure that we have a valid session to access the Theme API.\n * If a password is provided, that token will be used against Theme Access API.\n * Otherwise, it will ensure that the user is authenticated with the Admin API.\n *\n * @param store - Store fqdn to request auth for.\n * @param password - Password generated from Theme Access app.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token and store.\n */\nexport async function ensureAuthenticatedThemes(\n store: string,\n password: string | undefined,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Theme API with the following scopes:\n${outputToken.json(scopes)}\n`)\n if (password) {\n const session = {token: password, storeFqdn: store}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return session\n }\n return ensureAuthenticatedAdmin(store, scopes, options)\n}\n\n/**\n * Ensure that we have a valid session to access the Business Platform API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Business Platform API.\n */\nexport async function ensureAuthenticatedBusinessPlatform(scopes: BusinessPlatformScope[] = []): Promise<string> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Business Platform API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({businessPlatformApi: {scopes}}, process.env)\n if (!tokens.businessPlatform) {\n throw new BugError('No business-platform token found after ensuring authenticated')\n }\n return tokens.businessPlatform\n}\n\n/**\n * Logout from Shopify.\n *\n * @returns A promise that resolves when the logout is complete.\n */\nexport function logout(): Promise<void> {\n return sessionStore.remove()\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store, with access on behalf of the app.\n *\n * See `ensureAuthenticatedAdmin` for access on behalf of a user.\n *\n * @param storeFqdn - Store fqdn to request auth for.\n * @param clientId - Client ID of the app.\n * @param clientSecret - Client secret of the app.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdminAsApp(\n storeFqdn: string,\n clientId: string,\n clientSecret: string,\n): Promise<AdminSession> {\n const bodyData = {\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: 'client_credentials',\n }\n const tokenResponse = await shopifyFetch(\n `https://${storeFqdn}/admin/oauth/access_token`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(bodyData),\n },\n 'slow-request',\n )\n\n const body = await tokenResponse.text()\n\n if (tokenResponse.status === 400) {\n if (body.includes('app_not_installed')) {\n throw new AbortError(\n outputContent`App is not installed on ${outputToken.green(\n storeFqdn,\n )}. Try running ${outputToken.genericShellCommand(`shopify app dev`)} to connect your app to the shop.`,\n )\n }\n throw new AbortError(\n `Failed to get access token for app ${clientId} on store ${storeFqdn}: ${tokenResponse.statusText}`,\n )\n }\n try {\n const tokenJson = JSON.parse(body) as {access_token: string}\n return {token: tokenJson.access_token, storeFqdn}\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new AbortError(\n `Received invalid response from admin authentication service (HTTP ${tokenResponse.status}).`,\n 'The response could not be parsed as JSON. The service may be temporarily unavailable. Please try again.',\n )\n }\n throw error\n }\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/public/node/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAC,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,YAAY,MAAM,qCAAqC,CAAA;AACnE,OAAO,EACL,0BAA0B,EAC1B,qDAAqD,EACrD,wDAAwD,GACzD,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAOL,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAC,oBAAoB,EAAC,MAAM,gCAAgC,CAAA;AAsBnE;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,0BAA0B,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC;AAgBD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,OAAO,OAAO,CAAC,IAAI,KAAK,aAAa,CAAA;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACnD,OAAO,OAAO,CAAC,IAAI,KAAK,gBAAgB,CAAA;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAG,GAAG,OAAO,CAAC,GAAG,EACjB,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA,mEAAmE,CAAC,CAAA;IAC7F,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC1D,OAAO,EAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAA;AAChC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,SAA6B,EAAE,EAC/B,GAAG,GAAG,OAAO,CAAC,GAAG,EACjB,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAA;QACzD,OAAO,EAAC,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAA;IAC3D,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,WAAW,EAAE,EAAC,MAAM,EAAC,EAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;IAC/E,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,QAAQ,CAAC,sDAAsD,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,EAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAA;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mDAAmD,CACvE,UAAgD,EAAE,EAClD,sBAA+C,EAAE,EACjD,yBAAkD,EAAE,EACpD,GAAG,GAAG,OAAO,CAAC,GAAG;IAEjB,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,mBAAmB,CAAC;CACtC,CAAC,CAAA;IAEA,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,iBAAiB,GAAG,MAAM,qDAAqD,CAAC,QAAQ,CAAC,CAAA;QAC/F,MAAM,qBAAqB,GAAG,MAAM,wDAAwD,CAAC,QAAQ,CAAC,CAAA;QAEtG,OAAO;YACL,kBAAkB,EAAE,iBAAiB,CAAC,WAAW;YACjD,MAAM,EAAE,iBAAiB,CAAC,MAAM;YAChC,qBAAqB,EAAE,qBAAqB,CAAC,WAAW;SACzD,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAC,gBAAgB,EAAE,EAAC,MAAM,EAAE,mBAAmB,EAAC,EAAE,mBAAmB,EAAE,EAAC,MAAM,EAAE,sBAAsB,EAAC,EAAC,EACxG,GAAG,EACH,OAAO,CACR,CAAA;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACtD,MAAM,IAAI,QAAQ,CAAC,iFAAiF,CAAC,CAAA;IACvG,CAAC;IAED,OAAO;QACL,kBAAkB,EAAE,MAAM,CAAC,aAAa;QACxC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,qBAAqB,EAAE,MAAM,CAAC,gBAAgB;KAC/C,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,SAAoC,EAAE,EACtC,WAA+B,SAAS,EACxC,UAAgD,EAAE;IAElD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,EAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAC,CAAA;QAChD,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAC5F,qBAAqB,CAAC,UAAU,CAAC,CAAA;QACjC,0BAA0B,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnD,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,qBAAqB,EAAE,EAAC,MAAM,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACjG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,wDAAwD,CAAC,CAAA;IAC9E,CAAC;IACD,OAAO,MAAM,CAAC,UAAU,CAAA;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAAa,EACb,SAA0B,EAAE,EAC5B,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA,sGAAsG,WAAW,CAAC,GAAG,CAC5I,KAAK,CACN;EACD,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,QAAQ,EAAE,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,EAAE;QAC5F,GAAG,OAAO;KACX,CAAC,CAAA;IACF,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,QAAQ,CAAC,mDAAmD,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAA;AACrB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAa,EACb,QAA4B,EAC5B,SAA0B,EAAE,EAC5B,UAAgD,EAAE;IAElD,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,EAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAC,CAAA;QACnD,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAC5F,qBAAqB,CAAC,UAAU,CAAC,CAAA;QACjC,0BAA0B,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnD,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,OAAO,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mCAAmC,CAAC,SAAkC,EAAE;IAC5F,WAAW,CAAC,aAAa,CAAA;EACzB,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,mBAAmB,EAAE,EAAC,MAAM,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IACtF,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7B,MAAM,IAAI,QAAQ,CAAC,+DAA+D,CAAC,CAAA;IACrF,CAAC;IACD,OAAO,MAAM,CAAC,gBAAgB,CAAA;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM;IACpB,OAAO,YAAY,CAAC,MAAM,EAAE,CAAA;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,SAAiB,EACjB,QAAgB,EAChB,YAAoB;IAEpB,MAAM,QAAQ,GAAG;QACf,SAAS,EAAE,QAAQ;QACnB,aAAa,EAAE,YAAY;QAC3B,UAAU,EAAE,oBAAoB;KACjC,CAAA;IACD,MAAM,aAAa,GAAG,MAAM,YAAY,CACtC,WAAW,SAAS,2BAA2B,EAC/C;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;KAC/B,EACD,cAAc,CACf,CAAA;IAED,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAA;IAEvC,IAAI,aAAa,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,UAAU,CAClB,aAAa,CAAA,2BAA2B,WAAW,CAAC,KAAK,CACvD,SAAS,CACV,iBAAiB,WAAW,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,mCAAmC,CACxG,CAAA;QACH,CAAC;QACD,MAAM,IAAI,UAAU,CAClB,sCAAsC,QAAQ,aAAa,SAAS,KAAK,aAAa,CAAC,UAAU,EAAE,CACpG,CAAA;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAA;QAC5D,OAAO,EAAC,KAAK,EAAE,SAAS,CAAC,YAAY,EAAE,SAAS,EAAC,CAAA;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,UAAU,CAClB,qEAAqE,aAAa,CAAC,MAAM,IAAI,EAC7F,yGAAyG,CAC1G,CAAA;QACH,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC","sourcesContent":["import {shopifyFetch} from './http.js'\nimport {nonRandomUUID} from './crypto.js'\nimport {getAppAutomationToken} from './environment.js'\nimport {AbortError, BugError} from './error.js'\nimport {outputContent, outputToken, outputDebug} from './output.js'\nimport * as sessionStore from '../../private/node/session/store.js'\nimport {\n exchangeCustomPartnerToken,\n exchangeAppAutomationTokenForAppManagementAccessToken,\n exchangeAppAutomationTokenForBusinessPlatformAccessToken,\n} from '../../private/node/session/exchange.js'\nimport {\n AdminAPIScope,\n AppManagementAPIScope,\n BusinessPlatformScope,\n EnsureAuthenticatedAdditionalOptions,\n PartnersAPIScope,\n StorefrontRendererScope,\n ensureAuthenticated,\n setLastSeenAuthMethod,\n setLastSeenUserIdAfterAuth,\n} from '../../private/node/session.js'\nimport {isThemeAccessSession} from '../../private/node/api/rest.js'\n\n/**\n * Session Object to access the Admin API, includes the token and the store FQDN.\n */\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\n/**\n * Session Object for Partners API and App Management API access.\n */\nexport interface Session {\n token: string\n businessPlatformToken: string\n accountInfo: AccountInfo\n userId: string\n}\n\nexport type AccountInfo = UserAccountInfo | ServiceAccountInfo | UnknownAccountInfo\n\n/**\n * Records the user ID that should be attached to command analytics for this process.\n *\n * @param userId - User identifier to report on the command analytics event.\n */\nexport function setLastSeenUserId(userId: string): void {\n setLastSeenUserIdAfterAuth(userId)\n}\n\ninterface UserAccountInfo {\n type: 'UserAccount'\n email: string\n}\n\ninterface ServiceAccountInfo {\n type: 'ServiceAccount'\n orgName: string\n}\n\ninterface UnknownAccountInfo {\n type: 'UnknownAccount'\n}\n\n/**\n * Type guard to check if an account is a UserAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a UserAccount.\n */\nexport function isUserAccount(account: AccountInfo): account is UserAccountInfo {\n return account.type === 'UserAccount'\n}\n\n/**\n * Type guard to check if an account is a ServiceAccount.\n *\n * @param account - The account to check.\n * @returns True if the account is a ServiceAccount.\n */\nexport function isServiceAccount(account: AccountInfo): account is ServiceAccountInfo {\n return account.type === 'ServiceAccount'\n}\n\n/**\n * Ensure that we have a valid session with no particular scopes.\n *\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The user ID.\n */\nexport async function ensureAuthenticatedUser(\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with no particular scopes`)\n const tokens = await ensureAuthenticated({}, env, options)\n return {userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(\n scopes: PartnersAPIScope[] = [],\n env = process.env,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<{token: string; userId: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const envToken = getAppAutomationToken()\n if (envToken) {\n const result = await exchangeCustomPartnerToken(envToken)\n return {token: result.accessToken, userId: result.userId}\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}}, env, options)\n if (!tokens.partners) {\n throw new BugError('No partners token found after ensuring authenticated')\n }\n return {token: tokens.partners, userId: tokens.userId}\n}\n\n/**\n * Ensure that we have a valid session to access the App Management API.\n *\n * @param options - Optional extra options to use.\n * @param appManagementScopes - Optional array of extra scopes to authenticate with.\n * @param businessPlatformScopes - Optional array of extra scopes to authenticate with.\n * @param env - Optional environment variables to use.\n * @returns The access token for the App Management API.\n */\nexport async function ensureAuthenticatedAppManagementAndBusinessPlatform(\n options: EnsureAuthenticatedAdditionalOptions = {},\n appManagementScopes: AppManagementAPIScope[] = [],\n businessPlatformScopes: BusinessPlatformScope[] = [],\n env = process.env,\n): Promise<{appManagementToken: string; userId: string; businessPlatformToken: string}> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the App Management API with the following scopes:\n${outputToken.json(appManagementScopes)}\n`)\n\n const envToken = getAppAutomationToken()\n if (envToken) {\n const appManagmentToken = await exchangeAppAutomationTokenForAppManagementAccessToken(envToken)\n const businessPlatformToken = await exchangeAppAutomationTokenForBusinessPlatformAccessToken(envToken)\n\n return {\n appManagementToken: appManagmentToken.accessToken,\n userId: appManagmentToken.userId,\n businessPlatformToken: businessPlatformToken.accessToken,\n }\n }\n\n const tokens = await ensureAuthenticated(\n {appManagementApi: {scopes: appManagementScopes}, businessPlatformApi: {scopes: businessPlatformScopes}},\n env,\n options,\n )\n if (!tokens.appManagement || !tokens.businessPlatform) {\n throw new BugError('No App Management or Business Platform token found after ensuring authenticated')\n }\n\n return {\n appManagementToken: tokens.appManagement,\n userId: tokens.userId,\n businessPlatformToken: tokens.businessPlatform,\n }\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param password - Optional password to use.\n * @param options - Optional extra options to use.\n * @returns The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(\n scopes: StorefrontRendererScope[] = [],\n password: string | undefined = undefined,\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<string> {\n if (password) {\n const session = {token: password, storeFqdn: ''}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return password\n }\n\n outputDebug(outputContent`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}}, process.env, options)\n if (!tokens.storefront) {\n throw new BugError('No storefront token found after ensuring authenticated')\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n *\n * @param store - Store fqdn to request auth for.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdmin(\n store: string,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${outputToken.raw(\n store,\n )}:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}}, process.env, {\n ...options,\n })\n if (!tokens.admin) {\n throw new BugError('No admin token found after ensuring authenticated')\n }\n return tokens.admin\n}\n\n/**\n * Ensure that we have a valid session to access the Theme API.\n * If a password is provided, that token will be used against Theme Access API.\n * Otherwise, it will ensure that the user is authenticated with the Admin API.\n *\n * @param store - Store fqdn to request auth for.\n * @param password - Password generated from Theme Access app.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @param options - Optional extra options to use.\n * @returns The access token and store.\n */\nexport async function ensureAuthenticatedThemes(\n store: string,\n password: string | undefined,\n scopes: AdminAPIScope[] = [],\n options: EnsureAuthenticatedAdditionalOptions = {},\n): Promise<AdminSession> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Theme API with the following scopes:\n${outputToken.json(scopes)}\n`)\n if (password) {\n const session = {token: password, storeFqdn: store}\n const authMethod = isThemeAccessSession(session) ? 'theme_access_token' : 'custom_app_token'\n setLastSeenAuthMethod(authMethod)\n setLastSeenUserIdAfterAuth(nonRandomUUID(password))\n return session\n }\n return ensureAuthenticatedAdmin(store, scopes, options)\n}\n\n/**\n * Ensure that we have a valid session to access the Business Platform API.\n *\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Business Platform API.\n */\nexport async function ensureAuthenticatedBusinessPlatform(scopes: BusinessPlatformScope[] = []): Promise<string> {\n outputDebug(outputContent`Ensuring that the user is authenticated with the Business Platform API with the following scopes:\n${outputToken.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({businessPlatformApi: {scopes}}, process.env)\n if (!tokens.businessPlatform) {\n throw new BugError('No business-platform token found after ensuring authenticated')\n }\n return tokens.businessPlatform\n}\n\n/**\n * Logout from Shopify.\n *\n * @returns A promise that resolves when the logout is complete.\n */\nexport function logout(): Promise<void> {\n return sessionStore.remove()\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store, with access on behalf of the app.\n *\n * See `ensureAuthenticatedAdmin` for access on behalf of a user.\n *\n * @param storeFqdn - Store fqdn to request auth for.\n * @param clientId - Client ID of the app.\n * @param clientSecret - Client secret of the app.\n * @returns The access token for the Admin API.\n */\nexport async function ensureAuthenticatedAdminAsApp(\n storeFqdn: string,\n clientId: string,\n clientSecret: string,\n): Promise<AdminSession> {\n const bodyData = {\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: 'client_credentials',\n }\n const tokenResponse = await shopifyFetch(\n `https://${storeFqdn}/admin/oauth/access_token`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(bodyData),\n },\n 'slow-request',\n )\n\n const body = await tokenResponse.text()\n\n if (tokenResponse.status === 400) {\n if (body.includes('app_not_installed')) {\n throw new AbortError(\n outputContent`App is not installed on ${outputToken.green(\n storeFqdn,\n )}. Try running ${outputToken.genericShellCommand(`shopify app dev`)} to connect your app to the shop.`,\n )\n }\n throw new AbortError(\n `Failed to get access token for app ${clientId} on store ${storeFqdn}: ${tokenResponse.statusText}`,\n )\n }\n try {\n const tokenJson = JSON.parse(body) as {access_token: string}\n return {token: tokenJson.access_token, storeFqdn}\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new AbortError(\n `Received invalid response from admin authentication service (HTTP ${tokenResponse.status}).`,\n 'The response could not be parsed as JSON. The service may be temporarily unavailable. Please try again.',\n )\n }\n throw error\n }\n}\n"]}
@@ -5,11 +5,17 @@ import { isTruthy } from './context/utilities.js';
5
5
  import { renderWarning } from './ui.js';
6
6
  import { platformAndArch } from './os.js';
7
7
  import { shouldDisplayColors, outputDebug } from './output.js';
8
- import { execa, execaCommand } from 'execa';
8
+ import { execa } from 'execa';
9
9
  import supportsHyperlinks from 'supports-hyperlinks';
10
10
  import which from 'which';
11
11
  import { delimiter } from 'pathe';
12
12
  import { fstatSync } from 'fs';
13
+ /**
14
+ * The maximum size of data that can be read from stdin in bytes.
15
+ * This is to prevent memory exhaustion when reading from stdin.
16
+ * 10MB.
17
+ */
18
+ const MAX_STDIN_SIZE = 10 * 1024 * 1024;
13
19
  /**
14
20
  * Opens a URL in the user's default browser.
15
21
  *
@@ -127,26 +133,11 @@ function parseCommand(command) {
127
133
  * ```
128
134
  */
129
135
  export async function captureCommandWithExitCode(command, options) {
130
- const env = options?.env ?? process.env;
131
- if (shouldDisplayColors()) {
132
- env.FORCE_COLOR = '1';
133
- }
134
- const executionCwd = options?.cwd ?? cwd();
135
136
  const [cmd, ...args] = parseCommand(command);
136
137
  if (!cmd) {
137
138
  return { stdout: '', stderr: 'Empty command', exitCode: 1 };
138
139
  }
139
- checkCommandSafety(cmd, { cwd: executionCwd });
140
- const result = await execa(cmd, args, {
141
- env,
142
- cwd: executionCwd,
143
- reject: false,
144
- });
145
- return {
146
- stdout: result.stdout,
147
- stderr: result.stderr,
148
- exitCode: result.exitCode ?? 0,
149
- };
140
+ return captureOutputWithExitCode(cmd, args, options);
150
141
  }
151
142
  /**
152
143
  * Runs a command string asynchronously (parses command and arguments from the string).
@@ -155,31 +146,11 @@ export async function captureCommandWithExitCode(command, options) {
155
146
  * @param options - Optional settings for how to run the command.
156
147
  */
157
148
  export async function execCommand(command, options) {
158
- const env = options?.env ?? process.env;
159
- if (shouldDisplayColors()) {
160
- env.FORCE_COLOR = '1';
161
- }
162
- const executionCwd = options?.cwd ?? cwd();
163
- try {
164
- await execaCommand(command, {
165
- env,
166
- cwd: executionCwd,
167
- stdin: options?.stdin,
168
- stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,
169
- stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,
170
- });
171
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
- }
173
- catch (processError) {
174
- if (options?.externalErrorHandler) {
175
- await options.externalErrorHandler(processError);
176
- }
177
- else {
178
- const abortError = new ExternalError(processError.message, command, []);
179
- abortError.stack = processError.stack;
180
- throw abortError;
181
- }
149
+ const [cmd, ...args] = parseCommand(command);
150
+ if (!cmd) {
151
+ throw new AbortError('Empty command');
182
152
  }
153
+ await exec(cmd, args, options);
183
154
  }
184
155
  /**
185
156
  * Runs a command asynchronously.
@@ -361,9 +332,15 @@ export async function readStdinString() {
361
332
  return undefined;
362
333
  }
363
334
  let data = '';
335
+ let totalSize = 0;
364
336
  process.stdin.setEncoding('utf8');
365
337
  for await (const chunk of process.stdin) {
366
- data += String(chunk);
338
+ const chunkString = String(chunk);
339
+ totalSize += Buffer.byteLength(chunkString, 'utf8');
340
+ if (totalSize > MAX_STDIN_SIZE) {
341
+ throw new AbortError('Stdin input exceeded the maximum allowed size.');
342
+ }
343
+ data += chunkString;
367
344
  }
368
345
  return data.trim();
369
346
  }
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from './output.js'\nimport {execa, execaCommand, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync} from 'fs'\nimport type {Writable, Readable} from 'stream'\n\nexport interface ExecOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Options passed directly to execa.\n */\ninterface BuildExecOptions {\n /** Whether to throw on non-zero exit codes (default: true). */\n reject?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Result from running a command with captureOutputWithExitCode.\n */\nexport interface CaptureOutputResult {\n /** Standard output. */\n stdout: string\n /** Standard error. */\n stderr: string\n /** Exit code (0 = success). */\n exitCode: number\n}\n\n/**\n * Runs a command asynchronously and returns stdout, stderr, and exit code.\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureOutputWithExitCode('ls', ['-la'])\n * if (result.exitCode !== 0) \\{\n * console.error('Command failed:', result.stderr)\n * \\}\n * ```\n */\nexport async function captureOutputWithExitCode(\n command: string,\n args: string[],\n options?: ExecOptions,\n): Promise<CaptureOutputResult> {\n const result = await buildExec(command, args, options, {reject: false})\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Parse a command string into an array of arguments, respecting quoted strings.\n * Handles both single and double quotes, preserving spaces within quoted sections.\n *\n * @param command - The command string to parse (e.g., 'ls -la \"my folder\"').\n * @returns An array of command parts with quotes removed.\n *\n * @example\n * parseCommand('shopify theme push --theme \"My Theme Name\"') // ['shopify', 'theme', 'push', '--theme', 'My Theme Name']\n */\nfunction parseCommand(command: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (const char of command) {\n if (inQuote) {\n if (char === inQuote) {\n // End of quoted section\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n // Start of quoted section\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n // Whitespace outside quotes - end current token\n if (current) {\n result.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n // Don't forget the last token\n if (current) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Runs a command string asynchronously and returns stdout, stderr, and exit code.\n * Parses the command string into command and arguments (handles quoted strings).\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureCommandWithExitCode('shopify theme push --theme \"My Theme\"')\n * if (result.exitCode !== 0) {\n * console.error('Command failed:', result.stderr)\n * }\n * ```\n */\nexport async function captureCommandWithExitCode(command: string, options?: ExecOptions): Promise<CaptureOutputResult> {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n return {stdout: '', stderr: 'Empty command', exitCode: 1}\n }\n checkCommandSafety(cmd, {cwd: executionCwd})\n const result = await execa(cmd, args, {\n env,\n cwd: executionCwd,\n reject: false,\n })\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Runs a command string asynchronously (parses command and arguments from the string).\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n */\nexport async function execCommand(command: string, options?: ExecOptions): Promise<void> {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n try {\n await execaCommand(command, {\n env,\n cwd: executionCwd,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n })\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, [])\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @param execaOptions - Options passed directly to execa.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(\n command: string,\n args: string[],\n options?: ExecOptions,\n execaOptions?: BuildExecOptions,\n): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? 'ignore' : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n ...execaOptions,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, 1000 * seconds)\n })\n}\n\n/**\n * Check if the terminal supports OSC 8 hyperlinks.\n *\n * @returns True if the terminal supports hyperlinks.\n */\nexport function terminalSupportsHyperlinks(): boolean {\n return supportsHyperlinks.stdout\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @returns True if the current environment is a WSL environment.\n */\nexport async function isWsl(): Promise<boolean> {\n const wsl = await import('is-wsl')\n return wsl.default\n}\n\n/**\n * Check if stdin has piped data available.\n * This distinguishes between actual piped input (e.g., `echo \"query\" | cmd`)\n * and non-TTY environments without input (e.g., CI).\n *\n * @returns True if stdin is receiving piped data or file redirect, false otherwise.\n */\nexport function isStdinPiped(): boolean {\n try {\n const stats = fstatSync(0)\n return stats.isFIFO() || stats.isFile()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Reads all data from stdin and returns it as a string.\n * This is useful for commands that accept input via piping.\n *\n * @example\n * // Usage: echo \"your query\" | shopify app execute\n * const query = await readStdin()\n *\n * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.\n */\nexport async function readStdinString(): Promise<string | undefined> {\n if (!isStdinPiped()) {\n return undefined\n }\n\n let data = ''\n process.stdin.setEncoding('utf8')\n for await (const chunk of process.stdin) {\n data += String(chunk)\n }\n return data.trim()\n}\n"]}
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from './output.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync} from 'fs'\nimport type {Writable, Readable} from 'stream'\n\n/**\n * The maximum size of data that can be read from stdin in bytes.\n * This is to prevent memory exhaustion when reading from stdin.\n * 10MB.\n */\nconst MAX_STDIN_SIZE = 10 * 1024 * 1024\n\nexport interface ExecOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Options passed directly to execa.\n */\ninterface BuildExecOptions {\n /** Whether to throw on non-zero exit codes (default: true). */\n reject?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Result from running a command with captureOutputWithExitCode.\n */\nexport interface CaptureOutputResult {\n /** Standard output. */\n stdout: string\n /** Standard error. */\n stderr: string\n /** Exit code (0 = success). */\n exitCode: number\n}\n\n/**\n * Runs a command asynchronously and returns stdout, stderr, and exit code.\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureOutputWithExitCode('ls', ['-la'])\n * if (result.exitCode !== 0) \\{\n * console.error('Command failed:', result.stderr)\n * \\}\n * ```\n */\nexport async function captureOutputWithExitCode(\n command: string,\n args: string[],\n options?: ExecOptions,\n): Promise<CaptureOutputResult> {\n const result = await buildExec(command, args, options, {reject: false})\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Parse a command string into an array of arguments, respecting quoted strings.\n * Handles both single and double quotes, preserving spaces within quoted sections.\n *\n * @param command - The command string to parse (e.g., 'ls -la \"my folder\"').\n * @returns An array of command parts with quotes removed.\n *\n * @example\n * parseCommand('shopify theme push --theme \"My Theme Name\"') // ['shopify', 'theme', 'push', '--theme', 'My Theme Name']\n */\nfunction parseCommand(command: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (const char of command) {\n if (inQuote) {\n if (char === inQuote) {\n // End of quoted section\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n // Start of quoted section\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n // Whitespace outside quotes - end current token\n if (current) {\n result.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n // Don't forget the last token\n if (current) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Runs a command string asynchronously and returns stdout, stderr, and exit code.\n * Parses the command string into command and arguments (handles quoted strings).\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureCommandWithExitCode('shopify theme push --theme \"My Theme\"')\n * if (result.exitCode !== 0) {\n * console.error('Command failed:', result.stderr)\n * }\n * ```\n */\nexport async function captureCommandWithExitCode(command: string, options?: ExecOptions): Promise<CaptureOutputResult> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n return {stdout: '', stderr: 'Empty command', exitCode: 1}\n }\n return captureOutputWithExitCode(cmd, args, options)\n}\n\n/**\n * Runs a command string asynchronously (parses command and arguments from the string).\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n */\nexport async function execCommand(command: string, options?: ExecOptions): Promise<void> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n throw new AbortError('Empty command')\n }\n await exec(cmd, args, options)\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @param execaOptions - Options passed directly to execa.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(\n command: string,\n args: string[],\n options?: ExecOptions,\n execaOptions?: BuildExecOptions,\n): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? 'ignore' : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n ...execaOptions,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, 1000 * seconds)\n })\n}\n\n/**\n * Check if the terminal supports OSC 8 hyperlinks.\n *\n * @returns True if the terminal supports hyperlinks.\n */\nexport function terminalSupportsHyperlinks(): boolean {\n return supportsHyperlinks.stdout\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @returns True if the current environment is a WSL environment.\n */\nexport async function isWsl(): Promise<boolean> {\n const wsl = await import('is-wsl')\n return wsl.default\n}\n\n/**\n * Check if stdin has piped data available.\n * This distinguishes between actual piped input (e.g., `echo \"query\" | cmd`)\n * and non-TTY environments without input (e.g., CI).\n *\n * @returns True if stdin is receiving piped data or file redirect, false otherwise.\n */\nexport function isStdinPiped(): boolean {\n try {\n const stats = fstatSync(0)\n return stats.isFIFO() || stats.isFile()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Reads all data from stdin and returns it as a string.\n * This is useful for commands that accept input via piping.\n *\n * @example\n * // Usage: echo \"your query\" | shopify app execute\n * const query = await readStdin()\n *\n * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.\n */\nexport async function readStdinString(): Promise<string | undefined> {\n if (!isStdinPiped()) {\n return undefined\n }\n\n let data = ''\n let totalSize = 0\n process.stdin.setEncoding('utf8')\n for await (const chunk of process.stdin) {\n const chunkString = String(chunk)\n totalSize += Buffer.byteLength(chunkString, 'utf8')\n if (totalSize > MAX_STDIN_SIZE) {\n throw new AbortError('Stdin input exceeded the maximum allowed size.')\n }\n data += chunkString\n }\n return data.trim()\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable jsdoc/require-throws */
3
3
  /* eslint-disable no-restricted-imports */
4
4
  import { outputDebug } from './output.js';
5
- import { exec, spawn } from 'child_process';
5
+ import { spawn } from 'child_process';
6
6
  /**
7
7
  * Kills the process that calls the method and all its children.
8
8
  *
@@ -34,7 +34,8 @@ export function treeKill(pid = process.pid, killSignal = 'SIGTERM', killRoot = t
34
34
  */
35
35
  function adaptedTreeKill(pid, killSignal, killRoot, callback) {
36
36
  const rootPid = typeof pid === 'number' ? pid.toString() : pid;
37
- if (Number.isNaN(rootPid)) {
37
+ // Security: Validate that the PID is a number to prevent command injection
38
+ if (!/^\d+$/.test(rootPid)) {
38
39
  if (callback) {
39
40
  callback(new Error('pid must be a number'));
40
41
  return;
@@ -51,10 +52,21 @@ function adaptedTreeKill(pid, killSignal, killRoot, callback) {
51
52
  pidsToProcess.add(rootPid);
52
53
  // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- default handles all Unix-like platforms
53
54
  switch (process.platform) {
54
- case 'win32':
55
- // @ts-ignore
56
- exec(`taskkill /pid ${pid} /T /F`, callback);
55
+ case 'win32': {
56
+ // Security: Use spawn instead of exec to avoid shell injection when killing processes on Windows
57
+ const taskkill = spawn('taskkill', ['/pid', rootPid, '/T', '/F']);
58
+ taskkill.on('close', (code) => {
59
+ if (callback) {
60
+ if (code === 0) {
61
+ callback();
62
+ }
63
+ else {
64
+ callback(new Error(`taskkill exited with code ${code}`));
65
+ }
66
+ }
67
+ });
57
68
  break;
69
+ }
58
70
  case 'darwin':
59
71
  buildProcessTree(rootPid, tree, pidsToProcess, function (parentPid) {
60
72
  return spawn('pgrep', ['-lfP', parentPid]);
@@ -1 +1 @@
1
- {"version":3,"file":"tree-kill.js","sourceRoot":"","sources":["../../../src/public/node/tree-kill.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable jsdoc/require-throws */\n/* eslint-disable no-restricted-imports */\n\nimport {outputDebug} from './output.js'\nimport {exec, spawn} from 'child_process'\n\ntype ProcessTree = Record<string, string[]>\n\ntype AfterKillCallback = (error?: Error) => void\n\n/**\n * Kills the process that calls the method and all its children.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nexport function treeKill(\n pid: number | string = process.pid,\n killSignal = 'SIGTERM',\n killRoot = true,\n callback?: AfterKillCallback,\n): void {\n const after =\n callback ??\n ((error?: Error) => {\n if (error) outputDebug(`Failed to kill process ${pid}: ${error}`)\n })\n adaptedTreeKill(pid, killSignal, killRoot, after)\n}\n\n/**\n * Adapted from https://github.com/pkrumins/node-tree-kill.\n *\n * Our implementation allows to skip killing the root process. This is useful for example when\n * gracefully exiting the 'dev' process, as the default tree-kill implementation will cause it\n * to exit with a non-zero code. Instead, we want to treat it as a graceful termination.\n * In addition, we also add debug logging for better visibility in what tree-kill is doing.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction adaptedTreeKill(\n pid: number | string,\n killSignal: string,\n killRoot: boolean,\n callback: (error?: Error) => void,\n): void {\n const rootPid = typeof pid === 'number' ? pid.toString() : pid\n\n if (Number.isNaN(rootPid)) {\n if (callback) {\n callback(new Error('pid must be a number'))\n return\n } else {\n throw new Error('pid must be a number')\n }\n }\n\n // A map from parent pid to an array of children pids\n const tree: ProcessTree = {}\n tree[rootPid] = []\n\n // A set of pids to visit. We use it to recursively find all the children pids\n const pidsToProcess = new Set<string>()\n pidsToProcess.add(rootPid)\n\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- default handles all Unix-like platforms\n switch (process.platform) {\n case 'win32':\n // @ts-ignore\n exec(`taskkill /pid ${pid} /T /F`, callback)\n break\n case 'darwin':\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('pgrep', ['-lfP', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n default:\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('ps', ['-o', 'pid command', '--no-headers', '--ppid', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n }\n}\n\n/**\n * Kills all processes in the process tree.\n *\n * @param tree - Process tree.\n * @param killSignal - Type of kill signal to be used.\n * @param rootPid - Pid of the root process.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction killAll(\n tree: ProcessTree,\n killSignal: string,\n rootPid: string,\n killRoot: boolean,\n callback: AfterKillCallback,\n): void {\n const killed = new Set<string>()\n try {\n Object.keys(tree).forEach(function (pid) {\n tree[pid]!.forEach(function (pidpid) {\n if (!killed.has(pidpid)) {\n killPid(pidpid, killSignal)\n killed.add(pidpid)\n }\n })\n if (pid === rootPid && killRoot && !killed.has(pid)) {\n killPid(pid, killSignal)\n killed.add(pid)\n }\n })\n } catch (err: unknown) {\n if (callback) {\n // @ts-ignore\n callback(err)\n return\n } else {\n throw err\n }\n }\n if (callback) {\n callback()\n }\n}\n\n/**\n * Kills a process.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n */\nfunction killPid(pid: string, killSignal: string) {\n try {\n process.kill(parseInt(pid, 10), killSignal)\n } catch (err) {\n // @ts-ignore\n if (err.code !== 'ESRCH') throw err\n }\n}\n\n/**\n * Builds a process tree.\n *\n * @param parentPid - Pid of the parent process.\n * @param tree - Process tree.\n * @param pidsToProcess - Pids to process.\n * @param spawnChildProcessesList - Function to spawn child processes.\n * @param cb - Callback to run after building the process tree.\n */\nfunction buildProcessTree(\n parentPid: string,\n tree: ProcessTree,\n pidsToProcess: Set<string>,\n spawnChildProcessesList: (parentPid: string) => ReturnType<typeof spawn>,\n cb: () => void,\n) {\n const ps = spawnChildProcessesList(parentPid)\n let allData = ''\n ps.stdout?.on('data', function (data: Buffer) {\n const dataStr = data.toString('ascii')\n allData += dataStr\n })\n\n const onClose = (code: number) => {\n pidsToProcess.delete(parentPid)\n\n if (code !== 0) {\n // no more parent processes\n if (pidsToProcess.size === 0) {\n cb()\n return\n }\n return\n }\n\n allData\n .trim()\n .split('\\n')\n .forEach(function (line) {\n const match = line.match(/^(\\d+)\\s(.*)$/)\n if (match) {\n const pid = match[1]!\n const cmd = match[2]!\n tree[parentPid]!.push(pid)\n tree[pid] = []\n outputDebug(`Killing process ${pid}: ${cmd}`)\n pidsToProcess.add(pid)\n buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb)\n }\n })\n }\n\n ps.on('close', onClose)\n}\n"]}
1
+ {"version":3,"file":"tree-kill.js","sourceRoot":"","sources":["../../../src/public/node/tree-kill.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable jsdoc/require-throws */\n/* eslint-disable no-restricted-imports */\n\nimport {outputDebug} from './output.js'\nimport {spawn} from 'child_process'\n\ntype ProcessTree = Record<string, string[]>\n\ntype AfterKillCallback = (error?: Error) => void\n\n/**\n * Kills the process that calls the method and all its children.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nexport function treeKill(\n pid: number | string = process.pid,\n killSignal = 'SIGTERM',\n killRoot = true,\n callback?: AfterKillCallback,\n): void {\n const after =\n callback ??\n ((error?: Error) => {\n if (error) outputDebug(`Failed to kill process ${pid}: ${error}`)\n })\n adaptedTreeKill(pid, killSignal, killRoot, after)\n}\n\n/**\n * Adapted from https://github.com/pkrumins/node-tree-kill.\n *\n * Our implementation allows to skip killing the root process. This is useful for example when\n * gracefully exiting the 'dev' process, as the default tree-kill implementation will cause it\n * to exit with a non-zero code. Instead, we want to treat it as a graceful termination.\n * In addition, we also add debug logging for better visibility in what tree-kill is doing.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction adaptedTreeKill(\n pid: number | string,\n killSignal: string,\n killRoot: boolean,\n callback: (error?: Error) => void,\n): void {\n const rootPid = typeof pid === 'number' ? pid.toString() : pid\n\n // Security: Validate that the PID is a number to prevent command injection\n if (!/^\\d+$/.test(rootPid)) {\n if (callback) {\n callback(new Error('pid must be a number'))\n return\n } else {\n throw new Error('pid must be a number')\n }\n }\n\n // A map from parent pid to an array of children pids\n const tree: ProcessTree = {}\n tree[rootPid] = []\n\n // A set of pids to visit. We use it to recursively find all the children pids\n const pidsToProcess = new Set<string>()\n pidsToProcess.add(rootPid)\n\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- default handles all Unix-like platforms\n switch (process.platform) {\n case 'win32': {\n // Security: Use spawn instead of exec to avoid shell injection when killing processes on Windows\n const taskkill = spawn('taskkill', ['/pid', rootPid, '/T', '/F'])\n taskkill.on('close', (code: number) => {\n if (callback) {\n if (code === 0) {\n callback()\n } else {\n callback(new Error(`taskkill exited with code ${code}`))\n }\n }\n })\n break\n }\n case 'darwin':\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('pgrep', ['-lfP', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n default:\n buildProcessTree(\n rootPid,\n tree,\n pidsToProcess,\n function (parentPid: string) {\n return spawn('ps', ['-o', 'pid command', '--no-headers', '--ppid', parentPid])\n },\n function () {\n killAll(tree, killSignal, rootPid, killRoot, callback)\n },\n )\n break\n }\n}\n\n/**\n * Kills all processes in the process tree.\n *\n * @param tree - Process tree.\n * @param killSignal - Type of kill signal to be used.\n * @param rootPid - Pid of the root process.\n * @param killRoot - Whether to kill the root process.\n * @param callback - Optional callback to run after killing the processes.\n */\nfunction killAll(\n tree: ProcessTree,\n killSignal: string,\n rootPid: string,\n killRoot: boolean,\n callback: AfterKillCallback,\n): void {\n const killed = new Set<string>()\n try {\n Object.keys(tree).forEach(function (pid) {\n tree[pid]!.forEach(function (pidpid) {\n if (!killed.has(pidpid)) {\n killPid(pidpid, killSignal)\n killed.add(pidpid)\n }\n })\n if (pid === rootPid && killRoot && !killed.has(pid)) {\n killPid(pid, killSignal)\n killed.add(pid)\n }\n })\n } catch (err: unknown) {\n if (callback) {\n // @ts-ignore\n callback(err)\n return\n } else {\n throw err\n }\n }\n if (callback) {\n callback()\n }\n}\n\n/**\n * Kills a process.\n *\n * @param pid - Pid of the process to kill.\n * @param killSignal - Type of kill signal to be used.\n */\nfunction killPid(pid: string, killSignal: string) {\n try {\n process.kill(parseInt(pid, 10), killSignal)\n } catch (err) {\n // @ts-ignore\n if (err.code !== 'ESRCH') throw err\n }\n}\n\n/**\n * Builds a process tree.\n *\n * @param parentPid - Pid of the parent process.\n * @param tree - Process tree.\n * @param pidsToProcess - Pids to process.\n * @param spawnChildProcessesList - Function to spawn child processes.\n * @param cb - Callback to run after building the process tree.\n */\nfunction buildProcessTree(\n parentPid: string,\n tree: ProcessTree,\n pidsToProcess: Set<string>,\n spawnChildProcessesList: (parentPid: string) => ReturnType<typeof spawn>,\n cb: () => void,\n) {\n const ps = spawnChildProcessesList(parentPid)\n let allData = ''\n ps.stdout?.on('data', function (data: Buffer) {\n const dataStr = data.toString('ascii')\n allData += dataStr\n })\n\n const onClose = (code: number) => {\n pidsToProcess.delete(parentPid)\n\n if (code !== 0) {\n // no more parent processes\n if (pidsToProcess.size === 0) {\n cb()\n return\n }\n return\n }\n\n allData\n .trim()\n .split('\\n')\n .forEach(function (line) {\n const match = line.match(/^(\\d+)\\s(.*)$/)\n if (match) {\n const pid = match[1]!\n const cmd = match[2]!\n tree[parentPid]!.push(pid)\n tree[pid] = []\n outputDebug(`Killing process ${pid}: ${cmd}`)\n pidsToProcess.add(pid)\n buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb)\n }\n })\n }\n\n ps.on('close', onClose)\n}\n"]}
@@ -324,6 +324,11 @@ export async function renderConfirmationPrompt({ message, infoTable, confirmatio
324
324
  */
325
325
  export async function renderAutocompletePrompt({ renderOptions, ...props }, uiDebugOptions = defaultUIDebugOptions) {
326
326
  throwInNonTTY({ message: props.message, stdin: renderOptions?.stdin }, uiDebugOptions);
327
+ // The default search filters in-memory choices synchronously, so it doesn't need
328
+ // throttling. Skipping the throttle makes the keystroke-to-result latency feel
329
+ // instant. Callers that supply their own (typically remote/paginated) search keep
330
+ // the component's default throttle unless they opt out via `searchDebounceMs`.
331
+ const usingDefaultSearch = props.search === undefined;
327
332
  const newProps = {
328
333
  search(term) {
329
334
  const lowerTerm = term.toLowerCase();
@@ -333,6 +338,7 @@ export async function renderAutocompletePrompt({ renderOptions, ...props }, uiDe
333
338
  }),
334
339
  });
335
340
  },
341
+ ...(usingDefaultSearch ? { searchDebounceMs: 0 } : {}),
336
342
  ...props,
337
343
  };
338
344
  return runWithTimer('cmd_all_timing_prompts_ms')(async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable tsdoc/syntax */\nimport {AbortError, AbortSilentError, FatalError as Fatal} from './error.js'\nimport {outputContent, outputDebug, outputToken, TokenizedString} from './output.js'\nimport {terminalSupportsPrompting} from './system.js'\nimport {AbortController} from './abort.js'\nimport {runWithTimer} from './metadata.js'\nimport {ConcurrentOutput, ConcurrentOutputProps} from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {handleCtrlC, render, renderOnce} from '../../private/node/ui.js'\nimport {alert, AlertOptions} from '../../private/node/ui/alert.js'\nimport {CustomSection} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport ScalarDict from '../../private/node/ui/components/Table/ScalarDict.js'\nimport {Table, TableColumn, TableProps} from '../../private/node/ui/components/Table/Table.js'\nimport {\n Token,\n tokenItemToString,\n InlineToken,\n LinkToken,\n ListToken,\n TokenItem,\n} from '../../private/node/ui/components/TokenizedText.js'\nimport {\n DangerousConfirmationPrompt,\n DangerousConfirmationPromptProps,\n} from '../../private/node/ui/components/DangerousConfirmationPrompt.js'\nimport {SelectPrompt, SelectPromptProps} from '../../private/node/ui/components/SelectPrompt.js'\nimport {Tasks, Task} from '../../private/node/ui/components/Tasks.js'\nimport {TextPrompt, TextPromptProps} from '../../private/node/ui/components/TextPrompt.js'\nimport {AutocompletePromptProps, AutocompletePrompt} from '../../private/node/ui/components/AutocompletePrompt.js'\nimport {InfoTableSection} from '../../private/node/ui/components/Prompts/InfoTable.js'\nimport {InfoMessageProps} from '../../private/node/ui/components/Prompts/InfoMessage.js'\nimport {SingleTask} from '../../private/node/ui/components/SingleTask.js'\n\nimport React from 'react'\nimport {Key as InkKey, RenderOptions} from 'ink'\n\ntype PartialBy<T, TKey extends keyof T> = Omit<T, TKey> & Partial<Pick<T, TKey>>\n\ninterface UIDebugOptions {\n /** If true, don't check if the current terminal is interactive or not */\n skipTTYCheck?: boolean\n}\nconst defaultUIDebugOptions: UIDebugOptions = {\n skipTTYCheck: false,\n}\n\nexport interface RenderConcurrentOptions extends PartialBy<ConcurrentOutputProps, 'abortSignal'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n * @example\n * 00:00:00 │ backend │ first backend message\n * 00:00:00 │ backend │ second backend message\n * 00:00:00 │ backend │ third backend message\n * 00:00:00 │ frontend │ first frontend message\n * 00:00:00 │ frontend │ second frontend message\n * 00:00:00 │ frontend │ third frontend message\n *\n */\nexport async function renderConcurrent({renderOptions, ...props}: RenderConcurrentOptions) {\n const abortSignal = props.abortSignal ?? new AbortController().signal\n\n return render(<ConcurrentOutput {...props} abortSignal={abortSignal} />, renderOptions)\n}\n\nexport type AlertCustomSection = CustomSection\nexport type RenderAlertOptions = Omit<AlertOptions, 'type'>\n\n/**\n * Renders an information banner to the console.\n * @example Basic\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ CLI update available. │\n * │ │\n * │ Run `npm run shopify upgrade`. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ my-app initialized and ready to build. │\n * │ │\n * │ Next steps │\n * │ • Run `cd verification-app` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Dev docs [1] │\n * │ │\n * │ Custom section │\n * │ • Item 1 [2] │\n * │ • Item 2 │\n * │ • Item 3 [3] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev\n * [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s\n * 9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo\n * 35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j\n * 69i60.2711j0j7&sourceid=chrome&ie=UTF-8\n * [3] https://shopify.com\n *\n */\nexport function renderInfo(options: RenderAlertOptions) {\n return alert({...options, type: 'info'})\n}\n\n/**\n * Renders a success banner to the console.\n * @example Basic\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ CLI updated. │\n * │ │\n * │ You are now running version 3.47. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Deployment successful. │\n * │ │\n * │ Your extensions have been uploaded to your Shopify │\n * │ Partners Dashboard. │\n * │ │\n * │ Next steps │\n * │ • See your deployment and set it live [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/1797046/apps/4523695/deploy\n * ments\n *\n */\nexport function renderSuccess(options: RenderAlertOptions) {\n return alert({...options, type: 'success'})\n}\n\n/**\n * Renders a warning banner to the console.\n * @example Basic\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ You have reached your limit of checkout extensions for │\n * │ this app. │\n * │ │\n * │ You can free up space for a new one by deleting an │\n * │ existing one. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Required access scope update. │\n * │ │\n * │ The deadline for re-selecting your app scopes is May │\n * │ 1, 2022. │\n * │ │\n * │ Reference │\n * │ • Dev docs [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev/app/scopes\n *\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders an error banner to the console.\n * @example\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Version couldn't be released. │\n * │ │\n * │ This version needs to be submitted for review and │\n * │ approved by Shopify before it can be released. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n */\nexport function renderError(options: RenderAlertOptions) {\n return alert({...options, type: 'error'})\n}\n\ninterface RenderFatalErrorOptions {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n * @example Basic\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Something went wrong. │\n * │ │\n * │ To investigate the issue, examine this stack trace: │\n * │ at _compile (internal/modules/cjs/loader.js:1137) │\n * │ at js (internal/modules/cjs/loader.js:1157) │\n * │ at load (internal/modules/cjs/loader.js:985) │\n * │ at _load (internal/modules/cjs/loader.js:878) │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ No Organization found │\n * │ │\n * │ Next steps │\n * │ • Have you created a Shopify Partners organization │\n * │ [1]? │\n * │ • Have you confirmed your accounts from the emails │\n * │ you received? │\n * │ • Need to connect to a different App or │\n * │ organization? Run the command again with `--reset` │\n * │ │\n * │ amortizable-marketplace-ext │\n * │ • Some other error │\n * │ Validation errors │\n * │ • Missing expected key(s). │\n * │ │\n * │ amortizable-marketplace-ext-2 │\n * │ • Something was not found │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/signup\n *\n */\n\nexport function renderFatalError(error: Fatal, {renderOptions}: RenderFatalErrorOptions = {}) {\n return renderOnce(<FatalError error={error} />, {logLevel: 'error', renderOptions})\n}\n\nexport interface RenderSelectPromptOptions<T> extends Omit<SelectPromptProps<T>, 'onSubmit'> {\n isConfirmationPrompt?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a select prompt to the console.\n * @example\n * ? Associate your project with the org Castile Ventures?\n *\n * ┃ Add\n * ┃ • new-ext\n * ┃\n * ┃ Remove\n * ┃ • integrated-demand-ext\n * ┃ • order-discount\n *\n * Automations\n * > fifth\n * sixth\n *\n * Merchant Admin\n * eighth\n * ninth\n *\n * Other\n * first\n * second\n * third (limit reached)\n * fourth\n * seventh\n * tenth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderSelectPrompt<T>(\n {renderOptions, isConfirmationPrompt, ...props}: RenderSelectPromptOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T\n await render(\n <SelectPrompt\n {...props}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return selectedValue!\n })\n}\n\nexport interface RenderConfirmationPromptOptions extends Pick<\n SelectPromptProps<boolean>,\n 'message' | 'infoTable' | 'infoMessage' | 'abortSignal'\n> {\n confirmationMessage?: string\n cancellationMessage?: string\n renderOptions?: RenderOptions\n defaultValue?: boolean\n}\n\n/**\n * Renders a confirmation prompt to the console.\n * @example\n * ? Delete the following themes from the store?\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n * ┃\n * ┃ • first theme (#1)\n * ┃ • second theme (#2)\n *\n * > (y) Yes, confirm changes\n * (n) Cancel\n *\n * Press ↑↓ arrows to select, enter or a shortcut to\n * confirm.\n *\n */\nexport async function renderConfirmationPrompt({\n message,\n infoTable,\n confirmationMessage = 'Yes, confirm',\n cancellationMessage = 'No, cancel',\n renderOptions,\n defaultValue = true,\n abortSignal,\n infoMessage,\n}: RenderConfirmationPromptOptions): Promise<boolean> {\n const choices = [\n {\n label: confirmationMessage,\n value: true,\n key: 'y',\n },\n {\n label: cancellationMessage,\n value: false,\n key: 'n',\n },\n ]\n\n return renderSelectPrompt({\n choices,\n message,\n infoTable,\n renderOptions,\n defaultValue,\n isConfirmationPrompt: true,\n abortSignal,\n infoMessage,\n })\n}\n\nexport interface RenderAutocompleteOptions<T> extends PartialBy<\n Omit<AutocompletePromptProps<T>, 'onSubmit'>,\n 'search'\n> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders an autocomplete prompt to the console.\n * @example\n * ? Select a template: Type to search...\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n *\n * > first\n * second\n * third\n * fourth\n * fifth\n * sixth\n * seventh\n * eighth\n * ninth\n * tenth\n * eleventh\n * twelfth\n * thirteenth\n * fourteenth\n * fifteenth\n * sixteenth\n * seventeenth\n * eighteenth\n * nineteenth (disabled)\n * twentieth\n * twenty-first\n * twenty-second\n * twenty-third\n * twenty-fourth\n * twenty-fifth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderAutocompletePrompt<T>(\n {renderOptions, ...props}: RenderAutocompleteOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n const newProps = {\n search(term: string) {\n const lowerTerm = term.toLowerCase()\n return Promise.resolve({\n data: props.choices.filter((item) => {\n return item.label.toLowerCase().includes(lowerTerm) || item.group?.toLowerCase().includes(lowerTerm)\n }),\n })\n },\n ...props,\n }\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T | undefined\n await render(\n <AutocompletePrompt\n {...newProps}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n\n if (selectedValue === undefined) {\n throw new Error(\n 'Prompt was interrupted before a selection was made. This can happen if the process received a signal, was terminated, or the prompt was aborted.',\n )\n }\n\n return selectedValue\n })\n}\n\ninterface RenderTableOptions<T extends ScalarDict> extends TableProps<T> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a table to the console.\n * @example\n * ID Name email\n * ── ────────── ─────────────\n * 1 John Doe jon@doe.com\n * 2 Jane Doe jane@doe.com\n * 3 John Smith jon@smith.com\n */\nexport function renderTable<T extends ScalarDict>({renderOptions, ...props}: RenderTableOptions<T>) {\n return renderOnce(<Table {...props} />, {renderOptions})\n}\n\ninterface RenderTasksOptions {\n renderOptions?: RenderOptions\n noProgressBar?: boolean\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n * @example\n * Installing dependencies ...\n */\n\nexport async function renderTasks<TContext>(\n tasks: Task<TContext>[],\n {renderOptions, noProgressBar}: RenderTasksOptions = {},\n): Promise<TContext> {\n let taskResult: TContext\n await render(\n <Tasks\n tasks={tasks}\n onComplete={(ctx) => {\n taskResult = ctx\n }}\n noProgressBar={noProgressBar}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderSingleTaskOptions<T> {\n title: TokenizedString\n task: (updateStatus: (status: TokenizedString) => void) => Promise<T>\n onAbort?: () => void\n renderOptions?: RenderOptions\n}\n\n/**\n * Awaits a single task and displays a loading bar while it's in progress. The task's result is returned.\n * @param options - Configuration object\n * @param options.title - The initial title to display with the loading bar\n * @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.\n * @param options.renderOptions - Optional render configuration\n * @returns The result of the task\n * @example\n * Loading app ...\n */\nexport async function renderSingleTask<T>({\n title,\n task,\n onAbort,\n renderOptions,\n}: RenderSingleTaskOptions<T>): Promise<T> {\n let taskResult: T\n await render(\n <SingleTask\n title={title}\n task={task}\n onComplete={(result) => {\n taskResult = result\n }}\n onAbort={onAbort}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderTextPromptOptions extends Omit<TextPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a text prompt to the console.\n * @example\n * ? App project name (can be changed later):\n * > expansive commerce app\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderTextPrompt(\n {renderOptions, ...props}: RenderTextPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<string> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let enteredText = ''\n await render(\n <TextPrompt\n {...props}\n onSubmit={(value: string) => {\n enteredText = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return enteredText\n })\n}\n\nexport interface RenderDangerousConfirmationPromptOptions extends Omit<DangerousConfirmationPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a dangerous confirmation prompt to the console, forcing the user to\n * type a confirmation string to proceed.\n * @example\n * ? Release a new version of nightly-app-2023-06-19?\n *\n * ┃ Includes:\n * ┃ + web-px (new)\n * ┃ + sub-ui-ext\n * ┃ + theme-app-ext\n * ┃ + paymentify (from Partner Dashboard)\n * ┃\n * ┃ Removes:\n * ┃ - prod-discount-fun\n * ┃\n * ┃ This can permanently delete app user data.\n *\n * Type nightly-app-2023-06-19 to confirm, or press Escape\n * to cancel.\n * > █\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderDangerousConfirmationPrompt(\n {renderOptions, ...props}: RenderDangerousConfirmationPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<boolean> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let confirmed: boolean\n await render(\n <DangerousConfirmationPrompt\n {...props}\n onSubmit={(value: boolean) => {\n confirmed = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return confirmed!\n })\n}\n\n/** Waits for any key to be pressed except Ctrl+C which will terminate the process. */\n\nexport const keypress = async (stdin = process.stdin, uiDebugOptions: UIDebugOptions = defaultUIDebugOptions) => {\n throwInNonTTY({message: 'Press any key'}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(() => {\n return new Promise((resolve, reject) => {\n const handler = (buffer: Buffer) => {\n stdin.setRawMode(false)\n\n const bytes = Array.from(buffer)\n\n if (bytes.length && bytes[0] === 3) {\n outputDebug('Canceled keypress, User pressed CTRL+C')\n reject(new AbortSilentError())\n }\n stdin.unref()\n process.nextTick(resolve)\n }\n\n stdin.setRawMode(true)\n stdin.once('data', handler)\n\n // We want to indicate that we're still using stdin, so that the process\n // doesn't exit early.\n stdin.ref()\n })\n })\n}\n\ninterface IsTTYOptions {\n stdin?: NodeJS.ReadStream\n uiDebugOptions?: UIDebugOptions\n}\n\nexport function isTTY({stdin = undefined, uiDebugOptions = defaultUIDebugOptions}: IsTTYOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false should fall through to stdin/terminalSupportsPrompting\n return Boolean(uiDebugOptions.skipTTYCheck || stdin || terminalSupportsPrompting())\n}\n\ninterface ThrowInNonTTYOptions {\n message: TokenItem\n stdin?: NodeJS.ReadStream\n}\n\nfunction throwInNonTTY({message, stdin = undefined}: ThrowInNonTTYOptions, uiDebugOptions: UIDebugOptions) {\n if (isTTY({stdin, uiDebugOptions})) return\n\n const promptText = tokenItemToString(message)\n const errorMessage = `Failed to prompt:\n\n${outputContent`${outputToken.cyan(promptText)}`.value}\n\nThis usually happens when running a command non-interactively, for example in a CI environment, or when piping to or from another process.`\n throw new AbortError(\n errorMessage,\n 'To resolve this, specify the option in the command, or run the command in an interactive environment such as your local terminal.',\n )\n}\n\nexport type Key = InkKey\nexport type InfoMessage = InfoMessageProps['message']\nexport {Token, Task, TokenItem, InlineToken, LinkToken, TableColumn, InfoTableSection, ListToken, render, handleCtrlC}\n"]}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable tsdoc/syntax */\nimport {AbortError, AbortSilentError, FatalError as Fatal} from './error.js'\nimport {outputContent, outputDebug, outputToken, TokenizedString} from './output.js'\nimport {terminalSupportsPrompting} from './system.js'\nimport {AbortController} from './abort.js'\nimport {runWithTimer} from './metadata.js'\nimport {ConcurrentOutput, ConcurrentOutputProps} from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {handleCtrlC, render, renderOnce} from '../../private/node/ui.js'\nimport {alert, AlertOptions} from '../../private/node/ui/alert.js'\nimport {CustomSection} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport ScalarDict from '../../private/node/ui/components/Table/ScalarDict.js'\nimport {Table, TableColumn, TableProps} from '../../private/node/ui/components/Table/Table.js'\nimport {\n Token,\n tokenItemToString,\n InlineToken,\n LinkToken,\n ListToken,\n TokenItem,\n} from '../../private/node/ui/components/TokenizedText.js'\nimport {\n DangerousConfirmationPrompt,\n DangerousConfirmationPromptProps,\n} from '../../private/node/ui/components/DangerousConfirmationPrompt.js'\nimport {SelectPrompt, SelectPromptProps} from '../../private/node/ui/components/SelectPrompt.js'\nimport {Tasks, Task} from '../../private/node/ui/components/Tasks.js'\nimport {TextPrompt, TextPromptProps} from '../../private/node/ui/components/TextPrompt.js'\nimport {AutocompletePromptProps, AutocompletePrompt} from '../../private/node/ui/components/AutocompletePrompt.js'\nimport {InfoTableSection} from '../../private/node/ui/components/Prompts/InfoTable.js'\nimport {InfoMessageProps} from '../../private/node/ui/components/Prompts/InfoMessage.js'\nimport {SingleTask} from '../../private/node/ui/components/SingleTask.js'\n\nimport React from 'react'\nimport {Key as InkKey, RenderOptions} from 'ink'\n\ntype PartialBy<T, TKey extends keyof T> = Omit<T, TKey> & Partial<Pick<T, TKey>>\n\ninterface UIDebugOptions {\n /** If true, don't check if the current terminal is interactive or not */\n skipTTYCheck?: boolean\n}\nconst defaultUIDebugOptions: UIDebugOptions = {\n skipTTYCheck: false,\n}\n\nexport interface RenderConcurrentOptions extends PartialBy<ConcurrentOutputProps, 'abortSignal'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n * @example\n * 00:00:00 │ backend │ first backend message\n * 00:00:00 │ backend │ second backend message\n * 00:00:00 │ backend │ third backend message\n * 00:00:00 │ frontend │ first frontend message\n * 00:00:00 │ frontend │ second frontend message\n * 00:00:00 │ frontend │ third frontend message\n *\n */\nexport async function renderConcurrent({renderOptions, ...props}: RenderConcurrentOptions) {\n const abortSignal = props.abortSignal ?? new AbortController().signal\n\n return render(<ConcurrentOutput {...props} abortSignal={abortSignal} />, renderOptions)\n}\n\nexport type AlertCustomSection = CustomSection\nexport type RenderAlertOptions = Omit<AlertOptions, 'type'>\n\n/**\n * Renders an information banner to the console.\n * @example Basic\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ CLI update available. │\n * │ │\n * │ Run `npm run shopify upgrade`. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ my-app initialized and ready to build. │\n * │ │\n * │ Next steps │\n * │ • Run `cd verification-app` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Dev docs [1] │\n * │ │\n * │ Custom section │\n * │ • Item 1 [2] │\n * │ • Item 2 │\n * │ • Item 3 [3] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev\n * [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s\n * 9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo\n * 35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j\n * 69i60.2711j0j7&sourceid=chrome&ie=UTF-8\n * [3] https://shopify.com\n *\n */\nexport function renderInfo(options: RenderAlertOptions) {\n return alert({...options, type: 'info'})\n}\n\n/**\n * Renders a success banner to the console.\n * @example Basic\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ CLI updated. │\n * │ │\n * │ You are now running version 3.47. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Deployment successful. │\n * │ │\n * │ Your extensions have been uploaded to your Shopify │\n * │ Partners Dashboard. │\n * │ │\n * │ Next steps │\n * │ • See your deployment and set it live [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/1797046/apps/4523695/deploy\n * ments\n *\n */\nexport function renderSuccess(options: RenderAlertOptions) {\n return alert({...options, type: 'success'})\n}\n\n/**\n * Renders a warning banner to the console.\n * @example Basic\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ You have reached your limit of checkout extensions for │\n * │ this app. │\n * │ │\n * │ You can free up space for a new one by deleting an │\n * │ existing one. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Required access scope update. │\n * │ │\n * │ The deadline for re-selecting your app scopes is May │\n * │ 1, 2022. │\n * │ │\n * │ Reference │\n * │ • Dev docs [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev/app/scopes\n *\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders an error banner to the console.\n * @example\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Version couldn't be released. │\n * │ │\n * │ This version needs to be submitted for review and │\n * │ approved by Shopify before it can be released. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n */\nexport function renderError(options: RenderAlertOptions) {\n return alert({...options, type: 'error'})\n}\n\ninterface RenderFatalErrorOptions {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n * @example Basic\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Something went wrong. │\n * │ │\n * │ To investigate the issue, examine this stack trace: │\n * │ at _compile (internal/modules/cjs/loader.js:1137) │\n * │ at js (internal/modules/cjs/loader.js:1157) │\n * │ at load (internal/modules/cjs/loader.js:985) │\n * │ at _load (internal/modules/cjs/loader.js:878) │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ No Organization found │\n * │ │\n * │ Next steps │\n * │ • Have you created a Shopify Partners organization │\n * │ [1]? │\n * │ • Have you confirmed your accounts from the emails │\n * │ you received? │\n * │ • Need to connect to a different App or │\n * │ organization? Run the command again with `--reset` │\n * │ │\n * │ amortizable-marketplace-ext │\n * │ • Some other error │\n * │ Validation errors │\n * │ • Missing expected key(s). │\n * │ │\n * │ amortizable-marketplace-ext-2 │\n * │ • Something was not found │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/signup\n *\n */\n\nexport function renderFatalError(error: Fatal, {renderOptions}: RenderFatalErrorOptions = {}) {\n return renderOnce(<FatalError error={error} />, {logLevel: 'error', renderOptions})\n}\n\nexport interface RenderSelectPromptOptions<T> extends Omit<SelectPromptProps<T>, 'onSubmit'> {\n isConfirmationPrompt?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a select prompt to the console.\n * @example\n * ? Associate your project with the org Castile Ventures?\n *\n * ┃ Add\n * ┃ • new-ext\n * ┃\n * ┃ Remove\n * ┃ • integrated-demand-ext\n * ┃ • order-discount\n *\n * Automations\n * > fifth\n * sixth\n *\n * Merchant Admin\n * eighth\n * ninth\n *\n * Other\n * first\n * second\n * third (limit reached)\n * fourth\n * seventh\n * tenth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderSelectPrompt<T>(\n {renderOptions, isConfirmationPrompt, ...props}: RenderSelectPromptOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T\n await render(\n <SelectPrompt\n {...props}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return selectedValue!\n })\n}\n\nexport interface RenderConfirmationPromptOptions extends Pick<\n SelectPromptProps<boolean>,\n 'message' | 'infoTable' | 'infoMessage' | 'abortSignal'\n> {\n confirmationMessage?: string\n cancellationMessage?: string\n renderOptions?: RenderOptions\n defaultValue?: boolean\n}\n\n/**\n * Renders a confirmation prompt to the console.\n * @example\n * ? Delete the following themes from the store?\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n * ┃\n * ┃ • first theme (#1)\n * ┃ • second theme (#2)\n *\n * > (y) Yes, confirm changes\n * (n) Cancel\n *\n * Press ↑↓ arrows to select, enter or a shortcut to\n * confirm.\n *\n */\nexport async function renderConfirmationPrompt({\n message,\n infoTable,\n confirmationMessage = 'Yes, confirm',\n cancellationMessage = 'No, cancel',\n renderOptions,\n defaultValue = true,\n abortSignal,\n infoMessage,\n}: RenderConfirmationPromptOptions): Promise<boolean> {\n const choices = [\n {\n label: confirmationMessage,\n value: true,\n key: 'y',\n },\n {\n label: cancellationMessage,\n value: false,\n key: 'n',\n },\n ]\n\n return renderSelectPrompt({\n choices,\n message,\n infoTable,\n renderOptions,\n defaultValue,\n isConfirmationPrompt: true,\n abortSignal,\n infoMessage,\n })\n}\n\nexport interface RenderAutocompleteOptions<T> extends PartialBy<\n Omit<AutocompletePromptProps<T>, 'onSubmit'>,\n 'search'\n> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders an autocomplete prompt to the console.\n * @example\n * ? Select a template: Type to search...\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n *\n * > first\n * second\n * third\n * fourth\n * fifth\n * sixth\n * seventh\n * eighth\n * ninth\n * tenth\n * eleventh\n * twelfth\n * thirteenth\n * fourteenth\n * fifteenth\n * sixteenth\n * seventeenth\n * eighteenth\n * nineteenth (disabled)\n * twentieth\n * twenty-first\n * twenty-second\n * twenty-third\n * twenty-fourth\n * twenty-fifth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderAutocompletePrompt<T>(\n {renderOptions, ...props}: RenderAutocompleteOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n // The default search filters in-memory choices synchronously, so it doesn't need\n // throttling. Skipping the throttle makes the keystroke-to-result latency feel\n // instant. Callers that supply their own (typically remote/paginated) search keep\n // the component's default throttle unless they opt out via `searchDebounceMs`.\n const usingDefaultSearch = props.search === undefined\n const newProps = {\n search(term: string) {\n const lowerTerm = term.toLowerCase()\n return Promise.resolve({\n data: props.choices.filter((item) => {\n return item.label.toLowerCase().includes(lowerTerm) || item.group?.toLowerCase().includes(lowerTerm)\n }),\n })\n },\n ...(usingDefaultSearch ? {searchDebounceMs: 0} : {}),\n ...props,\n }\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T | undefined\n await render(\n <AutocompletePrompt\n {...newProps}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n\n if (selectedValue === undefined) {\n throw new Error(\n 'Prompt was interrupted before a selection was made. This can happen if the process received a signal, was terminated, or the prompt was aborted.',\n )\n }\n\n return selectedValue\n })\n}\n\ninterface RenderTableOptions<T extends ScalarDict> extends TableProps<T> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a table to the console.\n * @example\n * ID Name email\n * ── ────────── ─────────────\n * 1 John Doe jon@doe.com\n * 2 Jane Doe jane@doe.com\n * 3 John Smith jon@smith.com\n */\nexport function renderTable<T extends ScalarDict>({renderOptions, ...props}: RenderTableOptions<T>) {\n return renderOnce(<Table {...props} />, {renderOptions})\n}\n\ninterface RenderTasksOptions {\n renderOptions?: RenderOptions\n noProgressBar?: boolean\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n * @example\n * Installing dependencies ...\n */\n\nexport async function renderTasks<TContext>(\n tasks: Task<TContext>[],\n {renderOptions, noProgressBar}: RenderTasksOptions = {},\n): Promise<TContext> {\n let taskResult: TContext\n await render(\n <Tasks\n tasks={tasks}\n onComplete={(ctx) => {\n taskResult = ctx\n }}\n noProgressBar={noProgressBar}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderSingleTaskOptions<T> {\n title: TokenizedString\n task: (updateStatus: (status: TokenizedString) => void) => Promise<T>\n onAbort?: () => void\n renderOptions?: RenderOptions\n}\n\n/**\n * Awaits a single task and displays a loading bar while it's in progress. The task's result is returned.\n * @param options - Configuration object\n * @param options.title - The initial title to display with the loading bar\n * @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.\n * @param options.renderOptions - Optional render configuration\n * @returns The result of the task\n * @example\n * Loading app ...\n */\nexport async function renderSingleTask<T>({\n title,\n task,\n onAbort,\n renderOptions,\n}: RenderSingleTaskOptions<T>): Promise<T> {\n let taskResult: T\n await render(\n <SingleTask\n title={title}\n task={task}\n onComplete={(result) => {\n taskResult = result\n }}\n onAbort={onAbort}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderTextPromptOptions extends Omit<TextPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a text prompt to the console.\n * @example\n * ? App project name (can be changed later):\n * > expansive commerce app\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderTextPrompt(\n {renderOptions, ...props}: RenderTextPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<string> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let enteredText = ''\n await render(\n <TextPrompt\n {...props}\n onSubmit={(value: string) => {\n enteredText = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return enteredText\n })\n}\n\nexport interface RenderDangerousConfirmationPromptOptions extends Omit<DangerousConfirmationPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a dangerous confirmation prompt to the console, forcing the user to\n * type a confirmation string to proceed.\n * @example\n * ? Release a new version of nightly-app-2023-06-19?\n *\n * ┃ Includes:\n * ┃ + web-px (new)\n * ┃ + sub-ui-ext\n * ┃ + theme-app-ext\n * ┃ + paymentify (from Partner Dashboard)\n * ┃\n * ┃ Removes:\n * ┃ - prod-discount-fun\n * ┃\n * ┃ This can permanently delete app user data.\n *\n * Type nightly-app-2023-06-19 to confirm, or press Escape\n * to cancel.\n * > █\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderDangerousConfirmationPrompt(\n {renderOptions, ...props}: RenderDangerousConfirmationPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<boolean> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let confirmed: boolean\n await render(\n <DangerousConfirmationPrompt\n {...props}\n onSubmit={(value: boolean) => {\n confirmed = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return confirmed!\n })\n}\n\n/** Waits for any key to be pressed except Ctrl+C which will terminate the process. */\n\nexport const keypress = async (stdin = process.stdin, uiDebugOptions: UIDebugOptions = defaultUIDebugOptions) => {\n throwInNonTTY({message: 'Press any key'}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(() => {\n return new Promise((resolve, reject) => {\n const handler = (buffer: Buffer) => {\n stdin.setRawMode(false)\n\n const bytes = Array.from(buffer)\n\n if (bytes.length && bytes[0] === 3) {\n outputDebug('Canceled keypress, User pressed CTRL+C')\n reject(new AbortSilentError())\n }\n stdin.unref()\n process.nextTick(resolve)\n }\n\n stdin.setRawMode(true)\n stdin.once('data', handler)\n\n // We want to indicate that we're still using stdin, so that the process\n // doesn't exit early.\n stdin.ref()\n })\n })\n}\n\ninterface IsTTYOptions {\n stdin?: NodeJS.ReadStream\n uiDebugOptions?: UIDebugOptions\n}\n\nexport function isTTY({stdin = undefined, uiDebugOptions = defaultUIDebugOptions}: IsTTYOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false should fall through to stdin/terminalSupportsPrompting\n return Boolean(uiDebugOptions.skipTTYCheck || stdin || terminalSupportsPrompting())\n}\n\ninterface ThrowInNonTTYOptions {\n message: TokenItem\n stdin?: NodeJS.ReadStream\n}\n\nfunction throwInNonTTY({message, stdin = undefined}: ThrowInNonTTYOptions, uiDebugOptions: UIDebugOptions) {\n if (isTTY({stdin, uiDebugOptions})) return\n\n const promptText = tokenItemToString(message)\n const errorMessage = `Failed to prompt:\n\n${outputContent`${outputToken.cyan(promptText)}`.value}\n\nThis usually happens when running a command non-interactively, for example in a CI environment, or when piping to or from another process.`\n throw new AbortError(\n errorMessage,\n 'To resolve this, specify the option in the command, or run the command in an interactive environment such as your local terminal.',\n )\n}\n\nexport type Key = InkKey\nexport type InfoMessage = InfoMessageProps['message']\nexport {Token, Task, TokenItem, InlineToken, LinkToken, TableColumn, InfoTableSection, ListToken, render, handleCtrlC}\n"]}