@shopify/cli-kit 3.31.1 → 3.32.1

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 (252) hide show
  1. package/README.md +1 -1
  2. package/dist/api.d.ts +2 -5
  3. package/dist/api.js +2 -5
  4. package/dist/api.js.map +1 -1
  5. package/dist/constants.d.ts +1 -0
  6. package/dist/constants.js +1 -0
  7. package/dist/constants.js.map +1 -1
  8. package/dist/environment/local.d.ts +1 -0
  9. package/dist/environment/local.js +4 -1
  10. package/dist/environment/local.js.map +1 -1
  11. package/dist/file.d.ts +10 -3
  12. package/dist/file.js +34 -34
  13. package/dist/file.js.map +1 -1
  14. package/dist/http/fetch.js +1 -1
  15. package/dist/http/fetch.js.map +1 -1
  16. package/dist/http.d.ts +0 -1
  17. package/dist/http.js +0 -1
  18. package/dist/http.js.map +1 -1
  19. package/dist/index.d.ts +0 -8
  20. package/dist/index.js +0 -8
  21. package/dist/index.js.map +1 -1
  22. package/dist/metadata.d.ts +1 -1
  23. package/dist/metadata.js.map +1 -1
  24. package/dist/monorail.d.ts +1 -1
  25. package/dist/monorail.js.map +1 -1
  26. package/dist/npm.js +1 -1
  27. package/dist/npm.js.map +1 -1
  28. package/dist/output.d.ts +2 -2
  29. package/dist/output.js +1 -1
  30. package/dist/output.js.map +1 -1
  31. package/dist/path.d.ts +3 -1
  32. package/dist/path.js +2 -2
  33. package/dist/path.js.map +1 -1
  34. package/dist/plugins.d.ts +1 -1
  35. package/dist/plugins.js.map +1 -1
  36. package/dist/{json.d.ts → private/common/json.d.ts} +0 -0
  37. package/dist/{json.js → private/common/json.js} +0 -0
  38. package/dist/private/common/json.js.map +1 -0
  39. package/dist/private/node/analytics.d.ts +27 -0
  40. package/dist/private/node/analytics.js +57 -0
  41. package/dist/private/node/analytics.js.map +1 -0
  42. package/dist/private/node/api/graphql.d.ts +5 -0
  43. package/dist/private/node/api/graphql.js +63 -0
  44. package/dist/private/node/api/graphql.js.map +1 -0
  45. package/dist/{api/common.d.ts → private/node/api/headers.d.ts} +3 -8
  46. package/dist/{api/common.js → private/node/api/headers.js} +20 -60
  47. package/dist/private/node/api/headers.js.map +1 -0
  48. package/dist/private/node/ui/components/Alert.test.js +5 -5
  49. package/dist/private/node/ui/components/Alert.test.js.map +1 -1
  50. package/dist/private/node/ui/components/Banner.js +5 -5
  51. package/dist/private/node/ui/components/Banner.js.map +1 -1
  52. package/dist/private/node/ui/components/Banner.test.js +11 -11
  53. package/dist/private/node/ui/components/Banner.test.js.map +1 -1
  54. package/dist/private/node/ui/components/Command.test.js +3 -3
  55. package/dist/private/node/ui/components/Command.test.js.map +1 -1
  56. package/dist/private/node/ui/components/ConcurrentOutput.d.ts +2 -2
  57. package/dist/private/node/ui/components/ConcurrentOutput.js +1 -1
  58. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  59. package/dist/private/node/ui/components/ConcurrentOutput.test.js +3 -3
  60. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
  61. package/dist/private/node/ui/components/FatalError.test.js +9 -9
  62. package/dist/private/node/ui/components/FatalError.test.js.map +1 -1
  63. package/dist/private/node/ui/components/FilePath.test.js +3 -3
  64. package/dist/private/node/ui/components/FilePath.test.js.map +1 -1
  65. package/dist/private/node/ui/components/FullScreen.js +11 -9
  66. package/dist/private/node/ui/components/FullScreen.js.map +1 -1
  67. package/dist/private/node/ui/components/Link.test.js +5 -5
  68. package/dist/private/node/ui/components/Link.test.js.map +1 -1
  69. package/dist/private/node/ui/components/List.test.js +5 -5
  70. package/dist/private/node/ui/components/List.test.js.map +1 -1
  71. package/dist/private/node/ui/components/SelectInput.d.ts +2 -2
  72. package/dist/private/node/ui/components/SelectInput.js +16 -24
  73. package/dist/private/node/ui/components/SelectInput.js.map +1 -1
  74. package/dist/private/node/ui/components/SelectInput.test.js +62 -32
  75. package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
  76. package/dist/private/node/ui/components/{Prompt.d.ts → SelectPrompt.d.ts} +4 -3
  77. package/dist/private/node/ui/components/SelectPrompt.js +46 -0
  78. package/dist/private/node/ui/components/SelectPrompt.js.map +1 -0
  79. package/dist/private/node/ui/components/{Prompt.test.d.ts → SelectPrompt.test.d.ts} +0 -0
  80. package/dist/private/node/ui/components/{Prompt.test.js → SelectPrompt.test.js} +7 -6
  81. package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -0
  82. package/dist/private/node/ui/components/Table.js +2 -2
  83. package/dist/private/node/ui/components/Table.js.map +1 -1
  84. package/dist/private/node/ui/components/Tasks.d.ts +1 -1
  85. package/dist/private/node/ui/components/Tasks.js +3 -3
  86. package/dist/private/node/ui/components/Tasks.js.map +1 -1
  87. package/dist/private/node/ui/components/Tasks.test.js +4 -4
  88. package/dist/private/node/ui/components/Tasks.test.js.map +1 -1
  89. package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
  90. package/dist/private/node/ui/components/TextInput.d.ts +9 -0
  91. package/dist/private/node/ui/components/TextInput.js +74 -0
  92. package/dist/private/node/ui/components/TextInput.js.map +1 -0
  93. package/dist/private/node/ui/components/TextInput.test.d.ts +1 -0
  94. package/dist/private/node/ui/components/TextInput.test.js +139 -0
  95. package/dist/private/node/ui/components/TextInput.test.js.map +1 -0
  96. package/dist/private/node/ui/components/TextPrompt.d.ts +8 -0
  97. package/dist/private/node/ui/components/TextPrompt.js +52 -0
  98. package/dist/private/node/ui/components/TextPrompt.js.map +1 -0
  99. package/dist/private/node/ui/components/TextPrompt.test.d.ts +1 -0
  100. package/dist/private/node/ui/components/TextPrompt.test.js +68 -0
  101. package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -0
  102. package/dist/private/node/ui/components/TokenizedText.test.js +3 -3
  103. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
  104. package/dist/private/node/ui/components/UserInput.test.js +3 -3
  105. package/dist/private/node/ui/components/UserInput.test.js.map +1 -1
  106. package/dist/private/node/ui/hooks/use-layout.d.ts +6 -3
  107. package/dist/private/node/ui/hooks/use-layout.js +17 -8
  108. package/dist/private/node/ui/hooks/use-layout.js.map +1 -1
  109. package/dist/private/node/ui.d.ts +2 -3
  110. package/dist/private/node/ui.js +7 -16
  111. package/dist/private/node/ui.js.map +1 -1
  112. package/dist/public/common/array.js +1 -1
  113. package/dist/public/common/array.js.map +1 -1
  114. package/dist/public/common/collection.js +1 -1
  115. package/dist/public/common/collection.js.map +1 -1
  116. package/dist/public/common/function.js +1 -1
  117. package/dist/public/common/function.js.map +1 -1
  118. package/dist/public/common/lang.js +1 -1
  119. package/dist/public/common/lang.js.map +1 -1
  120. package/dist/public/common/object.js +4 -4
  121. package/dist/public/common/object.js.map +1 -1
  122. package/dist/public/common/string.d.ts +55 -1
  123. package/dist/public/common/string.js +93 -1
  124. package/dist/public/common/string.js.map +1 -1
  125. package/dist/public/common/url.d.ts +7 -0
  126. package/dist/public/common/url.js +17 -0
  127. package/dist/public/common/url.js.map +1 -0
  128. package/dist/public/node/abort.d.ts +16 -0
  129. package/dist/public/node/abort.js +17 -0
  130. package/dist/public/node/abort.js.map +1 -0
  131. package/dist/public/node/analytics.d.ts +13 -0
  132. package/dist/public/node/analytics.js +82 -0
  133. package/dist/public/node/analytics.js.map +1 -0
  134. package/dist/public/node/api/admin.d.ts +11 -0
  135. package/dist/public/node/api/admin.js +70 -0
  136. package/dist/public/node/api/admin.js.map +1 -0
  137. package/dist/public/node/api/oxygen.d.ts +22 -0
  138. package/dist/public/node/api/oxygen.js +40 -0
  139. package/dist/public/node/api/oxygen.js.map +1 -0
  140. package/dist/{api → public/node/api}/partners.d.ts +11 -3
  141. package/dist/public/node/api/partners.js +40 -0
  142. package/dist/public/node/api/partners.js.map +1 -0
  143. package/dist/public/node/archiver.js +1 -1
  144. package/dist/public/node/archiver.js.map +1 -1
  145. package/dist/public/node/base-command.js +1 -1
  146. package/dist/public/node/base-command.js.map +1 -1
  147. package/dist/public/node/crypto.d.ts +42 -0
  148. package/dist/public/node/crypto.js +55 -0
  149. package/dist/public/node/crypto.js.map +1 -0
  150. package/dist/public/node/error-handler.js +3 -2
  151. package/dist/public/node/error-handler.js.map +1 -1
  152. package/dist/public/node/framework.js +1 -1
  153. package/dist/public/node/framework.js.map +1 -1
  154. package/dist/public/node/hooks/postrun.js +2 -2
  155. package/dist/public/node/hooks/postrun.js.map +1 -1
  156. package/dist/public/node/hooks/prerun.js +2 -2
  157. package/dist/public/node/hooks/prerun.js.map +1 -1
  158. package/dist/{template.d.ts → public/node/liquid.d.ts} +10 -2
  159. package/dist/{template.js → public/node/liquid.js} +18 -13
  160. package/dist/public/node/liquid.js.map +1 -0
  161. package/dist/public/node/node-package-manager.d.ts +3 -3
  162. package/dist/public/node/node-package-manager.js +1 -1
  163. package/dist/public/node/node-package-manager.js.map +1 -1
  164. package/dist/public/node/os.d.ts +16 -0
  165. package/dist/{os.js → public/node/os.js} +33 -29
  166. package/dist/public/node/os.js.map +1 -0
  167. package/dist/public/node/presets.d.ts +1 -1
  168. package/dist/public/node/presets.js +2 -2
  169. package/dist/public/node/presets.js.map +1 -1
  170. package/dist/public/node/ruby.d.ts +13 -9
  171. package/dist/public/node/ruby.js +91 -23
  172. package/dist/public/node/ruby.js.map +1 -1
  173. package/dist/public/node/tcp.d.ts +2 -0
  174. package/dist/public/node/tcp.js +9 -0
  175. package/dist/public/node/tcp.js.map +1 -1
  176. package/dist/public/node/toml.d.ts +15 -0
  177. package/dist/public/node/toml.js +20 -0
  178. package/dist/public/node/toml.js.map +1 -0
  179. package/dist/public/node/ui.d.ts +12 -17
  180. package/dist/public/node/ui.js +25 -29
  181. package/dist/public/node/ui.js.map +1 -1
  182. package/dist/public/node/vscode.d.ts +14 -0
  183. package/dist/{vscode.js → public/node/vscode.js} +13 -7
  184. package/dist/public/node/vscode.js.map +1 -0
  185. package/dist/session/authorize.d.ts +4 -0
  186. package/dist/session/authorize.js +8 -3
  187. package/dist/session/authorize.js.map +1 -1
  188. package/dist/{api/identity.d.ts → session/identity-token-validation.d.ts} +0 -0
  189. package/dist/{api/identity.js → session/identity-token-validation.js} +1 -1
  190. package/dist/session/identity-token-validation.js.map +1 -0
  191. package/dist/session/redirect-listener.js +6 -3
  192. package/dist/session/redirect-listener.js.map +1 -1
  193. package/dist/session/schema.d.ts +18 -18
  194. package/dist/session/store.js +1 -1
  195. package/dist/session/store.js.map +1 -1
  196. package/dist/session.js +3 -3
  197. package/dist/session.js.map +1 -1
  198. package/dist/system.d.ts +2 -2
  199. package/dist/system.js +1 -1
  200. package/dist/system.js.map +1 -1
  201. package/dist/testing/ui.d.ts +1 -1
  202. package/dist/testing/ui.js +1 -1
  203. package/dist/testing/ui.js.map +1 -1
  204. package/dist/tsconfig.tsbuildinfo +1 -1
  205. package/dist/ui/inquirer/autocomplete.d.ts +2 -2
  206. package/dist/ui/inquirer/autocomplete.js +1 -1
  207. package/dist/ui/inquirer/autocomplete.js.map +1 -1
  208. package/dist/ui/inquirer/input.d.ts +2 -2
  209. package/dist/ui/inquirer/input.js.map +1 -1
  210. package/dist/ui/inquirer/password.d.ts +2 -2
  211. package/dist/ui/inquirer/password.js.map +1 -1
  212. package/dist/ui/inquirer/select.d.ts +2 -2
  213. package/dist/ui/inquirer/select.js +2 -2
  214. package/dist/ui/inquirer/select.js.map +1 -1
  215. package/package.json +30 -27
  216. package/dist/abort.d.ts +0 -1
  217. package/dist/abort.js +0 -2
  218. package/dist/abort.js.map +0 -1
  219. package/dist/analytics.d.ts +0 -44
  220. package/dist/analytics.js +0 -154
  221. package/dist/analytics.js.map +0 -1
  222. package/dist/api/admin.d.ts +0 -3
  223. package/dist/api/admin.js +0 -56
  224. package/dist/api/admin.js.map +0 -1
  225. package/dist/api/common.js.map +0 -1
  226. package/dist/api/identity.js.map +0 -1
  227. package/dist/api/oxygen.d.ts +0 -5
  228. package/dist/api/oxygen.js +0 -30
  229. package/dist/api/oxygen.js.map +0 -1
  230. package/dist/api/partners.js +0 -44
  231. package/dist/api/partners.js.map +0 -1
  232. package/dist/http/graphql.d.ts +0 -13
  233. package/dist/http/graphql.js +0 -12
  234. package/dist/http/graphql.js.map +0 -1
  235. package/dist/id.d.ts +0 -6
  236. package/dist/id.js +0 -18
  237. package/dist/id.js.map +0 -1
  238. package/dist/json.js.map +0 -1
  239. package/dist/os.d.ts +0 -10
  240. package/dist/os.js.map +0 -1
  241. package/dist/private/node/ui/components/Prompt.js +0 -23
  242. package/dist/private/node/ui/components/Prompt.js.map +0 -1
  243. package/dist/private/node/ui/components/Prompt.test.js.map +0 -1
  244. package/dist/string.d.ts +0 -28
  245. package/dist/string.js +0 -77
  246. package/dist/string.js.map +0 -1
  247. package/dist/template.js.map +0 -1
  248. package/dist/toml.d.ts +0 -3
  249. package/dist/toml.js +0 -8
  250. package/dist/toml.js.map +0 -1
  251. package/dist/vscode.d.ts +0 -8
  252. package/dist/vscode.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
  import { OutputProcess } from '../../output.js';
2
2
  import { Fatal } from '../../error.js';
3
3
  import { AlertProps } from '../../private/node/ui/components/Alert.js';
4
- import { Props as PromptProps } from '../../private/node/ui/components/Prompt.js';
4
+ import { Props as SelectPromptProps } from '../../private/node/ui/components/SelectPrompt.js';
5
5
  import { Task } from '../../private/node/ui/components/Tasks.js';
6
- import { AbortController } from 'abort-controller';
6
+ import { Props as TextPromptProps } from '../../private/node/ui/components/TextPrompt.js';
7
7
  import { RenderOptions } from 'ink';
8
+ import { AbortController } from '@shopify/cli-kit/node/abort';
8
9
  interface RenderConcurrentOptions {
9
10
  processes: OutputProcess[];
10
11
  abortController?: AbortController;
@@ -147,6 +148,7 @@ export declare function renderFatalError(error: Fatal): void;
147
148
  * ? Associate your project with the org Castile Ventures?
148
149
  *
149
150
  * Add: • new-ext
151
+ *
150
152
  * Remove: • integrated-demand-ext
151
153
  * • order-discount
152
154
 
@@ -167,23 +169,16 @@ export declare function renderFatalError(error: Fatal): void;
167
169
 
168
170
  * navigate with arrows, enter to select
169
171
  */
170
- export declare function renderPrompt<T>(options: Omit<PromptProps<T>, 'onChoose'>): Promise<T>;
171
- interface ConfirmationProps {
172
- question: string;
173
- infoTable?: PromptProps<boolean>['infoTable'];
174
- }
175
- /**
176
- * Renders a confirmation prompt to the console.
177
- *
178
- * ? Push the following changes to your Partners Dashboard?
179
- * \> (y) Yes, confirm
180
- * (c) Cancel
181
- *
182
- * navigate with arrows, enter to select
183
- */
184
- export declare function renderConfirmation({ question, infoTable }: ConfirmationProps): Promise<boolean>;
172
+ export declare function renderSelectPrompt<T>(props: Omit<SelectPromptProps<T>, 'onSubmit'>): Promise<unknown>;
185
173
  /**
186
174
  * Runs async tasks and displays their progress to the console.
187
175
  */
188
176
  export declare function renderTasks(tasks: Task[]): Promise<void>;
177
+ /**
178
+ * Renders a text prompt to the console.
179
+ *
180
+ * ? What is your name?
181
+ * \> John
182
+ */
183
+ export declare function renderTextPrompt(props: Omit<TextPromptProps, 'onSubmit'>): Promise<unknown>;
189
184
  export {};
@@ -1,11 +1,13 @@
1
1
  import ConcurrentOutput from '../../private/node/ui/components/ConcurrentOutput.js';
2
2
  import { consoleError } from '../../output.js';
3
- import { prompt, render, renderOnce } from '../../private/node/ui.js';
3
+ import { render, renderOnce } from '../../private/node/ui.js';
4
4
  import { alert } from '../../private/node/ui/alert.js';
5
5
  import { FatalError } from '../../private/node/ui/components/FatalError.js';
6
- import Tasks from '../../private/node/ui/components/Tasks.js';
6
+ import { SelectPrompt } from '../../private/node/ui/components/SelectPrompt.js';
7
+ import { Tasks } from '../../private/node/ui/components/Tasks.js';
8
+ import { TextPrompt } from '../../private/node/ui/components/TextPrompt.js';
7
9
  import React from 'react';
8
- import { AbortController } from 'abort-controller';
10
+ import { AbortController } from '@shopify/cli-kit/node/abort';
9
11
  /**
10
12
  * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.
11
13
  */
@@ -151,6 +153,7 @@ export function renderFatalError(error) {
151
153
  * ? Associate your project with the org Castile Ventures?
152
154
  *
153
155
  * Add: • new-ext
156
+ *
154
157
  * Remove: • integrated-demand-ext
155
158
  * • order-discount
156
159
 
@@ -171,32 +174,12 @@ export function renderFatalError(error) {
171
174
 
172
175
  * navigate with arrows, enter to select
173
176
  */
174
- export async function renderPrompt(options) {
175
- return prompt(options);
176
- }
177
- /**
178
- * Renders a confirmation prompt to the console.
179
- *
180
- * ? Push the following changes to your Partners Dashboard?
181
- * \> (y) Yes, confirm
182
- * (c) Cancel
183
- *
184
- * navigate with arrows, enter to select
185
- */
186
- export async function renderConfirmation({ question, infoTable }) {
187
- const choices = [
188
- {
189
- label: 'Yes, confirm',
190
- value: true,
191
- key: 'y',
192
- },
193
- {
194
- label: 'Cancel',
195
- value: false,
196
- key: 'c',
197
- },
198
- ];
199
- return prompt({ message: question, choices, infoTable });
177
+ export function renderSelectPrompt(props) {
178
+ return new Promise((resolve, reject) => {
179
+ render(React.createElement(SelectPrompt, { ...props, onSubmit: (value) => resolve(value) }), {
180
+ exitOnCtrlC: false,
181
+ }).catch(reject);
182
+ });
200
183
  }
201
184
  /**
202
185
  * Runs async tasks and displays their progress to the console.
@@ -204,4 +187,17 @@ export async function renderConfirmation({ question, infoTable }) {
204
187
  export function renderTasks(tasks) {
205
188
  return render(React.createElement(Tasks, { tasks: tasks }));
206
189
  }
190
+ /**
191
+ * Renders a text prompt to the console.
192
+ *
193
+ * ? What is your name?
194
+ * \> John
195
+ */
196
+ export function renderTextPrompt(props) {
197
+ return new Promise((resolve, reject) => {
198
+ render(React.createElement(TextPrompt, { ...props, onSubmit: (value) => resolve(value) }), {
199
+ exitOnCtrlC: false,
200
+ }).catch(reject);
201
+ });
202
+ }
207
203
  //# sourceMappingURL=ui.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,sDAAsD,CAAA;AACnF,OAAO,EAAC,YAAY,EAAgB,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnE,OAAO,EAAC,KAAK,EAAC,MAAM,gCAAgC,CAAA;AAEpD,OAAO,EAAC,UAAU,EAAC,MAAM,gDAAgD,CAAA;AAEzE,OAAO,KAAa,MAAM,2CAA2C,CAAA;AACrE,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAA;AAUhD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,SAAS,EACT,eAAe,EACf,cAAc,GAAG,IAAI,EACrB,aAAa,GAAG,EAAE,GACM;IACxB,OAAO,MAAM,CACX,oBAAC,gBAAgB,IACf,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,eAAe,IAAI,IAAI,eAAe,EAAE,EACzD,cAAc,EAAE,cAAc,GAC9B,EACF,aAAa,CACd,CAAA;AACH,CAAC;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,UAAU,CAAC,OAA2B;IACpD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAA;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,aAAa,CAAC,OAA2B;IACvD,OAAO,KAAK,CAAC,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,OAAO,UAAU,CAAC,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,OAAyC;IAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,CAAA;AACxB,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAC,QAAQ,EAAE,SAAS,EAAoB;IAC/E,MAAM,OAAO,GAAG;QACd;YACE,KAAK,EAAE,cAAc;YACrB,KAAK,EAAE,IAAI;YACX,GAAG,EAAE,GAAG;SACT;QACD;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,KAAK;YACZ,GAAG,EAAE,GAAG;SACT;KACF,CAAA;IAED,OAAO,MAAM,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAC,CAAC,CAAA;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,MAAM,CAAC,oBAAC,KAAK,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAA;AACxC,CAAC","sourcesContent":["import ConcurrentOutput from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {consoleError, OutputProcess} from '../../output.js'\nimport {prompt, render, renderOnce} from '../../private/node/ui.js'\nimport {Fatal} from '../../error.js'\nimport {alert} from '../../private/node/ui/alert.js'\nimport {AlertProps} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport {Props as PromptProps} from '../../private/node/ui/components/Prompt.js'\nimport Tasks, {Task} from '../../private/node/ui/components/Tasks.js'\nimport React from 'react'\nimport {AbortController} from 'abort-controller'\nimport {RenderOptions} from 'ink'\n\ninterface RenderConcurrentOptions {\n processes: OutputProcess[]\n abortController?: AbortController\n showTimestamps?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n */\nexport async function renderConcurrent({\n processes,\n abortController,\n showTimestamps = true,\n renderOptions = {},\n}: RenderConcurrentOptions) {\n return render(\n <ConcurrentOutput\n processes={processes}\n abortController={abortController ?? new AbortController()}\n showTimestamps={showTimestamps}\n />,\n renderOptions,\n )\n}\n\ntype RenderAlertOptions = Omit<AlertProps, 'type'>\n\n/**\n * Renders an information banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Body │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\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 * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\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 *\n * Basic:\n *\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\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 * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\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 *\n * Basic:\n *\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\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 * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n *\n * ```\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Couldn't connect to the Shopify Partner Dashboard. │\n * │ │\n * │ Check your internet connection and try again. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderFatalError(error: Fatal) {\n return renderOnce(<FatalError error={error} />, 'error', consoleError)\n}\n\n/**\n * Renders a select prompt to the console.\n *\n * ? Associate your project with the org Castile Ventures?\n *\n * Add: • new-ext\n * Remove: • integrated-demand-ext\n * • order-discount\n\n * \\> (f) first\n * (s) second\n * (3) third\n * (4) fourth\n * (5) seventh\n * (6) tenth\n\n * Automations\n * (7) fifth\n * (8) sixth\n\n * Merchant Admin\n * (9) eighth\n * (10) ninth\n\n * navigate with arrows, enter to select\n */\nexport async function renderPrompt<T>(options: Omit<PromptProps<T>, 'onChoose'>) {\n return prompt(options)\n}\n\ninterface ConfirmationProps {\n question: string\n infoTable?: PromptProps<boolean>['infoTable']\n}\n\n/**\n * Renders a confirmation prompt to the console.\n *\n * ? Push the following changes to your Partners Dashboard?\n * \\> (y) Yes, confirm\n * (c) Cancel\n *\n * navigate with arrows, enter to select\n */\nexport async function renderConfirmation({question, infoTable}: ConfirmationProps) {\n const choices = [\n {\n label: 'Yes, confirm',\n value: true,\n key: 'y',\n },\n {\n label: 'Cancel',\n value: false,\n key: 'c',\n },\n ]\n\n return prompt({message: question, choices, infoTable})\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n */\nexport function renderTasks(tasks: Task[]) {\n return render(<Tasks tasks={tasks} />)\n}\n"]}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"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","sourcesContent":["import ConcurrentOutput from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {consoleError, OutputProcess} from '../../output.js'\nimport {render, renderOnce} from '../../private/node/ui.js'\nimport {Fatal} from '../../error.js'\nimport {alert} from '../../private/node/ui/alert.js'\nimport {AlertProps} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport {SelectPrompt, Props as SelectPromptProps} from '../../private/node/ui/components/SelectPrompt.js'\nimport {Tasks, Task} from '../../private/node/ui/components/Tasks.js'\nimport {TextPrompt, Props as TextPromptProps} from '../../private/node/ui/components/TextPrompt.js'\nimport React from 'react'\nimport {RenderOptions} from 'ink'\nimport {AbortController} from '@shopify/cli-kit/node/abort'\n\ninterface RenderConcurrentOptions {\n processes: OutputProcess[]\n abortController?: AbortController\n showTimestamps?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n */\nexport async function renderConcurrent({\n processes,\n abortController,\n showTimestamps = true,\n renderOptions = {},\n}: RenderConcurrentOptions) {\n return render(\n <ConcurrentOutput\n processes={processes}\n abortController={abortController ?? new AbortController()}\n showTimestamps={showTimestamps}\n />,\n renderOptions,\n )\n}\n\ntype RenderAlertOptions = Omit<AlertProps, 'type'>\n\n/**\n * Renders an information banner to the console.\n *\n * Basic:\n *\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Body │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\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 * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\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 *\n * Basic:\n *\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\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 * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\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 *\n * Basic:\n *\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n *\n * Complete:\n * ```\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Title │\n * │ │\n * │ Body │\n * │ │\n * │ Next steps │\n * │ • Run `cd santorini-goods` │\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 * │ • Press 'return' to open the dev docs: │\n * │ https://shopify.dev │\n * │ │\n * │ Link: https://shopify.com │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n *\n * ```\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Couldn't connect to the Shopify Partner Dashboard. │\n * │ │\n * │ Check your internet connection and try again. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * ```\n */\nexport function renderFatalError(error: Fatal) {\n return renderOnce(<FatalError error={error} />, 'error', consoleError)\n}\n\n/**\n * Renders a select prompt to the console.\n *\n * ? Associate your project with the org Castile Ventures?\n *\n * Add: • new-ext\n *\n * Remove: • integrated-demand-ext\n * • order-discount\n\n * \\> (f) first\n * (s) second\n * (3) third\n * (4) fourth\n * (5) seventh\n * (6) tenth\n\n * Automations\n * (7) fifth\n * (8) sixth\n\n * Merchant Admin\n * (9) eighth\n * (10) ninth\n\n * navigate with arrows, enter to select\n */\nexport function renderSelectPrompt<T>(props: Omit<SelectPromptProps<T>, 'onSubmit'>) {\n return new Promise((resolve, reject) => {\n render(<SelectPrompt {...props} onSubmit={(value: T) => resolve(value)} />, {\n exitOnCtrlC: false,\n }).catch(reject)\n })\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n */\nexport function renderTasks(tasks: Task[]) {\n return render(<Tasks tasks={tasks} />)\n}\n\n/**\n * Renders a text prompt to the console.\n *\n * ? What is your name?\n * \\> John\n */\nexport function renderTextPrompt(props: Omit<TextPromptProps, 'onSubmit'>) {\n return new Promise((resolve, reject) => {\n render(<TextPrompt {...props} onSubmit={(value: string) => resolve(value)} />, {\n exitOnCtrlC: false,\n }).catch(reject)\n })\n}\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Check if user editor is VS Code.
3
+ *
4
+ * @param root - Root directory to start searching for .vscode directory.
5
+ * @returns True if user editor is VS Code.
6
+ */
7
+ export declare function isVSCode(root?: string): Promise<boolean>;
8
+ /**
9
+ * Add VSCode extension recommendations.
10
+ *
11
+ * @param directory - Directory that contains the .vscode folder.
12
+ * @param recommendations - List of VSCode extensions to recommend.
13
+ */
14
+ export declare function addRecommendedExtensions(directory: string, recommendations: string[]): Promise<void>;
@@ -1,19 +1,25 @@
1
- import { exists, write, read } from './file.js';
2
- import { findUp, join } from './path.js';
3
- import { content, token, debug } from './output.js';
1
+ import { exists, write, read } from '../../file.js';
2
+ import { findUp, join } from '../../path.js';
3
+ import { content, token, debug } from '../../output.js';
4
4
  /**
5
- * Check if user editor is VS Code
5
+ * Check if user editor is VS Code.
6
+ *
7
+ * @param root - Root directory to start searching for .vscode directory.
8
+ * @returns True if user editor is VS Code.
6
9
  */
7
- export const isVSCode = async (root = process.cwd()) => {
10
+ export async function isVSCode(root = process.cwd()) {
8
11
  debug(content `Checking if the directory ${token.path(root)} or any of its parents has a .vscode directory... `);
9
12
  const config = await findUp(join(root, '.vscode'), { type: 'directory' });
10
13
  if (!config) {
11
14
  return false;
12
15
  }
13
16
  return exists(config);
14
- };
17
+ }
15
18
  /**
16
- * Add VSCode extension recommendations
19
+ * Add VSCode extension recommendations.
20
+ *
21
+ * @param directory - Directory that contains the .vscode folder.
22
+ * @param recommendations - List of VSCode extensions to recommend.
17
23
  */
18
24
  export async function addRecommendedExtensions(directory, recommendations) {
19
25
  debug(content `Adding VSCode recommended extensions at ${token.path(directory)}:
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vscode.js","sourceRoot":"","sources":["../../../src/public/node/vscode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAC,MAAM,eAAe,CAAA;AACjD,OAAO,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAC,MAAM,iBAAiB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACjD,KAAK,CAAC,OAAO,CAAA,6BAA6B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IAC/G,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAC,IAAI,EAAE,WAAW,EAAC,CAAC,CAAA;IAEvE,IAAI,CAAC,MAAM,EAAE;QACX,OAAO,KAAK,CAAA;KACb;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,SAAiB,EAAE,eAAyB;IACzF,KAAK,CAAC,OAAO,CAAA,2CAA2C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;EAC7E,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;GAC1B,CAAC,CAAA;IACF,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAA;IAEjE,IAAI,MAAM,QAAQ,CAAC,SAAS,CAAC,EAAE;QAC7B,IAAI,sBAAsB,GAAG,EAAC,eAAe,EAAE,EAAE,EAAC,CAAA;QAClD,IAAI,MAAM,MAAM,CAAC,cAAc,CAAC,EAAE;YAChC,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,CAAA;YACzD,sBAAsB,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAA;SAC5D;QACD,MAAM,iBAAiB,GAAG;YACxB,GAAG,sBAAsB;YACzB,eAAe,EAAE,CAAC,GAAG,sBAAsB,CAAC,eAAe,EAAE,GAAG,eAAe,CAAC;SACjF,CAAA;QACD,MAAM,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;KACxE;AACH,CAAC","sourcesContent":["import {exists, write, read} from '../../file.js'\nimport {findUp, join} from '../../path.js'\nimport {content, token, debug} from '../../output.js'\n\n/**\n * Check if user editor is VS Code.\n *\n * @param root - Root directory to start searching for .vscode directory.\n * @returns True if user editor is VS Code.\n */\nexport async function isVSCode(root = process.cwd()): Promise<boolean> {\n debug(content`Checking if the directory ${token.path(root)} or any of its parents has a .vscode directory... `)\n const config = await findUp(join(root, '.vscode'), {type: 'directory'})\n\n if (!config) {\n return false\n }\n\n return exists(config)\n}\n\n/**\n * Add VSCode extension recommendations.\n *\n * @param directory - Directory that contains the .vscode folder.\n * @param recommendations - List of VSCode extensions to recommend.\n */\nexport async function addRecommendedExtensions(directory: string, recommendations: string[]): Promise<void> {\n debug(content`Adding VSCode recommended extensions at ${token.path(directory)}:\n${token.json(recommendations)}\n `)\n const extensionsPath = join(directory, '.vscode/extensions.json')\n\n if (await isVSCode(directory)) {\n let originalExtensionsJson = {recommendations: []}\n if (await exists(extensionsPath)) {\n const originalExtensionsFile = await read(extensionsPath)\n originalExtensionsJson = JSON.parse(originalExtensionsFile)\n }\n const newExtensionsJson = {\n ...originalExtensionsJson,\n recommendations: [...originalExtensionsJson.recommendations, ...recommendations],\n }\n await write(extensionsPath, JSON.stringify(newExtensionsJson, null, 2))\n }\n}\n"]}
@@ -5,3 +5,7 @@ export interface CodeAuthResult {
5
5
  codeVerifier: string;
6
6
  }
7
7
  export declare function authorize(scopes: string[], state?: string): Promise<CodeAuthResult>;
8
+ export declare function generateRandomChallengePair(): {
9
+ codeVerifier: string;
10
+ codeChallenge: string;
11
+ };
@@ -1,20 +1,19 @@
1
1
  import { listenRedirect } from './redirect-listener.js';
2
2
  import { clientId } from './identity.js';
3
- import { generateRandomChallengePair, randomHex } from '../string.js';
3
+ import { base64URLEncode, randomBytes, randomHex, sha256 } from '../public/node/crypto.js';
4
4
  import { open } from '../system.js';
5
5
  import { Abort, CancelExecution } from '../error.js';
6
6
  import { identity as identityFqdn } from '../environment/fqdn.js';
7
7
  import * as output from '../output.js';
8
8
  import { keypress, terminateBlockingPortProcessPrompt } from '../ui.js';
9
9
  import { checkPort as isPortAvailable } from 'get-port-please';
10
- import { killPortProcess } from 'kill-port-process';
11
10
  export const MismatchStateError = new Abort("The state received from the authentication doesn't match the one that initiated the authentication process.");
12
11
  export async function authorize(scopes, state = randomHex(30)) {
13
12
  const port = 3456;
14
13
  const host = '127.0.0.1';
15
14
  const redirectUri = `http://${host}:${port}`;
16
15
  const fqdn = await identityFqdn();
17
- const identityClientId = await clientId();
16
+ const identityClientId = clientId();
18
17
  await validateRedirectionPortAvailability(port);
19
18
  let url = `http://${fqdn}/oauth/authorize`;
20
19
  const { codeVerifier, codeChallenge } = generateRandomChallengePair();
@@ -38,7 +37,13 @@ export async function authorize(scopes, state = randomHex(30)) {
38
37
  }
39
38
  return { code: result.code, codeVerifier };
40
39
  }
40
+ export function generateRandomChallengePair() {
41
+ const codeVerifier = base64URLEncode(randomBytes(32));
42
+ const codeChallenge = base64URLEncode(sha256(codeVerifier));
43
+ return { codeVerifier, codeChallenge };
44
+ }
41
45
  async function validateRedirectionPortAvailability(port) {
46
+ const { killPortProcess } = await import('kill-port-process');
42
47
  if (await isPortAvailable(port)) {
43
48
  return;
44
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/session/authorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,2BAA2B,EAAE,SAAS,EAAC,MAAM,cAAc,CAAA;AACnE,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAAC,KAAK,EAAE,eAAe,EAAC,MAAM,aAAa,CAAA;AAClD,OAAO,EAAC,QAAQ,IAAI,YAAY,EAAC,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,MAAM,MAAM,cAAc,CAAA;AACtC,OAAO,EAAC,QAAQ,EAAE,kCAAkC,EAAC,MAAM,UAAU,CAAA;AACrE,OAAO,EAAC,SAAS,IAAI,eAAe,EAAC,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AAEjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,KAAK,CACzC,6GAA6G,CAC9G,CAAA;AAOD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAgB,EAAE,QAAgB,SAAS,CAAC,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,IAAI,GAAG,WAAW,CAAA;IACxB,MAAM,WAAW,GAAG,UAAU,IAAI,IAAI,IAAI,EAAE,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IACjC,MAAM,gBAAgB,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEzC,MAAM,mCAAmC,CAAC,IAAI,CAAC,CAAA;IAE/C,IAAI,GAAG,GAAG,UAAU,IAAI,kBAAkB,CAAA;IAE1C,MAAM,EAAC,YAAY,EAAE,aAAa,EAAC,GAAG,2BAA2B,EAAE,CAAA;IAEnE,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,YAAY,EAAE,WAAW;QACzB,KAAK;QACL,aAAa,EAAE,MAAM;QACrB,qBAAqB,EAAE,MAAM;QAC7B,cAAc,EAAE,aAAa;KAC9B,CAAA;IAED,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IACjE,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;IACtE,MAAM,QAAQ,EAAE,CAAA;IAEhB,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAA;IACxD,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;IAEf,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IAEpD,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE;QAC1B,MAAM,kBAAkB,CAAA;KACzB;IAED,OAAO,EAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAC,CAAA;AAC1C,CAAC;AAED,KAAK,UAAU,mCAAmC,CAAC,IAAY;IAC7D,IAAI,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE;QAC/B,OAAM;KACP;IAED,IAAI,MAAM,kCAAkC,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE;QACpE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;KAC5B;SAAM;QACL,MAAM,IAAI,eAAe,EAAE,CAAA;KAC5B;AACH,CAAC","sourcesContent":["import {listenRedirect} from './redirect-listener.js'\nimport {clientId} from './identity.js'\nimport {generateRandomChallengePair, randomHex} from '../string.js'\nimport {open} from '../system.js'\nimport {Abort, CancelExecution} from '../error.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\nimport * as output from '../output.js'\nimport {keypress, terminateBlockingPortProcessPrompt} from '../ui.js'\nimport {checkPort as isPortAvailable} from 'get-port-please'\nimport {killPortProcess} from 'kill-port-process'\n\nexport const MismatchStateError = new Abort(\n \"The state received from the authentication doesn't match the one that initiated the authentication process.\",\n)\n\nexport interface CodeAuthResult {\n code: string\n codeVerifier: string\n}\n\nexport async function authorize(scopes: string[], state: string = randomHex(30)): Promise<CodeAuthResult> {\n const port = 3456\n const host = '127.0.0.1'\n const redirectUri = `http://${host}:${port}`\n const fqdn = await identityFqdn()\n const identityClientId = await clientId()\n\n await validateRedirectionPortAvailability(port)\n\n let url = `http://${fqdn}/oauth/authorize`\n\n const {codeVerifier, codeChallenge} = generateRandomChallengePair()\n\n const params = {\n client_id: identityClientId,\n scope: scopes.join(' '),\n redirect_uri: redirectUri,\n state,\n response_type: 'code',\n code_challenge_method: 'S256',\n code_challenge: codeChallenge,\n }\n\n output.info('\\nTo run this command, log in to Shopify Partners.')\n output.info('👉 Press any key to open the login page on your browser')\n await keypress()\n\n url = `${url}?${new URLSearchParams(params).toString()}`\n await open(url)\n\n const result = await listenRedirect(host, port, url)\n\n if (result.state !== state) {\n throw MismatchStateError\n }\n\n return {code: result.code, codeVerifier}\n}\n\nasync function validateRedirectionPortAvailability(port: number) {\n if (await isPortAvailable(port)) {\n return\n }\n\n if (await terminateBlockingPortProcessPrompt(port, 'Authentication')) {\n await killPortProcess(port)\n } else {\n throw new CancelExecution()\n }\n}\n"]}
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/session/authorize.ts"],"names":[],"mappings":"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","sourcesContent":["import {listenRedirect} from './redirect-listener.js'\nimport {clientId} from './identity.js'\nimport {base64URLEncode, randomBytes, randomHex, sha256} from '../public/node/crypto.js'\nimport {open} from '../system.js'\nimport {Abort, CancelExecution} from '../error.js'\nimport {identity as identityFqdn} from '../environment/fqdn.js'\nimport * as output from '../output.js'\nimport {keypress, terminateBlockingPortProcessPrompt} from '../ui.js'\nimport {checkPort as isPortAvailable} from 'get-port-please'\n\nexport const MismatchStateError = new Abort(\n \"The state received from the authentication doesn't match the one that initiated the authentication process.\",\n)\n\nexport interface CodeAuthResult {\n code: string\n codeVerifier: string\n}\n\nexport async function authorize(scopes: string[], state: string = randomHex(30)): Promise<CodeAuthResult> {\n const port = 3456\n const host = '127.0.0.1'\n const redirectUri = `http://${host}:${port}`\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n\n await validateRedirectionPortAvailability(port)\n\n let url = `http://${fqdn}/oauth/authorize`\n\n const {codeVerifier, codeChallenge} = generateRandomChallengePair()\n\n const params = {\n client_id: identityClientId,\n scope: scopes.join(' '),\n redirect_uri: redirectUri,\n state,\n response_type: 'code',\n code_challenge_method: 'S256',\n code_challenge: codeChallenge,\n }\n\n output.info('\\nTo run this command, log in to Shopify Partners.')\n output.info('👉 Press any key to open the login page on your browser')\n await keypress()\n\n url = `${url}?${new URLSearchParams(params).toString()}`\n await open(url)\n\n const result = await listenRedirect(host, port, url)\n\n if (result.state !== state) {\n throw MismatchStateError\n }\n\n return {code: result.code, codeVerifier}\n}\n\nexport function generateRandomChallengePair() {\n const codeVerifier = base64URLEncode(randomBytes(32))\n const codeChallenge = base64URLEncode(sha256(codeVerifier))\n return {codeVerifier, codeChallenge}\n}\n\nasync function validateRedirectionPortAvailability(port: number) {\n const {killPortProcess} = await import('kill-port-process')\n\n if (await isPortAvailable(port)) {\n return\n }\n\n if (await terminateBlockingPortProcessPrompt(port, 'Authentication')) {\n await killPortProcess(port)\n } else {\n throw new CancelExecution()\n }\n}\n"]}
@@ -38,4 +38,4 @@ async function getInstrospectionEndpoint() {
38
38
  const json = await response.json();
39
39
  return json.introspection_endpoint;
40
40
  }
41
- //# sourceMappingURL=identity.js.map
41
+ //# sourceMappingURL=identity-token-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-token-validation.js","sourceRoot":"","sources":["../../src/session/identity-token-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAA;AAClC,OAAO,EAAC,YAAY,EAAC,MAAM,YAAY,CAAA;AAEvC,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAa;IACvD,IAAI;QACF,MAAM,iBAAiB,GAAG,MAAM,yBAAyB,EAAE,CAAA;QAC3D,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAC,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAC;YAC/E,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAC,KAAK,EAAC,CAAC;SAC9B,CAAA;QACD,KAAK,CAAC,kDAAkD,iBAAiB,EAAE,CAAC,CAAA;QAE5E,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;QAE/D,IAAI,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE;YACzE,8DAA8D;YAC9D,MAAM,IAAI,GAAQ,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YACvC,KAAK,CAAC,gCAAgC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;YACnD,OAAO,IAAI,CAAC,KAAK,CAAA;SAClB;aAAM;YACL,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YAClC,KAAK,CAAC;aACC,QAAQ,CAAC,MAAM;8BACE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;WAC3E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC5B,OAAO,KAAK,CAAA;SACb;QACD,qDAAqD;KACtD;IAAC,OAAO,KAAK,EAAE;QACd,KAAK,CAAC,kCAAkC,KAAK,EAAE,CAAC,CAAA;QAChD,OAAO,KAAK,CAAA;KACb;AACH,CAAC;AAED,KAAK,UAAU,yBAAyB;IACtC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,MAAM,QAAQ,EAAE,wCAAwC,CAAC,CAAA;IACxG,8DAA8D;IAC9D,MAAM,IAAI,GAAQ,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACvC,OAAO,IAAI,CAAC,sBAAsB,CAAA;AACpC,CAAC","sourcesContent":["import {identity} from '../environment/fqdn.js'\nimport {debug} from '../output.js'\nimport {shopifyFetch} from '../http.js'\n\nexport async function validateIdentityToken(token: string) {\n try {\n const instrospectionURL = await getInstrospectionEndpoint()\n const options = {\n method: 'POST',\n headers: {Authorization: `Bearer ${token}`, 'Content-Type': 'application/json'},\n body: JSON.stringify({token}),\n }\n debug(`Sending Identity Introspection request to URL: ${instrospectionURL}`)\n\n const response = await shopifyFetch(instrospectionURL, options)\n\n if (response.ok && response.headers.get('content-type')?.includes('json')) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const json: any = await response.json()\n debug(`The identity token is valid: ${json.valid}`)\n return json.valid\n } else {\n const text = await response.text()\n debug(`The Introspection request failed with:\n - status: ${response.status}\n - www-authenticate header: ${JSON.stringify(response.headers.get('www-authenticate'))}\n - body: ${JSON.stringify(text)}`)\n return false\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n debug(`The identity token is invalid: ${error}`)\n return false\n }\n}\n\nasync function getInstrospectionEndpoint(): Promise<string> {\n const response = await shopifyFetch(`https://${await identity()}/.well-known/openid-configuration.json`)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const json: any = await response.json()\n return json.introspection_endpoint\n}\n"]}
@@ -24,18 +24,21 @@ export class RedirectListener {
24
24
  const requestUrl = request.url;
25
25
  if (requestUrl?.includes('favicon')) {
26
26
  const faviconFile = await getFavicon();
27
- response.setHeader('Content-Type', 'image/svg+xml').write(faviconFile);
27
+ response.setHeader('Content-Type', 'image/svg+xml');
28
+ response.write(faviconFile);
28
29
  response.end();
29
30
  return {};
30
31
  }
31
32
  else if (requestUrl === '/style.css') {
32
33
  const stylesheetFile = await getStylesheet();
33
- response.setHeader('Content-Type', 'text/css').write(stylesheetFile);
34
+ response.setHeader('Content-Type', 'text/css');
35
+ response.write(stylesheetFile);
34
36
  response.end();
35
37
  return {};
36
38
  }
37
39
  const respond = async (contents, error, state, code) => {
38
- response.setHeader('Content-Type', 'text/html').write(contents);
40
+ response.setHeader('Content-Type', 'text/html');
41
+ response.write(contents);
39
42
  response.end();
40
43
  callback(error, state, code);
41
44
  return {};
@@ -1 +1 @@
1
- {"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../src/session/redirect-listener.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getFavicon,\n getStylesheet,\n getEmptyUrlHTML,\n getAuthErrorHTML,\n getMissingCodeHTML,\n getMissingStateHTML,\n getSuccessHTML,\n EmptyUrlString,\n MissingCodeString,\n MissingStateString,\n} from './post-auth.js'\nimport {Abort, Bug} from '../error.js'\nimport {content, info, token} from '../output.js'\nimport {createApp, IncomingMessage, ServerResponse} from 'h3'\nimport url from 'url'\nimport {createServer, Server} from 'http'\n\nconst ResponseTimeoutSeconds = 10\nconst ServerStopDelaySeconds = 0.5\n\n/**\n * It represents the result of a redirect.\n */\ntype RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void\n\n/**\n * Defines the interface of the options that\n * are used to instantiate a redirect listener.\n */\ninterface RedirectListenerOptions {\n host: string\n port: number\n callback: RedirectCallback\n}\n/**\n * When the authentication completes, Identity redirects\n * the user to a URL. In the case of the CLI, the redirect\n * is to localhost passing some parameters that are necessary\n * to continue the authentication. Because of that, we need\n * an HTTP server that runs and listens to the request.\n */\nexport class RedirectListener {\n private static createServer(callback: RedirectCallback): Server {\n const app = createApp().use('*', async (request: IncomingMessage, response: ServerResponse) => {\n const requestUrl = request.url\n if (requestUrl?.includes('favicon')) {\n const faviconFile = await getFavicon()\n response.setHeader('Content-Type', 'image/svg+xml').write(faviconFile)\n response.end()\n return {}\n } else if (requestUrl === '/style.css') {\n const stylesheetFile = await getStylesheet()\n response.setHeader('Content-Type', 'text/css').write(stylesheetFile)\n response.end()\n return {}\n }\n\n const respond = async (contents: string, error?: Error, state?: string, code?: string) => {\n response.setHeader('Content-Type', 'text/html').write(contents)\n response.end()\n callback(error, state, code)\n return {}\n }\n\n // If there was an empty/malformed URL sent back.\n if (!requestUrl) {\n const file = await getEmptyUrlHTML()\n const err = new Bug(EmptyUrlString)\n return respond(file, err, undefined, undefined)\n }\n\n // If an error was returned by the Identity server.\n const queryObject = url.parse(requestUrl, true).query\n if (queryObject.error && queryObject.error_description) {\n const file = await getAuthErrorHTML()\n const err = new Abort(`${queryObject.error_description}`)\n return respond(file, err, undefined, undefined)\n }\n\n // If the code isn't present in the URL.\n if (!queryObject.code) {\n const file = await getMissingCodeHTML()\n const err = new Bug(MissingCodeString)\n return respond(file, err, undefined, undefined)\n }\n\n // If the state isn't present in the URL.\n if (!queryObject.state) {\n const file = await getMissingStateHTML()\n const err = new Bug(MissingStateString)\n return respond(file, err, undefined, undefined)\n }\n\n const file = await getSuccessHTML()\n return respond(file, undefined, `${queryObject.code}`, `${queryObject.state}`)\n })\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return createServer(app)\n }\n\n port: number\n host: string\n server: ReturnType<typeof RedirectListener.createServer>\n\n constructor(options: RedirectListenerOptions) {\n this.port = options.port\n this.host = options.host\n this.server = RedirectListener.createServer(options.callback)\n }\n\n start(): void {\n this.server.listen({port: this.port, host: this.host}, () => {})\n }\n\n async stop(): Promise<void> {\n await this.server.close()\n }\n}\n\nexport async function listenRedirect(host: string, port: number, url: string): Promise<{code: string; state: string}> {\n const result = await new Promise<{code: string; state: string}>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const message = '\\nAuto-open timed out. Open the login page: '\n info(content`${message}${token.link('Log in to Shopify Partners', url)}\\n`)\n }, ResponseTimeoutSeconds * 1000)\n\n const callback: RedirectCallback = (error, code, state) => {\n clearTimeout(timeout)\n setTimeout(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n redirectListener.stop()\n if (error) reject(error)\n else resolve({code: code as string, state: state as string})\n }, ServerStopDelaySeconds * 1000)\n }\n\n const redirectListener = new RedirectListener({host, port, callback})\n redirectListener.start()\n })\n return result\n}\n"]}
1
+ {"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../src/session/redirect-listener.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getFavicon,\n getStylesheet,\n getEmptyUrlHTML,\n getAuthErrorHTML,\n getMissingCodeHTML,\n getMissingStateHTML,\n getSuccessHTML,\n EmptyUrlString,\n MissingCodeString,\n MissingStateString,\n} from './post-auth.js'\nimport {Abort, Bug} from '../error.js'\nimport {content, info, token} from '../output.js'\nimport {createApp, IncomingMessage, ServerResponse} from 'h3'\nimport url from 'url'\nimport {createServer, Server} from 'http'\n\nconst ResponseTimeoutSeconds = 10\nconst ServerStopDelaySeconds = 0.5\n\n/**\n * It represents the result of a redirect.\n */\ntype RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void\n\n/**\n * Defines the interface of the options that\n * are used to instantiate a redirect listener.\n */\ninterface RedirectListenerOptions {\n host: string\n port: number\n callback: RedirectCallback\n}\n/**\n * When the authentication completes, Identity redirects\n * the user to a URL. In the case of the CLI, the redirect\n * is to localhost passing some parameters that are necessary\n * to continue the authentication. Because of that, we need\n * an HTTP server that runs and listens to the request.\n */\nexport class RedirectListener {\n private static createServer(callback: RedirectCallback): Server {\n const app = createApp().use('*', async (request: IncomingMessage, response: ServerResponse) => {\n const requestUrl = request.url\n if (requestUrl?.includes('favicon')) {\n const faviconFile = await getFavicon()\n response.setHeader('Content-Type', 'image/svg+xml')\n response.write(faviconFile)\n response.end()\n return {}\n } else if (requestUrl === '/style.css') {\n const stylesheetFile = await getStylesheet()\n response.setHeader('Content-Type', 'text/css')\n response.write(stylesheetFile)\n response.end()\n return {}\n }\n\n const respond = async (contents: string, error?: Error, state?: string, code?: string) => {\n response.setHeader('Content-Type', 'text/html')\n response.write(contents)\n response.end()\n callback(error, state, code)\n return {}\n }\n\n // If there was an empty/malformed URL sent back.\n if (!requestUrl) {\n const file = await getEmptyUrlHTML()\n const err = new Bug(EmptyUrlString)\n return respond(file, err, undefined, undefined)\n }\n\n // If an error was returned by the Identity server.\n const queryObject = url.parse(requestUrl, true).query\n if (queryObject.error && queryObject.error_description) {\n const file = await getAuthErrorHTML()\n const err = new Abort(`${queryObject.error_description}`)\n return respond(file, err, undefined, undefined)\n }\n\n // If the code isn't present in the URL.\n if (!queryObject.code) {\n const file = await getMissingCodeHTML()\n const err = new Bug(MissingCodeString)\n return respond(file, err, undefined, undefined)\n }\n\n // If the state isn't present in the URL.\n if (!queryObject.state) {\n const file = await getMissingStateHTML()\n const err = new Bug(MissingStateString)\n return respond(file, err, undefined, undefined)\n }\n\n const file = await getSuccessHTML()\n return respond(file, undefined, `${queryObject.code}`, `${queryObject.state}`)\n })\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return createServer(app)\n }\n\n port: number\n host: string\n server: ReturnType<typeof RedirectListener.createServer>\n\n constructor(options: RedirectListenerOptions) {\n this.port = options.port\n this.host = options.host\n this.server = RedirectListener.createServer(options.callback)\n }\n\n start(): void {\n this.server.listen({port: this.port, host: this.host}, () => {})\n }\n\n async stop(): Promise<void> {\n await this.server.close()\n }\n}\n\nexport async function listenRedirect(host: string, port: number, url: string): Promise<{code: string; state: string}> {\n const result = await new Promise<{code: string; state: string}>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const message = '\\nAuto-open timed out. Open the login page: '\n info(content`${message}${token.link('Log in to Shopify Partners', url)}\\n`)\n }, ResponseTimeoutSeconds * 1000)\n\n const callback: RedirectCallback = (error, code, state) => {\n clearTimeout(timeout)\n setTimeout(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n redirectListener.stop()\n if (error) reject(error)\n else resolve({code: code as string, state: state as string})\n }, ServerStopDelaySeconds * 1000)\n }\n\n const redirectListener = new RedirectListener({host, port, callback})\n redirectListener.start()\n })\n return result\n}\n"]}
@@ -8,15 +8,15 @@ declare const IdentityTokenSchema: define.ZodObject<{
8
8
  expiresAt: define.ZodEffects<define.ZodDate, Date, Date>;
9
9
  scopes: define.ZodArray<define.ZodString, "many">;
10
10
  }, "strip", define.ZodTypeAny, {
11
+ scopes: string[];
11
12
  accessToken: string;
12
13
  refreshToken: string;
13
14
  expiresAt: Date;
14
- scopes: string[];
15
15
  }, {
16
+ scopes: string[];
16
17
  accessToken: string;
17
18
  refreshToken: string;
18
19
  expiresAt: Date;
19
- scopes: string[];
20
20
  }>;
21
21
  /**
22
22
  * The schema represents an application token.
@@ -26,13 +26,13 @@ declare const ApplicationTokenSchema: define.ZodObject<{
26
26
  expiresAt: define.ZodEffects<define.ZodDate, Date, Date>;
27
27
  scopes: define.ZodArray<define.ZodString, "many">;
28
28
  }, "strip", define.ZodTypeAny, {
29
+ scopes: string[];
29
30
  accessToken: string;
30
31
  expiresAt: Date;
31
- scopes: string[];
32
32
  }, {
33
+ scopes: string[];
33
34
  accessToken: string;
34
35
  expiresAt: Date;
35
- scopes: string[];
36
36
  }>;
37
37
  /**
38
38
  * This schema represents the format of the session
@@ -69,15 +69,15 @@ export declare const SessionSchema: define.ZodObject<{}, "strip", define.ZodObje
69
69
  expiresAt: define.ZodEffects<define.ZodDate, Date, Date>;
70
70
  scopes: define.ZodArray<define.ZodString, "many">;
71
71
  }, "strip", define.ZodTypeAny, {
72
+ scopes: string[];
72
73
  accessToken: string;
73
74
  refreshToken: string;
74
75
  expiresAt: Date;
75
- scopes: string[];
76
76
  }, {
77
+ scopes: string[];
77
78
  accessToken: string;
78
79
  refreshToken: string;
79
80
  expiresAt: Date;
80
- scopes: string[];
81
81
  }>;
82
82
  /**
83
83
  * It contains exchanged tokens for the applications the CLI
@@ -88,83 +88,83 @@ export declare const SessionSchema: define.ZodObject<{}, "strip", define.ZodObje
88
88
  expiresAt: define.ZodEffects<define.ZodDate, Date, Date>;
89
89
  scopes: define.ZodArray<define.ZodString, "many">;
90
90
  }, "strip", define.ZodTypeAny, {
91
+ scopes: string[];
91
92
  accessToken: string;
92
93
  expiresAt: Date;
93
- scopes: string[];
94
94
  }, {
95
+ scopes: string[];
95
96
  accessToken: string;
96
97
  expiresAt: Date;
97
- scopes: string[];
98
98
  }>, {
99
99
  [x: string]: {
100
+ scopes: string[];
100
101
  accessToken: string;
101
102
  expiresAt: Date;
102
- scopes: string[];
103
103
  };
104
104
  }, {
105
105
  [x: string]: {
106
+ scopes: string[];
106
107
  accessToken: string;
107
108
  expiresAt: Date;
108
- scopes: string[];
109
109
  };
110
110
  }>;
111
111
  }, "strip", define.ZodTypeAny, {
112
112
  identity: {
113
+ scopes: string[];
113
114
  accessToken: string;
114
115
  refreshToken: string;
115
116
  expiresAt: Date;
116
- scopes: string[];
117
117
  };
118
118
  applications: {
119
119
  [x: string]: {
120
+ scopes: string[];
120
121
  accessToken: string;
121
122
  expiresAt: Date;
122
- scopes: string[];
123
123
  };
124
124
  };
125
125
  }, {
126
126
  identity: {
127
+ scopes: string[];
127
128
  accessToken: string;
128
129
  refreshToken: string;
129
130
  expiresAt: Date;
130
- scopes: string[];
131
131
  };
132
132
  applications: {
133
133
  [x: string]: {
134
+ scopes: string[];
134
135
  accessToken: string;
135
136
  expiresAt: Date;
136
- scopes: string[];
137
137
  };
138
138
  };
139
139
  }>, {
140
140
  [x: string]: {
141
141
  identity: {
142
+ scopes: string[];
142
143
  accessToken: string;
143
144
  refreshToken: string;
144
145
  expiresAt: Date;
145
- scopes: string[];
146
146
  };
147
147
  applications: {
148
148
  [x: string]: {
149
+ scopes: string[];
149
150
  accessToken: string;
150
151
  expiresAt: Date;
151
- scopes: string[];
152
152
  };
153
153
  };
154
154
  };
155
155
  }, {
156
156
  [x: string]: {
157
157
  identity: {
158
+ scopes: string[];
158
159
  accessToken: string;
159
160
  refreshToken: string;
160
161
  expiresAt: Date;
161
- scopes: string[];
162
162
  };
163
163
  applications: {
164
164
  [x: string]: {
165
+ scopes: string[];
165
166
  accessToken: string;
166
167
  expiresAt: Date;
167
- scopes: string[];
168
168
  };
169
169
  };
170
170
  };
@@ -1,6 +1,6 @@
1
1
  import { SessionSchema } from './schema.js';
2
2
  import constants from '../constants.js';
3
- import { platformAndArch } from '../os.js';
3
+ import { platformAndArch } from '../public/node/os.js';
4
4
  import { store as secureStore, fetch as secureFetch, remove as secureRemove } from '../secure-store.js';
5
5
  import { content, debug } from '../output.js';
6
6
  import { getSession, removeSession, setSession, clearAllAppInfo } from '../store.js';
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,UAAU,CAAA;AACxC,OAAO,EAAC,KAAK,IAAI,WAAW,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,IAAI,YAAY,EAAC,MAAM,oBAAoB,CAAA;AACrG,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,aAAa,CAAA;AAGlF;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAgB;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,UAAU,CAAC,WAAW,CAAC,CAAA;KAC9B;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,OAAO,CAAA;IACX,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAA;KACxC;SAAM;QACL,OAAO,GAAG,MAAM,UAAU,EAAE,CAAA;KAC7B;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,SAAS,CAAA;KACjB;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IACrE,IAAI,aAAa,CAAC,OAAO,EAAE;QACzB,OAAO,aAAa,CAAC,IAAI,CAAA;KAC1B;SAAM;QACL,MAAM,MAAM,EAAE,CAAA;QACd,OAAO,SAAS,CAAA;KACjB;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;KAC/B;SAAM;QACL,MAAM,aAAa,EAAE,CAAA;KACtB;IAED,MAAM,eAAe,EAAE,CAAA;AACzB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB;IACjC,IAAI;QACF,IAAI,eAAe,EAAE,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC5C,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;YACrD,OAAO,KAAK,CAAA;SACb;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChE,KAAK,CAAC,OAAO,CAAA,2BAA2B,CAAC,CAAA;QACzC,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,MAAM,EAAE;QACf,KAAK,CAAC,OAAO,CAAA,6BAA6B,CAAC,CAAA;QAC3C,OAAO,KAAK,CAAA;KACb;AACH,CAAC","sourcesContent":["import {SessionSchema} from './schema.js'\nimport constants from '../constants.js'\nimport {platformAndArch} from '../os.js'\nimport {store as secureStore, fetch as secureFetch, remove as secureRemove} from '../secure-store.js'\nimport {content, debug} from '../output.js'\nimport {getSession, removeSession, setSession, clearAllAppInfo} from '../store.js'\nimport type {Session} from './schema.js'\n\n/**\n * The identifier of the session in the secure store.\n */\nexport const identifier = 'session'\n\n/**\n * Serializes the session as a JSON and stores it securely in the system.\n * If the secure store is not available, the session is stored in the local config.\n * @param session - the session to store.\n */\nexport async function store(session: Session) {\n const jsonSession = JSON.stringify(session)\n if (await secureStoreAvailable()) {\n await secureStore(identifier, jsonSession)\n } else {\n await setSession(jsonSession)\n }\n}\n\n/**\n * Fetches the session from the secure store and returns it.\n * If the secure store is not available, the session is fetched from the local config.\n * If the format of the session is invalid, the method will discard it.\n * In the future might add some logic for supporting migrating the schema\n * of already-persisted sessions.\n * @returns Returns a promise that resolves with the session if it exists and is valid.\n */\nexport async function fetch(): Promise<Session | undefined> {\n let content\n if (await secureStoreAvailable()) {\n content = await secureFetch(identifier)\n } else {\n content = await getSession()\n }\n\n if (!content) {\n return undefined\n }\n const contentJson = JSON.parse(content)\n const parsedSession = await SessionSchema.safeParseAsync(contentJson)\n if (parsedSession.success) {\n return parsedSession.data\n } else {\n await remove()\n return undefined\n }\n}\n\n/**\n * Removes a session from the system.\n */\nexport async function remove() {\n if (await secureStoreAvailable()) {\n await secureRemove(identifier)\n } else {\n await removeSession()\n }\n\n await clearAllAppInfo()\n}\n\n/**\n * Returns true if the secure store is available on the system.\n * Keytar it's not supported on some Linux environments or Windows.\n * More details: https://github.com/Shopify/shopify-cli-planning/issues/261\n * @returns a boolean indicating if the secure store is available.\n */\nasync function secureStoreAvailable(): Promise<boolean> {\n try {\n if (platformAndArch().platform === 'windows') {\n debug(content`Secure store not supported on Windows`)\n return false\n }\n const keytar = await import('keytar')\n await keytar.default.findCredentials(constants.keychain.service)\n debug(content`Secure store is available`)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (_error) {\n debug(content`Failed to load secure store`)\n return false\n }\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/session/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAC,KAAK,IAAI,WAAW,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,IAAI,YAAY,EAAC,MAAM,oBAAoB,CAAA;AACrG,OAAO,EAAC,OAAO,EAAE,KAAK,EAAC,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAC,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,aAAa,CAAA;AAGlF;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAgB;IAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;KAC3C;SAAM;QACL,MAAM,UAAU,CAAC,WAAW,CAAC,CAAA;KAC9B;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,OAAO,CAAA;IACX,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAA;KACxC;SAAM;QACL,OAAO,GAAG,MAAM,UAAU,EAAE,CAAA;KAC7B;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,SAAS,CAAA;KACjB;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,aAAa,GAAG,MAAM,aAAa,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IACrE,IAAI,aAAa,CAAC,OAAO,EAAE;QACzB,OAAO,aAAa,CAAC,IAAI,CAAA;KAC1B;SAAM;QACL,MAAM,MAAM,EAAE,CAAA;QACd,OAAO,SAAS,CAAA;KACjB;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,IAAI,MAAM,oBAAoB,EAAE,EAAE;QAChC,MAAM,YAAY,CAAC,UAAU,CAAC,CAAA;KAC/B;SAAM;QACL,MAAM,aAAa,EAAE,CAAA;KACtB;IAED,MAAM,eAAe,EAAE,CAAA;AACzB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB;IACjC,IAAI;QACF,IAAI,eAAe,EAAE,CAAC,QAAQ,KAAK,SAAS,EAAE;YAC5C,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;YACrD,OAAO,KAAK,CAAA;SACb;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAChE,KAAK,CAAC,OAAO,CAAA,2BAA2B,CAAC,CAAA;QACzC,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,MAAM,EAAE;QACf,KAAK,CAAC,OAAO,CAAA,6BAA6B,CAAC,CAAA;QAC3C,OAAO,KAAK,CAAA;KACb;AACH,CAAC","sourcesContent":["import {SessionSchema} from './schema.js'\nimport constants from '../constants.js'\nimport {platformAndArch} from '../public/node/os.js'\nimport {store as secureStore, fetch as secureFetch, remove as secureRemove} from '../secure-store.js'\nimport {content, debug} from '../output.js'\nimport {getSession, removeSession, setSession, clearAllAppInfo} from '../store.js'\nimport type {Session} from './schema.js'\n\n/**\n * The identifier of the session in the secure store.\n */\nexport const identifier = 'session'\n\n/**\n * Serializes the session as a JSON and stores it securely in the system.\n * If the secure store is not available, the session is stored in the local config.\n * @param session - the session to store.\n */\nexport async function store(session: Session) {\n const jsonSession = JSON.stringify(session)\n if (await secureStoreAvailable()) {\n await secureStore(identifier, jsonSession)\n } else {\n await setSession(jsonSession)\n }\n}\n\n/**\n * Fetches the session from the secure store and returns it.\n * If the secure store is not available, the session is fetched from the local config.\n * If the format of the session is invalid, the method will discard it.\n * In the future might add some logic for supporting migrating the schema\n * of already-persisted sessions.\n * @returns Returns a promise that resolves with the session if it exists and is valid.\n */\nexport async function fetch(): Promise<Session | undefined> {\n let content\n if (await secureStoreAvailable()) {\n content = await secureFetch(identifier)\n } else {\n content = await getSession()\n }\n\n if (!content) {\n return undefined\n }\n const contentJson = JSON.parse(content)\n const parsedSession = await SessionSchema.safeParseAsync(contentJson)\n if (parsedSession.success) {\n return parsedSession.data\n } else {\n await remove()\n return undefined\n }\n}\n\n/**\n * Removes a session from the system.\n */\nexport async function remove() {\n if (await secureStoreAvailable()) {\n await secureRemove(identifier)\n } else {\n await removeSession()\n }\n\n await clearAllAppInfo()\n}\n\n/**\n * Returns true if the secure store is available on the system.\n * Keytar it's not supported on some Linux environments or Windows.\n * More details: https://github.com/Shopify/shopify-cli-planning/issues/261\n * @returns a boolean indicating if the secure store is available.\n */\nasync function secureStoreAvailable(): Promise<boolean> {\n try {\n if (platformAndArch().platform === 'windows') {\n debug(content`Secure store not supported on Windows`)\n return false\n }\n const keytar = await import('keytar')\n await keytar.default.findCredentials(constants.keychain.service)\n debug(content`Secure store is available`)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (_error) {\n debug(content`Failed to load secure store`)\n return false\n }\n}\n"]}
package/dist/session.js CHANGED
@@ -11,11 +11,11 @@ import { authorize } from './session/authorize.js';
11
11
  import * as secureStore from './session/store.js';
12
12
  import constants from './constants.js';
13
13
  import * as output from './output.js';
14
- import { partners } from './api.js';
15
- import { RequestClientError } from './api/common.js';
16
14
  import { firstPartyDev, useDeviceAuth } from './environment/local.js';
17
15
  import { pollForDeviceAuthorization, requestDeviceAuthorization } from './session/device-authorization.js';
18
16
  import { AbortError } from './public/node/error.js';
17
+ import { partnersRequest } from './public/node/api/partners.js';
18
+ import { RequestClientError } from './private/node/api/headers.js';
19
19
  import { gql } from 'graphql-request';
20
20
  const NoSessionError = new Bug('No session found after ensuring authenticated');
21
21
  const MissingPartnerTokenError = new Bug('No partners token found after ensuring authenticated');
@@ -153,7 +153,7 @@ ${token.json(applications)}
153
153
  }
154
154
  export async function hasPartnerAccount(partnersToken) {
155
155
  try {
156
- await partners.request(gql `
156
+ await partnersRequest(gql `
157
157
  {
158
158
  organizations(first: 1) {
159
159
  nodes {