@shopify/cli-kit 4.6.1 → 4.7.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 (164) hide show
  1. package/dist/private/node/analytics/bounded-collections.js +1 -4
  2. package/dist/private/node/analytics/bounded-collections.js.map +1 -1
  3. package/dist/private/node/analytics/graphql-error-codes.d.ts +2 -2
  4. package/dist/private/node/analytics/graphql-error-codes.js +2 -2
  5. package/dist/private/node/analytics/graphql-error-codes.js.map +1 -1
  6. package/dist/private/node/analytics.js +12 -7
  7. package/dist/private/node/analytics.js.map +1 -1
  8. package/dist/private/node/api/headers.js +3 -0
  9. package/dist/private/node/api/headers.js.map +1 -1
  10. package/dist/private/node/api.js +8 -8
  11. package/dist/private/node/api.js.map +1 -1
  12. package/dist/private/node/conf-store.js +1 -1
  13. package/dist/private/node/conf-store.js.map +1 -1
  14. package/dist/private/node/content-tokens.js +27 -2
  15. package/dist/private/node/content-tokens.js.map +1 -1
  16. package/dist/private/node/otel-metrics.d.ts +1 -1
  17. package/dist/private/node/otel-metrics.js +5 -2
  18. package/dist/private/node/otel-metrics.js.map +1 -1
  19. package/dist/private/node/plugin-hints.d.ts +16 -0
  20. package/dist/private/node/plugin-hints.js +29 -0
  21. package/dist/private/node/plugin-hints.js.map +1 -0
  22. package/dist/private/node/request-ids.js +2 -3
  23. package/dist/private/node/request-ids.js.map +1 -1
  24. package/dist/private/node/session/device-authorization.js +4 -7
  25. package/dist/private/node/session/device-authorization.js.map +1 -1
  26. package/dist/private/node/session/exchange.d.ts +4 -4
  27. package/dist/private/node/session/exchange.js +21 -5
  28. package/dist/private/node/session/exchange.js.map +1 -1
  29. package/dist/private/node/testing/ui.js +18 -19
  30. package/dist/private/node/testing/ui.js.map +1 -1
  31. package/dist/private/node/ui/components/Alert.d.ts +1 -1
  32. package/dist/private/node/ui/components/Alert.js.map +1 -1
  33. package/dist/private/node/ui/components/ConcurrentOutput.test.js +2 -0
  34. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
  35. package/dist/private/node/ui/components/DangerousConfirmationPrompt.d.ts +1 -1
  36. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
  37. package/dist/private/node/ui/components/List.d.ts +1 -1
  38. package/dist/private/node/ui/components/List.js.map +1 -1
  39. package/dist/private/node/ui/components/Prompts/InfoMessage.d.ts +1 -1
  40. package/dist/private/node/ui/components/Prompts/InfoMessage.js.map +1 -1
  41. package/dist/private/node/ui/components/Prompts/InfoTable.d.ts +1 -1
  42. package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
  43. package/dist/private/node/ui/components/Prompts/PromptLayout.d.ts +1 -1
  44. package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
  45. package/dist/private/node/ui/components/SingleTask.test.js +1 -0
  46. package/dist/private/node/ui/components/SingleTask.test.js.map +1 -1
  47. package/dist/private/node/ui/components/TabularData.d.ts +1 -1
  48. package/dist/private/node/ui/components/TabularData.js +2 -1
  49. package/dist/private/node/ui/components/TabularData.js.map +1 -1
  50. package/dist/private/node/ui/components/TextPrompt.d.ts +1 -1
  51. package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
  52. package/dist/private/node/ui/components/TokenizedText.d.ts +1 -38
  53. package/dist/private/node/ui/components/TokenizedText.js +0 -54
  54. package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
  55. package/dist/private/node/ui/components/TokenizedText.test.js +2 -1
  56. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
  57. package/dist/private/node/ui/components/token-item.d.ts +38 -0
  58. package/dist/private/node/ui/components/token-item.js +63 -0
  59. package/dist/private/node/ui/components/token-item.js.map +1 -0
  60. package/dist/private/node/ui/hooks/use-abort-signal.js +5 -4
  61. package/dist/private/node/ui/hooks/use-abort-signal.js.map +1 -1
  62. package/dist/private/node/ui/hooks/use-select-state.js +2 -1
  63. package/dist/private/node/ui/hooks/use-select-state.js.map +1 -1
  64. package/dist/private/node/ui/utilities.d.ts +6 -6
  65. package/dist/private/node/ui/utilities.js +1 -1
  66. package/dist/private/node/ui/utilities.js.map +1 -1
  67. package/dist/private/node/ui.js +18 -15
  68. package/dist/private/node/ui.js.map +1 -1
  69. package/dist/public/common/string.d.ts +1 -1
  70. package/dist/public/common/string.js.map +1 -1
  71. package/dist/public/common/version.d.ts +1 -1
  72. package/dist/public/common/version.js +1 -1
  73. package/dist/public/common/version.js.map +1 -1
  74. package/dist/public/node/abort.d.ts +14 -6
  75. package/dist/public/node/abort.js +7 -6
  76. package/dist/public/node/abort.js.map +1 -1
  77. package/dist/public/node/analytics.d.ts +1 -0
  78. package/dist/public/node/analytics.js +79 -32
  79. package/dist/public/node/analytics.js.map +1 -1
  80. package/dist/public/node/api/admin.js +1 -1
  81. package/dist/public/node/api/admin.js.map +1 -1
  82. package/dist/public/node/base-command.d.ts +10 -0
  83. package/dist/public/node/base-command.js +31 -8
  84. package/dist/public/node/base-command.js.map +1 -1
  85. package/dist/public/node/cli.d.ts +13 -0
  86. package/dist/public/node/cli.js +18 -2
  87. package/dist/public/node/cli.js.map +1 -1
  88. package/dist/public/node/context/local.d.ts +3 -1
  89. package/dist/public/node/context/local.js +14 -7
  90. package/dist/public/node/context/local.js.map +1 -1
  91. package/dist/public/node/custom-oclif-loader.js +19 -16
  92. package/dist/public/node/custom-oclif-loader.js.map +1 -1
  93. package/dist/public/node/doctor/framework.js +4 -5
  94. package/dist/public/node/doctor/framework.js.map +1 -1
  95. package/dist/public/node/environment.js +8 -11
  96. package/dist/public/node/environment.js.map +1 -1
  97. package/dist/public/node/error.d.ts +1 -4
  98. package/dist/public/node/error.js +20 -7
  99. package/dist/public/node/error.js.map +1 -1
  100. package/dist/public/node/git.js +7 -5
  101. package/dist/public/node/git.js.map +1 -1
  102. package/dist/public/node/global-context.js +1 -1
  103. package/dist/public/node/global-context.js.map +1 -1
  104. package/dist/public/node/hidden-folder.js +2 -4
  105. package/dist/public/node/hidden-folder.js.map +1 -1
  106. package/dist/public/node/hooks/postrun.js +1 -1
  107. package/dist/public/node/hooks/postrun.js.map +1 -1
  108. package/dist/public/node/hooks/prerun.js +5 -1
  109. package/dist/public/node/hooks/prerun.js.map +1 -1
  110. package/dist/public/node/local-storage.js +1 -0
  111. package/dist/public/node/local-storage.js.map +1 -1
  112. package/dist/public/node/metadata.d.ts +3 -0
  113. package/dist/public/node/metadata.js.map +1 -1
  114. package/dist/public/node/mimes.js +1 -3
  115. package/dist/public/node/mimes.js.map +1 -1
  116. package/dist/public/node/node-package-manager.js +31 -73
  117. package/dist/public/node/node-package-manager.js.map +1 -1
  118. package/dist/public/node/notifications-system.js +19 -3
  119. package/dist/public/node/notifications-system.js.map +1 -1
  120. package/dist/public/node/os.js +5 -10
  121. package/dist/public/node/os.js.map +1 -1
  122. package/dist/public/node/output.js +11 -20
  123. package/dist/public/node/output.js.map +1 -1
  124. package/dist/public/node/plugins/tunnel.d.ts +1 -2
  125. package/dist/public/node/plugins/tunnel.js +2 -2
  126. package/dist/public/node/plugins/tunnel.js.map +1 -1
  127. package/dist/public/node/result.js +4 -2
  128. package/dist/public/node/result.js.map +1 -1
  129. package/dist/public/node/serial-batch-processor.js +4 -3
  130. package/dist/public/node/serial-batch-processor.js.map +1 -1
  131. package/dist/public/node/store-auth-session.js +1 -1
  132. package/dist/public/node/store-auth-session.js.map +1 -1
  133. package/dist/public/node/system.d.ts +15 -1
  134. package/dist/public/node/system.js +42 -6
  135. package/dist/public/node/system.js.map +1 -1
  136. package/dist/public/node/themes/conf.js +2 -2
  137. package/dist/public/node/themes/conf.js.map +1 -1
  138. package/dist/public/node/themes/factories.js +2 -2
  139. package/dist/public/node/themes/factories.js.map +1 -1
  140. package/dist/public/node/themes/theme-manager.js +2 -0
  141. package/dist/public/node/themes/theme-manager.js.map +1 -1
  142. package/dist/public/node/themes/urls.js +7 -7
  143. package/dist/public/node/themes/urls.js.map +1 -1
  144. package/dist/public/node/toml/toml-file.js +12 -13
  145. package/dist/public/node/toml/toml-file.js.map +1 -1
  146. package/dist/public/node/ui.d.ts +1 -1
  147. package/dist/public/node/ui.js +1 -1
  148. package/dist/public/node/ui.js.map +1 -1
  149. package/dist/public/node/vendor/dev_server/dev-server-2024.js +14 -2
  150. package/dist/public/node/vendor/dev_server/dev-server-2024.js.map +1 -1
  151. package/dist/public/node/vendor/dev_server/dev-server.js +3 -0
  152. package/dist/public/node/vendor/dev_server/dev-server.js.map +1 -1
  153. package/dist/public/node/vendor/dev_server/network/index.js +1 -1
  154. package/dist/public/node/vendor/dev_server/network/index.js.map +1 -1
  155. package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.js +1 -0
  156. package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.js.map +1 -1
  157. package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.js +5 -2
  158. package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.js.map +1 -1
  159. package/dist/public/node/vendor/otel-js/service/types.d.ts +2 -2
  160. package/dist/public/node/vendor/otel-js/service/types.js.map +1 -1
  161. package/dist/public/node/vscode.js +12 -11
  162. package/dist/public/node/vscode.js.map +1 -1
  163. package/dist/tsconfig.tsbuildinfo +1 -1
  164. package/package.json +3 -9
@@ -1,6 +1,6 @@
1
- import { ExtendableError } from '../error.js';
2
1
  import { err } from '../result.js';
3
- export class TunnelError extends ExtendableError {
2
+ export class TunnelError extends Error {
3
+ type;
4
4
  constructor(type, message) {
5
5
  super(message);
6
6
  this.type = type;
@@ -1 +1 @@
1
- {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../../../src/public/node/plugins/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAG3C,OAAO,EAAC,GAAG,EAAS,MAAM,cAAc,CAAA;AAgBxC,MAAM,OAAO,WAAY,SAAQ,eAAe;IAE9C,YAAY,IAAqB,EAAE,OAAgB;QACjD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAuBD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAqB,EAA0B,EAAE;IAC9E,OAAO,KAAK,IAAI,EAAE,CAAC,KAAK,CAAA;AAC1B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAsD,EAAuB,EAAE;IACzG,OAAO,KAAK,EAAE,MAAwC,EAA8B,EAAE;QACpF,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ;YAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAA;QACzF,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {ExtendableError} from '../error.js'\nimport {OutputMessage} from '../output.js'\nimport {FanoutHookFunction, PluginReturnsForHook} from '../plugins.js'\nimport {err, Result} from '../result.js'\nimport {TokenItem} from '../ui.js'\n\nexport type TunnelErrorType = 'invalid-provider' | 'tunnel-already-running' | 'wrong-credentials' | 'unknown'\nexport interface TunnelClient {\n getTunnelStatus: () => TunnelStatusType\n stopTunnel: () => void\n provider: string\n port: number\n}\nexport type TunnelStatusType =\n | {status: 'not-started'}\n | {status: 'starting'}\n | {status: 'connected'; url: string}\n | {status: 'error'; message: TokenItem | OutputMessage; tryMessage?: TokenItem | OutputMessage | null}\n\nexport class TunnelError extends ExtendableError {\n type: TunnelErrorType\n constructor(type: TunnelErrorType, message?: string) {\n super(message)\n this.type = type\n }\n}\n\n/**\n * Tunnel Plugins types\n *\n * Any plugin that provides tunnel functionality should implement `defineProvider`and `startTunnel`\n */\nexport interface HookReturnPerTunnelPlugin {\n tunnel_start: {\n options: {port: number; provider: string}\n pluginReturns: Record<string, Result<TunnelClient, TunnelError>>\n }\n tunnel_provider: {\n options: Record<string, never>\n pluginReturns: Record<string, {name: string}>\n }\n}\n\nexport type TunnelProviderFunction = FanoutHookFunction<'tunnel_provider', ''>\nexport type TunnelStartFunction = FanoutHookFunction<'tunnel_start', ''>\nexport type TunnelStartReturn = PluginReturnsForHook<'tunnel_start', ''>\nexport type TunnelStartAction = (port: number) => Promise<TunnelStartReturn>\n\nexport const defineProvider = (input: {name: string}): TunnelProviderFunction => {\n return async () => input\n}\n\nexport const startTunnel = (options: {provider: string; action: TunnelStartAction}): TunnelStartFunction => {\n return async (inputs: {provider: string; port: number}): Promise<TunnelStartReturn> => {\n if (inputs.provider !== options.provider) return err(new TunnelError('invalid-provider'))\n return options.action(inputs.port)\n }\n}\n"]}
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../../../src/public/node/plugins/tunnel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,GAAG,EAAS,MAAM,cAAc,CAAA;AAgBxC,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,IAAI,CAAiB;IACrB,YAAY,IAAqB,EAAE,OAAgB;QACjD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAuBD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAqB,EAA0B,EAAE;IAC9E,OAAO,KAAK,IAAI,EAAE,CAAC,KAAK,CAAA;AAC1B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAsD,EAAuB,EAAE;IACzG,OAAO,KAAK,EAAE,MAAwC,EAA8B,EAAE;QACpF,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ;YAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAA;QACzF,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {OutputMessage} from '../output.js'\nimport {FanoutHookFunction, PluginReturnsForHook} from '../plugins.js'\nimport {err, Result} from '../result.js'\nimport {TokenItem} from '../ui.js'\n\nexport type TunnelErrorType = 'invalid-provider' | 'tunnel-already-running' | 'wrong-credentials' | 'unknown'\nexport interface TunnelClient {\n getTunnelStatus: () => TunnelStatusType\n stopTunnel: () => void\n provider: string\n port: number\n}\nexport type TunnelStatusType =\n | {status: 'not-started'}\n | {status: 'starting'}\n | {status: 'connected'; url: string}\n | {status: 'error'; message: TokenItem | OutputMessage; tryMessage?: TokenItem | OutputMessage | null}\n\nexport class TunnelError extends Error {\n type: TunnelErrorType\n constructor(type: TunnelErrorType, message?: string) {\n super(message)\n this.type = type\n }\n}\n\n/**\n * Tunnel Plugins types\n *\n * Any plugin that provides tunnel functionality should implement `defineProvider`and `startTunnel`\n */\nexport interface HookReturnPerTunnelPlugin {\n tunnel_start: {\n options: {port: number; provider: string}\n pluginReturns: Record<string, Result<TunnelClient, TunnelError>>\n }\n tunnel_provider: {\n options: Record<string, never>\n pluginReturns: Record<string, {name: string}>\n }\n}\n\nexport type TunnelProviderFunction = FanoutHookFunction<'tunnel_provider', ''>\nexport type TunnelStartFunction = FanoutHookFunction<'tunnel_start', ''>\nexport type TunnelStartReturn = PluginReturnsForHook<'tunnel_start', ''>\nexport type TunnelStartAction = (port: number) => Promise<TunnelStartReturn>\n\nexport const defineProvider = (input: {name: string}): TunnelProviderFunction => {\n return async () => input\n}\n\nexport const startTunnel = (options: {provider: string; action: TunnelStartAction}): TunnelStartFunction => {\n return async (inputs: {provider: string; port: number}): Promise<TunnelStartReturn> => {\n if (inputs.provider !== options.provider) return err(new TunnelError('invalid-provider'))\n return options.action(inputs.port)\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { FatalError, AbortError, ExtendableError } from './error.js';
1
+ import { FatalError, AbortError } from './error.js';
2
2
  /**
3
3
  * Utility metho to create an `Ok` result from a `value`
4
4
  *
@@ -14,6 +14,7 @@ export const ok = (value) => new Ok(value);
14
14
  */
15
15
  export const err = (err) => new Err(err);
16
16
  export class Ok {
17
+ value;
17
18
  constructor(value) {
18
19
  this.value = value;
19
20
  }
@@ -68,6 +69,7 @@ export class Ok {
68
69
  }
69
70
  }
70
71
  export class Err {
72
+ error;
71
73
  // eslint-disable-next-line n/handle-callback-err
72
74
  constructor(error) {
73
75
  this.error = error;
@@ -103,7 +105,7 @@ export class Err {
103
105
  if (this.error instanceof FatalError) {
104
106
  throw this.error;
105
107
  }
106
- else if (this.error instanceof ExtendableError || this.error instanceof Error) {
108
+ else if (this.error instanceof Error) {
107
109
  const error = new AbortError(this.error.message);
108
110
  error.stack = this.error.stack;
109
111
  throw error;
@@ -1 +1 @@
1
- {"version":3,"file":"result.js","sourceRoot":"","sources":["../../../src/public/node/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,YAAY,CAAA;AAIlE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAyB,KAAa,EAAsB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAA;AAE9F;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAmC,GAAW,EAAuB,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;AAEvG,MAAM,OAAO,EAAE;IACb,YAAqB,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAEtC;;;;OAIG;IACH,KAAK;QACH,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,OAAgC;QACrC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnB,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAe,MAAuC;QACvD,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/B,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAe,OAAwC;QAC7D,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;CACF;AAED,MAAM,OAAO,GAAG;IACd,iDAAiD;IACjD,YAAqB,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAEtC;;;;OAIG;IACH,KAAK;QACH,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAiC;QACtC,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,0IAA0I;QAC1I,MAAM,IAAI,CAAC,KAAK,CAAA;IAClB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,IAAI,CAAC,KAAK,YAAY,UAAU,EAAE,CAAC;YACrC,MAAM,IAAI,CAAC,KAAK,CAAA;QAClB,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,YAAY,eAAe,IAAI,IAAI,CAAC,KAAK,YAAY,KAAK,EAAE,CAAC;YAChF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAChD,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAA;YAC9B,MAAM,KAAK,CAAA;QACb,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAe,OAA6C;QAC7D,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAe,MAAuC;QAC5D,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IAChC,CAAC;CACF","sourcesContent":["import {FatalError, AbortError, ExtendableError} from './error.js'\n\nexport type Result<TValue, TError> = Ok<TValue, TError> | Err<TValue, TError>\n\n/**\n * Utility metho to create an `Ok` result from a `value`\n *\n * @param value - `value` used to crete the `Result`\n * @returns an instance of a `Ok` `Result` inferring its type\n */\nexport const ok = <TValue, TError = never>(value: TValue): Ok<TValue, TError> => new Ok(value)\n\n/**\n * Utility method to create an `Error` result from an `error`\n *\n * @param err - `error` used to crete the `Result`\n * @returns an instance of an `Error` `Result` inferring its type\n */\nexport const err = <TValue = never, TError = unknown>(err: TError): Err<TValue, TError> => new Err(err)\n\nexport class Ok<TValue, TError> {\n constructor(readonly value: TValue) {}\n\n /**\n * Check if a `Result` is an `Err` inferring its type. `!isErr()` should be used before accessing the `value`\n *\n * @returns `false` as the `Resul` is `OK`\n */\n isErr(): this is Err<TValue, TError> {\n return false\n }\n\n /**\n * Runs the `handler` method an return the same an unaltered copy of the `Result`. It could be used to log an\n * output when the result is `Ok` without breaking the flow\n *\n * @param handler - method to be run when the result is `Ok`\n * @returns a copy of the same `Result`\n */\n doOnOk(handler: (value: TValue) => void): Result<TValue, TError> {\n handler(this.value)\n return ok(this.value)\n }\n\n /**\n * A safe mode to throw the `error` of the `Result`\n */\n valueOrBug(): TValue {\n return this.value\n }\n\n /**\n * Throws an abort error if the result doesn't represent a value.\n */\n valueOrAbort(): TValue {\n return this.value\n }\n\n /**\n * Maps the value to another one with a different type. It leaves the `Error` type unaltered\n *\n * @param mapper - The mapper method to apply an `OK` value\n * @returns a new result with the new mapped value\n */\n map<TMappedValue>(mapper: (value: TValue) => TMappedValue): Result<TMappedValue, TError> {\n return ok(mapper(this.value))\n }\n\n /**\n * Maps the error type to another one. It leaves the `Ok` type and value unaltered\n *\n * @param _mapper - This mapper method is not used for an `Ok` value\n * @returns a new result with the new mapped error type and an value\n */\n mapError<TMappedError>(_mapper: (error: TError) => TMappedError): Result<TValue, TMappedError> {\n return ok(this.value)\n }\n}\n\nexport class Err<TValue, TError> {\n // eslint-disable-next-line n/handle-callback-err\n constructor(readonly error: TError) {}\n\n /**\n * Check if a `Result` is an `Err` inferring its type. `!isErr()` should be used before accessing the `value`\n *\n * @returns `false` as the `Resul` is `OK`\n */\n isErr(): this is Err<TValue, TError> {\n return true\n }\n\n /**\n * Return an unaltered copy of the `Error` without doing anything.\n *\n * @param _handler - This handler method is not used for an `Error`\n * @returns a copy of the same `Error`\n */\n doOnOk(_handler: (value: TValue) => void): Result<TValue, TError> {\n return err(this.error)\n }\n\n /**\n * A safe mode to throw the `error` of the `Result`\n */\n valueOrBug(): TValue {\n // eslint-disable-next-line @typescript-eslint/only-throw-error -- TError may not extend Error; this is intentional for the Result pattern\n throw this.error\n }\n\n /**\n * Throws an abort error if the result doesn't represent a value.\n */\n valueOrAbort(): TValue {\n if (this.error instanceof FatalError) {\n throw this.error\n } else if (this.error instanceof ExtendableError || this.error instanceof Error) {\n const error = new AbortError(this.error.message)\n error.stack = this.error.stack\n throw error\n } else {\n throw new AbortError(`${this.error}`)\n }\n }\n\n /**\n * Maps the value type to another one. It leaves the `Error` unaltered\n *\n * @param _mapper - This mapper method is not used for an `Error` value\n * @returns a new result with the new value type and an unaltered error\n */\n map<TMappedValue>(_mapper: (valueOrBug: TValue) => TMappedValue): Result<TMappedValue, TError> {\n return err(this.error)\n }\n\n /**\n * Maps the error to another one with a different type. It leaves the value type unaltered\n *\n * @param mapper - The mapper method to apply an `Error` value\n * @returns a new result with the new mapped error\n */\n mapError<TMappedError>(mapper: (error: TError) => TMappedError): Result<TValue, TMappedError> {\n return err(mapper(this.error))\n }\n}\n"]}
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../../src/public/node/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,UAAU,EAAC,MAAM,YAAY,CAAA;AAIjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAyB,KAAa,EAAsB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAA;AAE9F;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAmC,GAAW,EAAuB,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;AAEvG,MAAM,OAAO,EAAE;IACQ;IAArB,YAAqB,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAEtC;;;;OAIG;IACH,KAAK;QACH,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,OAAgC;QACrC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnB,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAe,MAAuC;QACvD,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/B,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAe,OAAwC;QAC7D,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;CACF;AAED,MAAM,OAAO,GAAG;IAEO;IADrB,iDAAiD;IACjD,YAAqB,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAEtC;;;;OAIG;IACH,KAAK;QACH,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAiC;QACtC,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,0IAA0I;QAC1I,MAAM,IAAI,CAAC,KAAK,CAAA;IAClB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,IAAI,CAAC,KAAK,YAAY,UAAU,EAAE,CAAC;YACrC,MAAM,IAAI,CAAC,KAAK,CAAA;QAClB,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,YAAY,KAAK,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAChD,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAA;YAC9B,MAAM,KAAK,CAAA;QACb,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAe,OAA6C;QAC7D,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxB,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CAAe,MAAuC;QAC5D,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IAChC,CAAC;CACF","sourcesContent":["import {FatalError, AbortError} from './error.js'\n\nexport type Result<TValue, TError> = Ok<TValue, TError> | Err<TValue, TError>\n\n/**\n * Utility metho to create an `Ok` result from a `value`\n *\n * @param value - `value` used to crete the `Result`\n * @returns an instance of a `Ok` `Result` inferring its type\n */\nexport const ok = <TValue, TError = never>(value: TValue): Ok<TValue, TError> => new Ok(value)\n\n/**\n * Utility method to create an `Error` result from an `error`\n *\n * @param err - `error` used to crete the `Result`\n * @returns an instance of an `Error` `Result` inferring its type\n */\nexport const err = <TValue = never, TError = unknown>(err: TError): Err<TValue, TError> => new Err(err)\n\nexport class Ok<TValue, TError> {\n constructor(readonly value: TValue) {}\n\n /**\n * Check if a `Result` is an `Err` inferring its type. `!isErr()` should be used before accessing the `value`\n *\n * @returns `false` as the `Resul` is `OK`\n */\n isErr(): this is Err<TValue, TError> {\n return false\n }\n\n /**\n * Runs the `handler` method an return the same an unaltered copy of the `Result`. It could be used to log an\n * output when the result is `Ok` without breaking the flow\n *\n * @param handler - method to be run when the result is `Ok`\n * @returns a copy of the same `Result`\n */\n doOnOk(handler: (value: TValue) => void): Result<TValue, TError> {\n handler(this.value)\n return ok(this.value)\n }\n\n /**\n * A safe mode to throw the `error` of the `Result`\n */\n valueOrBug(): TValue {\n return this.value\n }\n\n /**\n * Throws an abort error if the result doesn't represent a value.\n */\n valueOrAbort(): TValue {\n return this.value\n }\n\n /**\n * Maps the value to another one with a different type. It leaves the `Error` type unaltered\n *\n * @param mapper - The mapper method to apply an `OK` value\n * @returns a new result with the new mapped value\n */\n map<TMappedValue>(mapper: (value: TValue) => TMappedValue): Result<TMappedValue, TError> {\n return ok(mapper(this.value))\n }\n\n /**\n * Maps the error type to another one. It leaves the `Ok` type and value unaltered\n *\n * @param _mapper - This mapper method is not used for an `Ok` value\n * @returns a new result with the new mapped error type and an value\n */\n mapError<TMappedError>(_mapper: (error: TError) => TMappedError): Result<TValue, TMappedError> {\n return ok(this.value)\n }\n}\n\nexport class Err<TValue, TError> {\n // eslint-disable-next-line n/handle-callback-err\n constructor(readonly error: TError) {}\n\n /**\n * Check if a `Result` is an `Err` inferring its type. `!isErr()` should be used before accessing the `value`\n *\n * @returns `false` as the `Resul` is `OK`\n */\n isErr(): this is Err<TValue, TError> {\n return true\n }\n\n /**\n * Return an unaltered copy of the `Error` without doing anything.\n *\n * @param _handler - This handler method is not used for an `Error`\n * @returns a copy of the same `Error`\n */\n doOnOk(_handler: (value: TValue) => void): Result<TValue, TError> {\n return err(this.error)\n }\n\n /**\n * A safe mode to throw the `error` of the `Result`\n */\n valueOrBug(): TValue {\n // eslint-disable-next-line @typescript-eslint/only-throw-error -- TError may not extend Error; this is intentional for the Result pattern\n throw this.error\n }\n\n /**\n * Throws an abort error if the result doesn't represent a value.\n */\n valueOrAbort(): TValue {\n if (this.error instanceof FatalError) {\n throw this.error\n } else if (this.error instanceof Error) {\n const error = new AbortError(this.error.message)\n error.stack = this.error.stack\n throw error\n } else {\n throw new AbortError(`${this.error}`)\n }\n }\n\n /**\n * Maps the value type to another one. It leaves the `Error` unaltered\n *\n * @param _mapper - This mapper method is not used for an `Error` value\n * @returns a new result with the new value type and an unaltered error\n */\n map<TMappedValue>(_mapper: (valueOrBug: TValue) => TMappedValue): Result<TMappedValue, TError> {\n return err(this.error)\n }\n\n /**\n * Maps the error to another one with a different type. It leaves the value type unaltered\n *\n * @param mapper - The mapper method to apply an `Error` value\n * @returns a new result with the new mapped error\n */\n mapError<TMappedError>(mapper: (error: TError) => TMappedError): Result<TValue, TMappedError> {\n return err(mapper(this.error))\n }\n}\n"]}
@@ -4,14 +4,15 @@
4
4
  * automatically queued for the next batch.
5
5
  */
6
6
  export class SerialBatchProcessor {
7
+ processBatch;
8
+ queue = [];
9
+ processingPromise = undefined;
7
10
  constructor(processBatch) {
8
11
  this.processBatch = processBatch;
9
- this.queue = [];
10
- this.processingPromise = undefined;
11
12
  }
12
13
  enqueue(item) {
13
14
  this.queue.push(item);
14
- this.processingPromise ?? (this.processingPromise = this.startProcessing());
15
+ this.processingPromise ??= this.startProcessing();
15
16
  }
16
17
  async waitForCompletion() {
17
18
  if (this.processingPromise) {
@@ -1 +1 @@
1
- {"version":3,"file":"serial-batch-processor.js","sourceRoot":"","sources":["../../../src/public/node/serial-batch-processor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,oBAAoB;IAI/B,YAA6B,YAA2C;QAA3C,iBAAY,GAAZ,YAAY,CAA+B;QAHhE,UAAK,GAAQ,EAAE,CAAA;QACf,sBAAiB,GAA8B,SAAS,CAAA;IAEW,CAAC;IAE5E,OAAO,CAAC,IAAO;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAErB,IAAI,CAAC,iBAAiB,KAAtB,IAAI,CAAC,iBAAiB,GAAK,IAAI,CAAC,eAAe,EAAE,EAAA;IACnD,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,iBAAiB,CAAA;QAC/B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,oCAAoC;gBACpC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;gBAEf,4BAA4B;gBAC5B,4CAA4C;gBAC5C,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,iDAAiD;YACjD,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAA;QACpC,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Handles serial processing of items with automatic batching\n * Only one processing operation runs at a time, with new items\n * automatically queued for the next batch.\n */\nexport class SerialBatchProcessor<T> {\n private queue: T[] = []\n private processingPromise: Promise<void> | undefined = undefined\n\n constructor(private readonly processBatch: (items: T[]) => Promise<void>) {}\n\n enqueue(item: T): void {\n this.queue.push(item)\n\n this.processingPromise ??= this.startProcessing()\n }\n\n async waitForCompletion(): Promise<void> {\n if (this.processingPromise) {\n return this.processingPromise\n }\n }\n\n private async startProcessing(): Promise<void> {\n try {\n while (this.queue.length > 0) {\n // Get current batch and clear queue\n const batch = [...this.queue]\n this.queue = []\n\n // Process the current batch\n // eslint-disable-next-line no-await-in-loop\n await this.processBatch(batch)\n }\n } finally {\n // Always make sure we reset the processing state\n this.processingPromise = undefined\n }\n }\n}\n"]}
1
+ {"version":3,"file":"serial-batch-processor.js","sourceRoot":"","sources":["../../../src/public/node/serial-batch-processor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,oBAAoB;IAIF;IAHrB,KAAK,GAAQ,EAAE,CAAA;IACf,iBAAiB,GAA8B,SAAS,CAAA;IAEhE,YAA6B,YAA2C;QAA3C,iBAAY,GAAZ,YAAY,CAA+B;IAAG,CAAC;IAE5E,OAAO,CAAC,IAAO;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAErB,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAAC,eAAe,EAAE,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,iBAAiB,CAAA;QAC/B,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,oCAAoC;gBACpC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;gBAEf,4BAA4B;gBAC5B,4CAA4C;gBAC5C,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,iDAAiD;YACjD,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAA;QACpC,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Handles serial processing of items with automatic batching\n * Only one processing operation runs at a time, with new items\n * automatically queued for the next batch.\n */\nexport class SerialBatchProcessor<T> {\n private queue: T[] = []\n private processingPromise: Promise<void> | undefined = undefined\n\n constructor(private readonly processBatch: (items: T[]) => Promise<void>) {}\n\n enqueue(item: T): void {\n this.queue.push(item)\n\n this.processingPromise ??= this.startProcessing()\n }\n\n async waitForCompletion(): Promise<void> {\n if (this.processingPromise) {\n return this.processingPromise\n }\n }\n\n private async startProcessing(): Promise<void> {\n try {\n while (this.queue.length > 0) {\n // Get current batch and clear queue\n const batch = [...this.queue]\n this.queue = []\n\n // Process the current batch\n // eslint-disable-next-line no-await-in-loop\n await this.processBatch(batch)\n }\n } finally {\n // Always make sure we reset the processing state\n this.processingPromise = undefined\n }\n }\n}\n"]}
@@ -6,7 +6,7 @@ const STORE_AUTH_PROJECT_NAME = 'shopify-cli-store';
6
6
  const EXPIRY_MARGIN_MS = 4 * 60 * 1000;
7
7
  let _storeAuthSessionStorage;
8
8
  function storeAuthSessionStorage() {
9
- _storeAuthSessionStorage ?? (_storeAuthSessionStorage = new LocalStorage({ projectName: STORE_AUTH_PROJECT_NAME }));
9
+ _storeAuthSessionStorage ??= new LocalStorage({ projectName: STORE_AUTH_PROJECT_NAME });
10
10
  return _storeAuthSessionStorage;
11
11
  }
12
12
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"store-auth-session.js","sourceRoot":"","sources":["../../../src/public/node/store-auth-session.ts"],"names":[],"mappings":"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","sourcesContent":["import {STORE_AUTH_APP_CLIENT_ID} from './constants.js'\nimport {normalizeStoreFqdn} from './context/fqdn.js'\nimport {LocalStorage} from './local-storage.js'\nimport {setLastSeenUserId} from './session.js'\nimport type {JsonMapType} from './toml/codec.js'\nimport type {AdminSession} from './session.js'\n\nconst STORE_AUTH_PROJECT_NAME = 'shopify-cli-store'\nconst EXPIRY_MARGIN_MS = 4 * 60 * 1000\n\n/**\n * Discriminator for a stored store auth session.\n *\n * - 'standard': created via `shopify store auth`.\n * - 'preview': created via `shopify store create preview`; backed by a server-issued Admin API token.\n *\n * Stored sessions written before this discriminator existed have no `kind` field and are\n * read back as 'standard'.\n */\nexport type StoredStoreSessionKind = 'standard' | 'preview'\n\nexport interface StoredPreviewStoreMetadata {\n /** Placeholder account UUID returned by the preview-store backend when available. */\n placeholderAccountUuid?: string\n /** Numeric shop id returned by the preview-store backend. */\n shopId: string\n /** Store name returned by the preview-store backend. */\n name: string\n /** ISO country code requested for the store, when provided by the caller. */\n country?: string\n /** ISO timestamp for when the preview store was created locally. */\n createdAt: string\n /** Access URL returned by the preview-store backend. */\n accessUrl?: string\n}\n\nexport interface StoredStoreAppSession {\n store: string\n clientId: string\n userId: string\n accessToken: string\n refreshToken?: string\n scopes: string[]\n acquiredAt: string\n expiresAt?: string\n refreshTokenExpiresAt?: string\n associatedUser?: {\n id: number\n email?: string\n firstName?: string\n lastName?: string\n accountOwner?: boolean\n }\n /**\n * Discriminator. Optional in storage for back-compat with sessions written before the\n * field existed; `sessionKind()` resolves missing values to 'standard'.\n */\n kind?: StoredStoreSessionKind\n /** Preview-store-only metadata. Set iff `kind === 'preview'`. */\n preview?: StoredPreviewStoreMetadata\n}\n\ninterface StoredStoreAppSessionBucket {\n currentUserId: string\n sessionsByUserId: {[userId: string]: StoredStoreAppSession}\n}\n\ninterface StoreAuthSessionSchema {\n [key: string]: StoredStoreAppSessionBucket\n}\n\ntype RawStoreAuthSessionStorage = JsonMapType\n\nlet _storeAuthSessionStorage: LocalStorage<StoreAuthSessionSchema> | undefined\n\nfunction storeAuthSessionStorage() {\n _storeAuthSessionStorage ??= new LocalStorage<StoreAuthSessionSchema>({projectName: STORE_AUTH_PROJECT_NAME})\n return _storeAuthSessionStorage\n}\n\n/**\n * Build the local-storage key used for store-auth sessions.\n *\n * @param store - The normalized store FQDN.\n * @returns The store-auth session storage key.\n */\nexport function storeAuthSessionKey(store: string): string {\n return `${STORE_AUTH_APP_CLIENT_ID}::${escapeStoreAuthSessionKeySegment(store)}`\n}\n\nfunction escapeStoreAuthSessionKeySegment(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\\./g, '\\\\.')\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string'\n}\n\nfunction sanitizeAssociatedUser(value: unknown): StoredStoreAppSession['associatedUser'] | undefined {\n if (!value || typeof value !== 'object') return undefined\n\n const associatedUser = value as Record<string, unknown>\n if (typeof associatedUser.id !== 'number') return undefined\n\n return {\n id: associatedUser.id,\n ...(isString(associatedUser.email) ? {email: associatedUser.email} : {}),\n ...(isString(associatedUser.firstName) ? {firstName: associatedUser.firstName} : {}),\n ...(isString(associatedUser.lastName) ? {lastName: associatedUser.lastName} : {}),\n ...(typeof associatedUser.accountOwner === 'boolean' ? {accountOwner: associatedUser.accountOwner} : {}),\n }\n}\n\nfunction sanitizePreviewMetadata(value: unknown): StoredPreviewStoreMetadata | undefined {\n if (!value || typeof value !== 'object') return undefined\n\n const metadata = value as Record<string, unknown>\n if (!isString(metadata.shopId) || !isString(metadata.name) || !isString(metadata.createdAt)) return undefined\n\n return {\n shopId: metadata.shopId,\n name: metadata.name,\n createdAt: metadata.createdAt,\n ...(isString(metadata.placeholderAccountUuid) ? {placeholderAccountUuid: metadata.placeholderAccountUuid} : {}),\n ...(isString(metadata.country) ? {country: metadata.country} : {}),\n ...(isString(metadata.accessUrl) ? {accessUrl: metadata.accessUrl} : {}),\n }\n}\n\nfunction sanitizeStoredStoreAppSession(value: unknown): StoredStoreAppSession | undefined {\n if (!value || typeof value !== 'object') return undefined\n\n const session = value as Record<string, unknown>\n if (\n !isString(session.store) ||\n !isString(session.clientId) ||\n !isString(session.userId) ||\n !isString(session.accessToken) ||\n !Array.isArray(session.scopes) ||\n !session.scopes.every(isString) ||\n !isString(session.acquiredAt)\n ) {\n return undefined\n }\n\n const associatedUser = sanitizeAssociatedUser(session.associatedUser)\n\n // Discriminator is optional for back-compat: sessions written before this field existed\n // are read back as 'standard'. Unknown values are coerced to 'standard' and the field is\n // omitted from the result so it doesn't pollute legacy buckets.\n const kind: StoredStoreSessionKind = session.kind === 'preview' ? 'preview' : 'standard'\n const preview = kind === 'preview' ? sanitizePreviewMetadata(session.preview) : undefined\n\n // A session declared as 'preview' but missing/malformed metadata is rejected outright,\n // because store-list fallback and future re-mint/claim flows rely on this metadata.\n if (kind === 'preview' && !preview) return undefined\n\n return {\n store: session.store,\n clientId: session.clientId,\n userId: session.userId,\n accessToken: session.accessToken,\n scopes: session.scopes,\n acquiredAt: session.acquiredAt,\n ...(isString(session.refreshToken) ? {refreshToken: session.refreshToken} : {}),\n ...(isString(session.expiresAt) ? {expiresAt: session.expiresAt} : {}),\n ...(isString(session.refreshTokenExpiresAt) ? {refreshTokenExpiresAt: session.refreshTokenExpiresAt} : {}),\n ...(associatedUser ? {associatedUser} : {}),\n ...(kind === 'preview' ? {kind} : {}),\n ...(preview ? {preview} : {}),\n }\n}\n\nfunction sanitizeStoredStoreAppSessionBucket(\n store: string,\n storedBucket: unknown,\n storage: LocalStorage<StoreAuthSessionSchema>,\n): StoredStoreAppSessionBucket | undefined {\n if (!storedBucket || typeof storedBucket !== 'object') return undefined\n\n const {sessionsByUserId, currentUserId} = storedBucket as Partial<StoredStoreAppSessionBucket>\n const looksLikeBucket = sessionsByUserId !== undefined || currentUserId !== undefined\n if (!looksLikeBucket) return undefined\n\n const key = storeAuthSessionKey(store)\n if (\n !sessionsByUserId ||\n typeof sessionsByUserId !== 'object' ||\n Array.isArray(sessionsByUserId) ||\n typeof currentUserId !== 'string'\n ) {\n storage.delete(key)\n return undefined\n }\n\n const sanitizedSessionsByUserId = Object.fromEntries(\n Object.entries(sessionsByUserId).flatMap(([userId, session]) => {\n const sanitizedSession = sanitizeStoredStoreAppSession(session)\n return sanitizedSession ? [[userId, sanitizedSession]] : []\n }),\n )\n\n if (Object.keys(sanitizedSessionsByUserId).length !== Object.keys(sessionsByUserId).length) {\n if (sanitizedSessionsByUserId[currentUserId]) {\n storage.set(key, {\n currentUserId,\n sessionsByUserId: sanitizedSessionsByUserId,\n })\n } else {\n storage.delete(key)\n return undefined\n }\n }\n\n return {\n currentUserId,\n sessionsByUserId: sanitizedSessionsByUserId,\n }\n}\n\nfunction readStoredStoreAppSessionBucket(\n store: string,\n storage: LocalStorage<StoreAuthSessionSchema>,\n): StoredStoreAppSessionBucket | undefined {\n return sanitizeStoredStoreAppSessionBucket(store, storage.get(storeAuthSessionKey(store)), storage)\n}\n\n// `conf` persists dotted keys as nested objects. Store-auth callers should not\n// learn that layout directly; this helper keeps the current traversal private to\n// the persistence seam while higher-level code projects summaries instead.\nfunction readRawStoreAuthSessionStorage(storage: LocalStorage<StoreAuthSessionSchema>): RawStoreAuthSessionStorage {\n return (storage as unknown as {config?: {store?: RawStoreAuthSessionStorage}}).config?.store ?? {}\n}\n\n/**\n * Project the current session for every store that has locally stored store auth.\n *\n * @param storage - Optional storage override for tests.\n * @returns Current stored store auth sessions.\n */\nexport function listCurrentStoredStoreAppSessions(\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): StoredStoreAppSession[] {\n const sessions: StoredStoreAppSession[] = []\n const keyPrefix = `${STORE_AUTH_APP_CLIENT_ID}::`\n\n for (const [key, value] of Object.entries(readRawStoreAuthSessionStorage(storage))) {\n if (!key.startsWith(keyPrefix)) continue\n\n const bucket = sanitizeStoredStoreAppSessionBucket(key.slice(keyPrefix.length), value, storage)\n const session = bucket?.sessionsByUserId[bucket.currentUserId]\n if (session) sessions.push(session)\n }\n\n return sessions\n}\n\n/**\n * Get the current stored store auth session for a store.\n *\n * @param store - The store FQDN or URL to load a store-auth session for.\n * @param storage - Optional storage override for tests.\n * @returns The current stored store auth session, or undefined when missing or malformed.\n */\nexport function getCurrentStoredStoreAppSession(\n store: string,\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): StoredStoreAppSession | undefined {\n const storeFqdn = normalizeStoreFqdn(store)\n const bucket = readStoredStoreAppSessionBucket(storeFqdn, storage)\n if (!bucket) return undefined\n\n const session = bucket.sessionsByUserId[bucket.currentUserId]\n if (!session) {\n storage.delete(storeAuthSessionKey(storeFqdn))\n return undefined\n }\n\n return session\n}\n\n/**\n * Persist a store auth session and mark it as current for its store.\n *\n * @param session - The store auth session to persist.\n * @param storage - Optional storage override for tests.\n */\nexport function setStoredStoreAppSession(\n session: StoredStoreAppSession,\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): void {\n const key = storeAuthSessionKey(session.store)\n const existingBucket = readStoredStoreAppSessionBucket(session.store, storage)\n\n const nextBucket: StoredStoreAppSessionBucket = {\n currentUserId: session.userId,\n sessionsByUserId: {\n ...(existingBucket?.sessionsByUserId ?? {}),\n [session.userId]: session,\n },\n }\n\n storage.set(key, nextBucket)\n}\n\n/**\n * Clear stored store auth sessions for a store.\n *\n * @param store - The store FQDN or URL to clear sessions for.\n * @param userIdOrStorage - Optional user ID to clear, or storage override when clearing all users.\n * @param maybeStorage - Optional storage override when clearing one user.\n */\nexport function clearStoredStoreAppSession(\n store: string,\n userIdOrStorage?: string | LocalStorage<StoreAuthSessionSchema>,\n maybeStorage?: LocalStorage<StoreAuthSessionSchema>,\n): void {\n const storeFqdn = normalizeStoreFqdn(store)\n const userId = typeof userIdOrStorage === 'string' ? userIdOrStorage : undefined\n const storage = (typeof userIdOrStorage === 'string' ? maybeStorage : userIdOrStorage) ?? storeAuthSessionStorage()\n\n const key = storeAuthSessionKey(storeFqdn)\n\n if (!userId) {\n storage.delete(key)\n return\n }\n\n const existingBucket = readStoredStoreAppSessionBucket(storeFqdn, storage)\n if (!existingBucket) return\n\n const {[userId]: _removedSession, ...remainingSessions} = existingBucket.sessionsByUserId\n\n const remainingUserIds = Object.keys(remainingSessions)\n if (remainingUserIds.length === 0) {\n storage.delete(key)\n return\n }\n\n storage.set(key, {\n currentUserId: existingBucket.currentUserId === userId ? remainingUserIds[0]! : existingBucket.currentUserId,\n sessionsByUserId: remainingSessions,\n })\n}\n\n/**\n * Load an Admin API session from the local store-auth cache when one is currently usable.\n *\n * @param store - The store FQDN or URL to load a store-auth session for.\n * @param storage - Optional storage override for tests.\n * @returns An Admin session, or undefined when no usable session is cached.\n */\nexport function getStoreAuthAdminSession(\n store: string,\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): AdminSession | undefined {\n const storeFqdn = normalizeStoreFqdn(store)\n const session = getCurrentStoredStoreAppSession(storeFqdn, storage)\n if (!session || isSessionExpired(session)) return undefined\n\n setLastSeenUserId(session.userId)\n\n return {\n token: session.accessToken,\n storeFqdn,\n }\n}\n\n/**\n * Check whether a stored store auth session is expired, including the refresh margin.\n *\n * @param session - The stored store auth session.\n * @returns True when the session is expired or has an invalid expiry timestamp.\n */\nexport function isSessionExpired(session: StoredStoreAppSession): boolean {\n if (!session.expiresAt) return false\n\n const expiresAtMs = new Date(session.expiresAt).getTime()\n if (Number.isNaN(expiresAtMs)) return true\n\n return expiresAtMs - EXPIRY_MARGIN_MS < Date.now()\n}\n"]}
1
+ {"version":3,"file":"store-auth-session.js","sourceRoot":"","sources":["../../../src/public/node/store-auth-session.ts"],"names":[],"mappings":"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","sourcesContent":["import {STORE_AUTH_APP_CLIENT_ID} from './constants.js'\nimport {normalizeStoreFqdn} from './context/fqdn.js'\nimport {LocalStorage} from './local-storage.js'\nimport {setLastSeenUserId} from './session.js'\nimport type {JsonMapType} from './toml/codec.js'\nimport type {AdminSession} from './session.js'\n\nconst STORE_AUTH_PROJECT_NAME = 'shopify-cli-store'\nconst EXPIRY_MARGIN_MS = 4 * 60 * 1000\n\n/**\n * Discriminator for a stored store auth session.\n *\n * - 'standard': created via `shopify store auth`.\n * - 'preview': created via `shopify store create preview`; backed by a server-issued Admin API token.\n *\n * Stored sessions written before this discriminator existed have no `kind` field and are\n * read back as 'standard'.\n */\nexport type StoredStoreSessionKind = 'standard' | 'preview'\n\nexport interface StoredPreviewStoreMetadata {\n /** Placeholder account UUID returned by the preview-store backend when available. */\n placeholderAccountUuid?: string\n /** Numeric shop id returned by the preview-store backend. */\n shopId: string\n /** Store name returned by the preview-store backend. */\n name: string\n /** ISO country code requested for the store, when provided by the caller. */\n country?: string\n /** ISO timestamp for when the preview store was created locally. */\n createdAt: string\n /** Access URL returned by the preview-store backend. */\n accessUrl?: string\n}\n\nexport interface StoredStoreAppSession {\n store: string\n clientId: string\n userId: string\n accessToken: string\n refreshToken?: string\n scopes: string[]\n acquiredAt: string\n expiresAt?: string\n refreshTokenExpiresAt?: string\n associatedUser?: {\n id: number\n email?: string\n firstName?: string\n lastName?: string\n accountOwner?: boolean\n }\n /**\n * Discriminator. Optional in storage for back-compat with sessions written before the\n * field existed; `sessionKind()` resolves missing values to 'standard'.\n */\n kind?: StoredStoreSessionKind\n /** Preview-store-only metadata. Set iff `kind === 'preview'`. */\n preview?: StoredPreviewStoreMetadata\n}\n\ninterface StoredStoreAppSessionBucket {\n currentUserId: string\n sessionsByUserId: {[userId: string]: StoredStoreAppSession}\n}\n\ninterface StoreAuthSessionSchema {\n [key: string]: StoredStoreAppSessionBucket\n}\n\ntype RawStoreAuthSessionStorage = JsonMapType\n\nlet _storeAuthSessionStorage: LocalStorage<StoreAuthSessionSchema> | undefined\n\nfunction storeAuthSessionStorage() {\n _storeAuthSessionStorage ??= new LocalStorage<StoreAuthSessionSchema>({projectName: STORE_AUTH_PROJECT_NAME})\n return _storeAuthSessionStorage\n}\n\n/**\n * Build the local-storage key used for store-auth sessions.\n *\n * @param store - The normalized store FQDN.\n * @returns The store-auth session storage key.\n */\nexport function storeAuthSessionKey(store: string): string {\n return `${STORE_AUTH_APP_CLIENT_ID}::${escapeStoreAuthSessionKeySegment(store)}`\n}\n\nfunction escapeStoreAuthSessionKeySegment(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\\./g, '\\\\.')\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string'\n}\n\nfunction sanitizeAssociatedUser(value: unknown): StoredStoreAppSession['associatedUser'] | undefined {\n if (!value || typeof value !== 'object') return undefined\n\n const associatedUser = value as Record<string, unknown>\n if (typeof associatedUser.id !== 'number') return undefined\n\n return {\n id: associatedUser.id,\n ...(isString(associatedUser.email) ? {email: associatedUser.email} : {}),\n ...(isString(associatedUser.firstName) ? {firstName: associatedUser.firstName} : {}),\n ...(isString(associatedUser.lastName) ? {lastName: associatedUser.lastName} : {}),\n ...(typeof associatedUser.accountOwner === 'boolean' ? {accountOwner: associatedUser.accountOwner} : {}),\n }\n}\n\nfunction sanitizePreviewMetadata(value: unknown): StoredPreviewStoreMetadata | undefined {\n if (!value || typeof value !== 'object') return undefined\n\n const metadata = value as Record<string, unknown>\n if (!isString(metadata.shopId) || !isString(metadata.name) || !isString(metadata.createdAt)) return undefined\n\n return {\n shopId: metadata.shopId,\n name: metadata.name,\n createdAt: metadata.createdAt,\n ...(isString(metadata.placeholderAccountUuid) ? {placeholderAccountUuid: metadata.placeholderAccountUuid} : {}),\n ...(isString(metadata.country) ? {country: metadata.country} : {}),\n ...(isString(metadata.accessUrl) ? {accessUrl: metadata.accessUrl} : {}),\n }\n}\n\nfunction sanitizeStoredStoreAppSession(value: unknown): StoredStoreAppSession | undefined {\n if (!value || typeof value !== 'object') return undefined\n\n const session = value as Record<string, unknown>\n if (\n !isString(session.store) ||\n !isString(session.clientId) ||\n !isString(session.userId) ||\n !isString(session.accessToken) ||\n !Array.isArray(session.scopes) ||\n !session.scopes.every(isString) ||\n !isString(session.acquiredAt)\n ) {\n return undefined\n }\n\n const associatedUser = sanitizeAssociatedUser(session.associatedUser)\n\n // Discriminator is optional for back-compat: sessions written before this field existed\n // are read back as 'standard'. Unknown values are coerced to 'standard' and the field is\n // omitted from the result so it doesn't pollute legacy buckets.\n const kind: StoredStoreSessionKind = session.kind === 'preview' ? 'preview' : 'standard'\n const preview = kind === 'preview' ? sanitizePreviewMetadata(session.preview) : undefined\n\n // A session declared as 'preview' but missing/malformed metadata is rejected outright,\n // because store-list fallback and future re-mint/claim flows rely on this metadata.\n if (kind === 'preview' && !preview) return undefined\n\n return {\n store: session.store,\n clientId: session.clientId,\n userId: session.userId,\n accessToken: session.accessToken,\n scopes: session.scopes,\n acquiredAt: session.acquiredAt,\n ...(isString(session.refreshToken) ? {refreshToken: session.refreshToken} : {}),\n ...(isString(session.expiresAt) ? {expiresAt: session.expiresAt} : {}),\n ...(isString(session.refreshTokenExpiresAt) ? {refreshTokenExpiresAt: session.refreshTokenExpiresAt} : {}),\n ...(associatedUser ? {associatedUser} : {}),\n ...(kind === 'preview' ? {kind} : {}),\n ...(preview ? {preview} : {}),\n }\n}\n\nfunction sanitizeStoredStoreAppSessionBucket(\n store: string,\n storedBucket: unknown,\n storage: LocalStorage<StoreAuthSessionSchema>,\n): StoredStoreAppSessionBucket | undefined {\n if (!storedBucket || typeof storedBucket !== 'object') return undefined\n\n const {sessionsByUserId, currentUserId} = storedBucket as Partial<StoredStoreAppSessionBucket>\n const looksLikeBucket = sessionsByUserId !== undefined || currentUserId !== undefined\n if (!looksLikeBucket) return undefined\n\n const key = storeAuthSessionKey(store)\n if (\n !sessionsByUserId ||\n typeof sessionsByUserId !== 'object' ||\n Array.isArray(sessionsByUserId) ||\n typeof currentUserId !== 'string'\n ) {\n storage.delete(key)\n return undefined\n }\n\n const sanitizedSessionsByUserId = Object.fromEntries(\n Object.entries(sessionsByUserId).flatMap(([userId, session]) => {\n const sanitizedSession = sanitizeStoredStoreAppSession(session)\n return sanitizedSession ? [[userId, sanitizedSession]] : []\n }),\n )\n\n if (Object.keys(sanitizedSessionsByUserId).length !== Object.keys(sessionsByUserId).length) {\n if (sanitizedSessionsByUserId[currentUserId]) {\n storage.set(key, {\n currentUserId,\n sessionsByUserId: sanitizedSessionsByUserId,\n })\n } else {\n storage.delete(key)\n return undefined\n }\n }\n\n return {\n currentUserId,\n sessionsByUserId: sanitizedSessionsByUserId,\n }\n}\n\nfunction readStoredStoreAppSessionBucket(\n store: string,\n storage: LocalStorage<StoreAuthSessionSchema>,\n): StoredStoreAppSessionBucket | undefined {\n return sanitizeStoredStoreAppSessionBucket(store, storage.get(storeAuthSessionKey(store)), storage)\n}\n\n// `conf` persists dotted keys as nested objects. Store-auth callers should not\n// learn that layout directly; this helper keeps the current traversal private to\n// the persistence seam while higher-level code projects summaries instead.\nfunction readRawStoreAuthSessionStorage(storage: LocalStorage<StoreAuthSessionSchema>): RawStoreAuthSessionStorage {\n return (storage as unknown as {config?: {store?: RawStoreAuthSessionStorage}}).config?.store ?? {}\n}\n\n/**\n * Project the current session for every store that has locally stored store auth.\n *\n * @param storage - Optional storage override for tests.\n * @returns Current stored store auth sessions.\n */\nexport function listCurrentStoredStoreAppSessions(\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): StoredStoreAppSession[] {\n const sessions: StoredStoreAppSession[] = []\n const keyPrefix = `${STORE_AUTH_APP_CLIENT_ID}::`\n\n for (const [key, value] of Object.entries(readRawStoreAuthSessionStorage(storage))) {\n if (!key.startsWith(keyPrefix)) continue\n\n const bucket = sanitizeStoredStoreAppSessionBucket(key.slice(keyPrefix.length), value, storage)\n const session = bucket?.sessionsByUserId[bucket.currentUserId]\n if (session) sessions.push(session)\n }\n\n return sessions\n}\n\n/**\n * Get the current stored store auth session for a store.\n *\n * @param store - The store FQDN or URL to load a store-auth session for.\n * @param storage - Optional storage override for tests.\n * @returns The current stored store auth session, or undefined when missing or malformed.\n */\nexport function getCurrentStoredStoreAppSession(\n store: string,\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): StoredStoreAppSession | undefined {\n const storeFqdn = normalizeStoreFqdn(store)\n const bucket = readStoredStoreAppSessionBucket(storeFqdn, storage)\n if (!bucket) return undefined\n\n const session = bucket.sessionsByUserId[bucket.currentUserId]\n if (!session) {\n storage.delete(storeAuthSessionKey(storeFqdn))\n return undefined\n }\n\n return session\n}\n\n/**\n * Persist a store auth session and mark it as current for its store.\n *\n * @param session - The store auth session to persist.\n * @param storage - Optional storage override for tests.\n */\nexport function setStoredStoreAppSession(\n session: StoredStoreAppSession,\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): void {\n const key = storeAuthSessionKey(session.store)\n const existingBucket = readStoredStoreAppSessionBucket(session.store, storage)\n\n const nextBucket: StoredStoreAppSessionBucket = {\n currentUserId: session.userId,\n sessionsByUserId: {\n ...(existingBucket?.sessionsByUserId ?? {}),\n [session.userId]: session,\n },\n }\n\n storage.set(key, nextBucket)\n}\n\n/**\n * Clear stored store auth sessions for a store.\n *\n * @param store - The store FQDN or URL to clear sessions for.\n * @param userIdOrStorage - Optional user ID to clear, or storage override when clearing all users.\n * @param maybeStorage - Optional storage override when clearing one user.\n */\nexport function clearStoredStoreAppSession(\n store: string,\n userIdOrStorage?: string | LocalStorage<StoreAuthSessionSchema>,\n maybeStorage?: LocalStorage<StoreAuthSessionSchema>,\n): void {\n const storeFqdn = normalizeStoreFqdn(store)\n const userId = typeof userIdOrStorage === 'string' ? userIdOrStorage : undefined\n const storage = (typeof userIdOrStorage === 'string' ? maybeStorage : userIdOrStorage) ?? storeAuthSessionStorage()\n\n const key = storeAuthSessionKey(storeFqdn)\n\n if (!userId) {\n storage.delete(key)\n return\n }\n\n const existingBucket = readStoredStoreAppSessionBucket(storeFqdn, storage)\n if (!existingBucket) return\n\n const {[userId]: _removedSession, ...remainingSessions} = existingBucket.sessionsByUserId\n\n const remainingUserIds = Object.keys(remainingSessions)\n if (remainingUserIds.length === 0) {\n storage.delete(key)\n return\n }\n\n storage.set(key, {\n currentUserId: existingBucket.currentUserId === userId ? remainingUserIds[0]! : existingBucket.currentUserId,\n sessionsByUserId: remainingSessions,\n })\n}\n\n/**\n * Load an Admin API session from the local store-auth cache when one is currently usable.\n *\n * @param store - The store FQDN or URL to load a store-auth session for.\n * @param storage - Optional storage override for tests.\n * @returns An Admin session, or undefined when no usable session is cached.\n */\nexport function getStoreAuthAdminSession(\n store: string,\n storage: LocalStorage<StoreAuthSessionSchema> = storeAuthSessionStorage(),\n): AdminSession | undefined {\n const storeFqdn = normalizeStoreFqdn(store)\n const session = getCurrentStoredStoreAppSession(storeFqdn, storage)\n if (!session || isSessionExpired(session)) return undefined\n\n setLastSeenUserId(session.userId)\n\n return {\n token: session.accessToken,\n storeFqdn,\n }\n}\n\n/**\n * Check whether a stored store auth session is expired, including the refresh margin.\n *\n * @param session - The stored store auth session.\n * @returns True when the session is expired or has an invalid expiry timestamp.\n */\nexport function isSessionExpired(session: StoredStoreAppSession): boolean {\n if (!session.expiresAt) return false\n\n const expiresAtMs = new Date(session.expiresAt).getTime()\n if (Number.isNaN(expiresAtMs)) return true\n\n return expiresAtMs - EXPIRY_MARGIN_MS < Date.now()\n}\n"]}
@@ -115,12 +115,25 @@ export declare function terminalSupportsPrompting(): boolean;
115
115
  * @returns True if the current environment is a CI environment.
116
116
  */
117
117
  export declare function isCI(): boolean;
118
+ interface WslDetectionOverrides {
119
+ platform?: NodeJS.Platform;
120
+ kernelRelease?: string;
121
+ procVersion?: string;
122
+ insideContainer?: boolean;
123
+ }
118
124
  /**
119
125
  * Check if the current environment is a WSL environment.
120
126
  *
127
+ * @param overrides - Detection inputs, read from the system when not provided. Intended for tests.
121
128
  * @returns True if the current environment is a WSL environment.
122
129
  */
123
- export declare function isWsl(): Promise<boolean>;
130
+ export declare function isWsl(overrides?: WslDetectionOverrides): Promise<boolean>;
131
+ /**
132
+ * Check if the current process is running inside a container.
133
+ *
134
+ * @returns True if the current process is running inside a container.
135
+ */
136
+ export declare function isInsideContainer(): boolean;
124
137
  /**
125
138
  * Check if stdin has piped data available.
126
139
  * This distinguishes between actual piped input (e.g., `echo "query" | cmd`)
@@ -140,3 +153,4 @@ export declare function isStdinPiped(): boolean;
140
153
  * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.
141
154
  */
142
155
  export declare function readStdinString(): Promise<string | undefined>;
156
+ export {};
@@ -10,7 +10,8 @@ import { execa } from 'execa';
10
10
  import supportsHyperlinks from 'supports-hyperlinks';
11
11
  import which from 'which';
12
12
  import { delimiter } from 'pathe';
13
- import { fstatSync } from 'fs';
13
+ import { fstatSync, existsSync, readFileSync } from 'fs';
14
+ import { release } from 'os';
14
15
  import { setTimeout } from 'timers/promises';
15
16
  /**
16
17
  * The maximum size of data that can be read from stdin in bytes.
@@ -223,11 +224,12 @@ function buildExec(command, args, options, execaOptions) {
223
224
  }
224
225
  const executionCwd = options?.cwd ?? cwd();
225
226
  checkCommandSafety(command, { cwd: executionCwd });
227
+ const backgroundStdio = options?.input === undefined ? 'ignore' : ['pipe', 'ignore', 'ignore'];
226
228
  const commandProcess = execa(command, args, {
227
229
  env,
228
230
  cwd: executionCwd,
229
231
  input: options?.input,
230
- stdio: options?.background ? 'ignore' : options?.stdio,
232
+ stdio: options?.background ? backgroundStdio : options?.stdio,
231
233
  stdin: options?.stdin,
232
234
  stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,
233
235
  stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,
@@ -296,11 +298,45 @@ export function isCI() {
296
298
  /**
297
299
  * Check if the current environment is a WSL environment.
298
300
  *
301
+ * @param overrides - Detection inputs, read from the system when not provided. Intended for tests.
299
302
  * @returns True if the current environment is a WSL environment.
300
303
  */
301
- export async function isWsl() {
302
- const wsl = await import('is-wsl');
303
- return wsl.default;
304
+ // Mirrors https://github.com/sindresorhus/is-wsl: WSL reports "microsoft" in the kernel
305
+ // release, but containers running inside WSL shouldn't count.
306
+ export async function isWsl(overrides = {}) {
307
+ const platform = overrides.platform ?? process.platform;
308
+ if (platform !== 'linux')
309
+ return false;
310
+ const insideContainer = () => overrides.insideContainer ?? isInsideContainer();
311
+ if ((overrides.kernelRelease ?? release()).toLowerCase().includes('microsoft')) {
312
+ return !insideContainer();
313
+ }
314
+ try {
315
+ const procVersion = overrides.procVersion ?? readFileSync('/proc/version', 'utf8');
316
+ return procVersion.toLowerCase().includes('microsoft') ? !insideContainer() : false;
317
+ // eslint-disable-next-line no-catch-all/no-catch-all
318
+ }
319
+ catch {
320
+ return false;
321
+ }
322
+ }
323
+ // Mirrors the is-inside-container and is-docker packages: Podman creates /run/.containerenv,
324
+ // Docker creates /.dockerenv or mentions "docker" in the process cgroup.
325
+ /**
326
+ * Check if the current process is running inside a container.
327
+ *
328
+ * @returns True if the current process is running inside a container.
329
+ */
330
+ export function isInsideContainer() {
331
+ if (existsSync('/run/.containerenv') || existsSync('/.dockerenv'))
332
+ return true;
333
+ try {
334
+ return readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
335
+ // eslint-disable-next-line no-catch-all/no-catch-all
336
+ }
337
+ catch {
338
+ return false;
339
+ }
304
340
  }
305
341
  /**
306
342
  * Check if stdin has piped data available.
@@ -312,7 +348,7 @@ export async function isWsl() {
312
348
  export function isStdinPiped() {
313
349
  try {
314
350
  const stats = fstatSync(0);
315
- return stats.isFIFO() || stats.isFile();
351
+ return stats.isFIFO() || stats.isFile() || stats.isSocket();
316
352
  // eslint-disable-next-line no-catch-all/no-catch-all
317
353
  }
318
354
  catch {
@@ -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 {isCloudEnvironment} from './context/local.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 {setTimeout} from 'timers/promises'\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 if (isCloudEnvironment()) return false\n\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 await setTimeout(1000 * seconds)\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"]}
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 {isCloudEnvironment} from './context/local.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync, existsSync, readFileSync} from 'fs'\nimport {release} from 'os'\nimport {setTimeout} from 'timers/promises'\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 if (isCloudEnvironment()) return false\n\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 backgroundStdio = options?.input === undefined ? 'ignore' : (['pipe', 'ignore', 'ignore'] as const)\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? backgroundStdio : 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 await setTimeout(1000 * seconds)\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\ninterface WslDetectionOverrides {\n platform?: NodeJS.Platform\n kernelRelease?: string\n procVersion?: string\n insideContainer?: boolean\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @param overrides - Detection inputs, read from the system when not provided. Intended for tests.\n * @returns True if the current environment is a WSL environment.\n */\n// Mirrors https://github.com/sindresorhus/is-wsl: WSL reports \"microsoft\" in the kernel\n// release, but containers running inside WSL shouldn't count.\nexport async function isWsl(overrides: WslDetectionOverrides = {}): Promise<boolean> {\n const platform = overrides.platform ?? process.platform\n if (platform !== 'linux') return false\n const insideContainer = () => overrides.insideContainer ?? isInsideContainer()\n if ((overrides.kernelRelease ?? release()).toLowerCase().includes('microsoft')) {\n return !insideContainer()\n }\n try {\n const procVersion = overrides.procVersion ?? readFileSync('/proc/version', 'utf8')\n return procVersion.toLowerCase().includes('microsoft') ? !insideContainer() : false\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n// Mirrors the is-inside-container and is-docker packages: Podman creates /run/.containerenv,\n// Docker creates /.dockerenv or mentions \"docker\" in the process cgroup.\n/**\n * Check if the current process is running inside a container.\n *\n * @returns True if the current process is running inside a container.\n */\nexport function isInsideContainer(): boolean {\n if (existsSync('/run/.containerenv') || existsSync('/.dockerenv')) return true\n try {\n return readFileSync('/proc/self/cgroup', 'utf8').includes('docker')\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\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() || stats.isSocket()\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,9 +2,9 @@ import { LocalStorage } from '../local-storage.js';
2
2
  import { outputDebug, outputContent } from '../output.js';
3
3
  let _hostThemeLocalStorageInstance;
4
4
  export function hostThemeLocalStorage() {
5
- _hostThemeLocalStorageInstance ?? (_hostThemeLocalStorageInstance = new LocalStorage({
5
+ _hostThemeLocalStorageInstance ??= new LocalStorage({
6
6
  projectName: 'shopify-cli-host-theme-conf',
7
- }));
7
+ });
8
8
  return _hostThemeLocalStorageInstance;
9
9
  }
10
10
  export function getHostTheme(storeFqdn) {
@@ -1 +1 @@
1
- {"version":3,"file":"conf.js","sourceRoot":"","sources":["../../../../src/public/node/themes/conf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,cAAc,CAAA;AAOvD,IAAI,8BAAqF,CAAA;AAEzF,MAAM,UAAU,qBAAqB;IACnC,8BAA8B,KAA9B,8BAA8B,GAAK,IAAI,YAAY,CAA8B;QAC/E,WAAW,EAAE,6BAA6B;KAC3C,CAAC,EAAA;IACF,OAAO,8BAA8B,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAoB;IAC/C,WAAW,CAAC,aAAa,CAAA,uBAAuB,CAAC,CAAA;IACjD,OAAO,qBAAqB,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAoB,EAAE,OAAoB;IACrE,WAAW,CAAC,aAAa,CAAA,uBAAuB,CAAC,CAAA;IACjD,qBAAqB,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAoB;IAClD,WAAW,CAAC,aAAa,CAAA,wBAAwB,CAAC,CAAA;IAClD,qBAAqB,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAC3C,CAAC","sourcesContent":["import {LocalStorage} from '../local-storage.js'\nimport {AdminSession} from '../session.js'\nimport {outputDebug, outputContent} from '../output.js'\n\ntype HostThemeId = string\ntype StoreFqdn = AdminSession['storeFqdn']\n\ntype HostThemeLocalStorageSchema = Record<StoreFqdn, HostThemeId>\n\nlet _hostThemeLocalStorageInstance: LocalStorage<HostThemeLocalStorageSchema> | undefined\n\nexport function hostThemeLocalStorage(): LocalStorage<HostThemeLocalStorageSchema> {\n _hostThemeLocalStorageInstance ??= new LocalStorage<HostThemeLocalStorageSchema>({\n projectName: 'shopify-cli-host-theme-conf',\n })\n return _hostThemeLocalStorageInstance\n}\n\nexport function getHostTheme(storeFqdn: StoreFqdn): string | undefined {\n outputDebug(outputContent`Getting host theme...`)\n return hostThemeLocalStorage().get(storeFqdn)\n}\n\nexport function setHostTheme(storeFqdn: StoreFqdn, themeId: HostThemeId): void {\n outputDebug(outputContent`Setting host theme...`)\n hostThemeLocalStorage().set(storeFqdn, themeId)\n}\n\nexport function removeHostTheme(storeFqdn: StoreFqdn): void {\n outputDebug(outputContent`Removing host theme...`)\n hostThemeLocalStorage().delete(storeFqdn)\n}\n"]}
1
+ {"version":3,"file":"conf.js","sourceRoot":"","sources":["../../../../src/public/node/themes/conf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,cAAc,CAAA;AAOvD,IAAI,8BAAqF,CAAA;AAEzF,MAAM,UAAU,qBAAqB;IACnC,8BAA8B,KAAK,IAAI,YAAY,CAA8B;QAC/E,WAAW,EAAE,6BAA6B;KAC3C,CAAC,CAAA;IACF,OAAO,8BAA8B,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAoB;IAC/C,WAAW,CAAC,aAAa,CAAA,uBAAuB,CAAC,CAAA;IACjD,OAAO,qBAAqB,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAoB,EAAE,OAAoB;IACrE,WAAW,CAAC,aAAa,CAAA,uBAAuB,CAAC,CAAA;IACjD,qBAAqB,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAoB;IAClD,WAAW,CAAC,aAAa,CAAA,wBAAwB,CAAC,CAAA;IAClD,qBAAqB,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAC3C,CAAC","sourcesContent":["import {LocalStorage} from '../local-storage.js'\nimport {AdminSession} from '../session.js'\nimport {outputDebug, outputContent} from '../output.js'\n\ntype HostThemeId = string\ntype StoreFqdn = AdminSession['storeFqdn']\n\ntype HostThemeLocalStorageSchema = Record<StoreFqdn, HostThemeId>\n\nlet _hostThemeLocalStorageInstance: LocalStorage<HostThemeLocalStorageSchema> | undefined\n\nexport function hostThemeLocalStorage(): LocalStorage<HostThemeLocalStorageSchema> {\n _hostThemeLocalStorageInstance ??= new LocalStorage<HostThemeLocalStorageSchema>({\n projectName: 'shopify-cli-host-theme-conf',\n })\n return _hostThemeLocalStorageInstance\n}\n\nexport function getHostTheme(storeFqdn: StoreFqdn): string | undefined {\n outputDebug(outputContent`Getting host theme...`)\n return hostThemeLocalStorage().get(storeFqdn)\n}\n\nexport function setHostTheme(storeFqdn: StoreFqdn, themeId: HostThemeId): void {\n outputDebug(outputContent`Setting host theme...`)\n hostThemeLocalStorage().set(storeFqdn, themeId)\n}\n\nexport function removeHostTheme(storeFqdn: StoreFqdn): void {\n outputDebug(outputContent`Removing host theme...`)\n hostThemeLocalStorage().delete(storeFqdn)\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  export function buildTheme(themeJson) {
2
2
  if (!themeJson)
3
3
  return;
4
- themeJson.processing ?? (themeJson.processing = false);
5
- themeJson.createdAtRuntime ?? (themeJson.createdAtRuntime = false);
4
+ themeJson.processing ??= false;
5
+ themeJson.createdAtRuntime ??= false;
6
6
  const { id, name, role, processing, createdAtRuntime } = themeJson;
7
7
  return {
8
8
  id,
@@ -1 +1 @@
1
- {"version":3,"file":"factories.js","sourceRoot":"","sources":["../../../../src/public/node/themes/factories.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,UAAU,CAAC,SAA+B;IACxD,IAAI,CAAC,SAAS;QAAE,OAAM;IAEtB,SAAS,CAAC,UAAU,KAApB,SAAS,CAAC,UAAU,GAAK,KAAK,EAAA;IAC9B,SAAS,CAAC,gBAAgB,KAA1B,SAAS,CAAC,gBAAgB,GAAK,KAAK,EAAA;IAEpC,MAAM,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAC,GAAG,SAAS,CAAA;IAEhE,OAAO;QACL,EAAE;QACF,IAAI;QACJ,UAAU;QACV,gBAAgB;QAChB,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;KACtC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,IAAI,CAAC,KAAK;QAAE,OAAM;IAElB,MAAM,EAAC,GAAG,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAA;IAC7B,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAC,CAAA;AACxB,CAAC;AAID,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,IAAI,CAAC,KAAK;QAAE,OAAM;IAElB,MAAM,EAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAC,GAAG,KAAK,CAAA;IAChD,gGAAgG;IAChG,kJAAkJ;IAClJ,MAAM,KAAK,GAAG,EAAC,IAAI,EAAE,CAAC,KAAK,IAAI,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAA;IAC3E,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAC,CAAA;AAClD,CAAC","sourcesContent":["import {Checksum, Theme, ThemeAsset} from './types.js'\n\ninterface RemoteThemeResponse {\n id: number\n name: string\n role: string\n createdAtRuntime?: boolean\n processing?: boolean\n}\n\ninterface RemoteAssetResponse {\n key: string\n checksum: string\n attachment: string | undefined\n // value is an empty string ('') when the file is empty\n value: string\n}\n\nexport interface RemoteBulkUploadResponse {\n body: {asset?: RemoteAssetResponse; errors?: {asset: string[]}}\n code: number\n}\n\nexport function buildTheme(themeJson?: RemoteThemeResponse): Theme | undefined {\n if (!themeJson) return\n\n themeJson.processing ??= false\n themeJson.createdAtRuntime ??= false\n\n const {id, name, role, processing, createdAtRuntime} = themeJson\n\n return {\n id,\n name,\n processing,\n createdAtRuntime,\n role: role === 'main' ? 'live' : role,\n }\n}\n\nexport function buildChecksum(asset?: RemoteAssetResponse): Checksum | undefined {\n if (!asset) return\n\n const {key, checksum} = asset\n return {key, checksum}\n}\n\nexport function buildThemeAsset(asset: undefined): undefined\nexport function buildThemeAsset(asset: RemoteAssetResponse): ThemeAsset\nexport function buildThemeAsset(asset?: RemoteAssetResponse): ThemeAsset | undefined {\n if (!asset) return\n\n const {key, checksum, attachment, value} = asset\n // Note: for attachments, this is the size of the base64 string, not the real length of the file\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty string value should fall through to attachment for binary assets\n const stats = {size: (value || attachment || '').length, mtime: Date.now()}\n return {key, checksum, attachment, value, stats}\n}\n"]}
1
+ {"version":3,"file":"factories.js","sourceRoot":"","sources":["../../../../src/public/node/themes/factories.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,UAAU,CAAC,SAA+B;IACxD,IAAI,CAAC,SAAS;QAAE,OAAM;IAEtB,SAAS,CAAC,UAAU,KAAK,KAAK,CAAA;IAC9B,SAAS,CAAC,gBAAgB,KAAK,KAAK,CAAA;IAEpC,MAAM,EAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAC,GAAG,SAAS,CAAA;IAEhE,OAAO;QACL,EAAE;QACF,IAAI;QACJ,UAAU;QACV,gBAAgB;QAChB,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;KACtC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,IAAI,CAAC,KAAK;QAAE,OAAM;IAElB,MAAM,EAAC,GAAG,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAA;IAC7B,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAC,CAAA;AACxB,CAAC;AAID,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,IAAI,CAAC,KAAK;QAAE,OAAM;IAElB,MAAM,EAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAC,GAAG,KAAK,CAAA;IAChD,gGAAgG;IAChG,kJAAkJ;IAClJ,MAAM,KAAK,GAAG,EAAC,IAAI,EAAE,CAAC,KAAK,IAAI,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAA;IAC3E,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAC,CAAA;AAClD,CAAC","sourcesContent":["import {Checksum, Theme, ThemeAsset} from './types.js'\n\ninterface RemoteThemeResponse {\n id: number\n name: string\n role: string\n createdAtRuntime?: boolean\n processing?: boolean\n}\n\ninterface RemoteAssetResponse {\n key: string\n checksum: string\n attachment: string | undefined\n // value is an empty string ('') when the file is empty\n value: string\n}\n\nexport interface RemoteBulkUploadResponse {\n body: {asset?: RemoteAssetResponse; errors?: {asset: string[]}}\n code: number\n}\n\nexport function buildTheme(themeJson?: RemoteThemeResponse): Theme | undefined {\n if (!themeJson) return\n\n themeJson.processing ??= false\n themeJson.createdAtRuntime ??= false\n\n const {id, name, role, processing, createdAtRuntime} = themeJson\n\n return {\n id,\n name,\n processing,\n createdAtRuntime,\n role: role === 'main' ? 'live' : role,\n }\n}\n\nexport function buildChecksum(asset?: RemoteAssetResponse): Checksum | undefined {\n if (!asset) return\n\n const {key, checksum} = asset\n return {key, checksum}\n}\n\nexport function buildThemeAsset(asset: undefined): undefined\nexport function buildThemeAsset(asset: RemoteAssetResponse): ThemeAsset\nexport function buildThemeAsset(asset?: RemoteAssetResponse): ThemeAsset | undefined {\n if (!asset) return\n\n const {key, checksum, attachment, value} = asset\n // Note: for attachments, this is the size of the base64 string, not the real length of the file\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty string value should fall through to attachment for binary assets\n const stats = {size: (value || attachment || '').length, mtime: Date.now()}\n return {key, checksum, attachment, value, stats}\n}\n"]}
@@ -3,6 +3,8 @@ import { DEVELOPMENT_THEME_ROLE } from './utils.js';
3
3
  import { generateThemeName } from '../../../private/node/themes/generate-theme-name.js';
4
4
  import { BugError } from '../error.js';
5
5
  export class ThemeManager {
6
+ adminSession;
7
+ themeId;
6
8
  constructor(adminSession) {
7
9
  this.adminSession = adminSession;
8
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"theme-manager.js","sourceRoot":"","sources":["../../../../src/public/node/themes/theme-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,0BAA0B,EAAE,WAAW,EAAC,MAAM,UAAU,CAAA;AAE5E,OAAO,EAAC,sBAAsB,EAAO,MAAM,YAAY,CAAA;AACvD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qDAAqD,CAAA;AAErF,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AAEpC,MAAM,OAAgB,YAAY;IAMhC,YAAsB,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAEpD,KAAK,CAAC,YAAY,CAAC,IAAa,EAAE,IAAW;QAC3C,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;QACpC,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QACvC,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAa,EAAE,IAAW;QACpC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3B,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GACT,IAAI,IAAI,IAAI,KAAK,sBAAsB;YACrC,CAAC,CAAC,MAAM,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC;YAC3D,CAAC,CAAC,MAAM,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAQ,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;QAEtE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,WAAW,EAAE,CAAA;QACpB,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,iBAAiB,CAAC,OAAe;QAC/B,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAgB,EAAE,SAAkB;QAC/C,MAAM,IAAI,GAAG,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzD,MAAM,IAAI,GAAG,SAAS,IAAI,sBAAsB,CAAA;QAChD,MAAM,KAAK,GAAG,MAAM,WAAW,CAC7B;YACE,IAAI;YACJ,IAAI;SACL,EACD,IAAI,CAAC,YAAY,CAClB,CAAA;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,QAAQ,CAAC,qCAAqC,IAAI,eAAe,IAAI,GAAG,CAAC,CAAA;QACrF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;CACF","sourcesContent":["import {fetchTheme, findDevelopmentThemeByName, themeCreate} from './api.js'\nimport {Theme} from './types.js'\nimport {DEVELOPMENT_THEME_ROLE, Role} from './utils.js'\nimport {generateThemeName} from '../../../private/node/themes/generate-theme-name.js'\nimport {AdminSession} from '../session.js'\nimport {BugError} from '../error.js'\n\nexport abstract class ThemeManager {\n protected themeId: string | undefined\n protected abstract setTheme(themeId: string): void\n protected abstract removeTheme(): void\n protected abstract context: string\n\n constructor(protected adminSession: AdminSession) {}\n\n async findOrCreate(name?: string, role?: Role): Promise<Theme> {\n let theme = await this.fetch(name, role)\n if (theme) {\n this.setTheme(theme.id.toString())\n } else {\n theme = await this.create(role, name)\n }\n return theme\n }\n\n async fetch(name?: string, role?: Role) {\n if (!this.themeId && !name) {\n return\n }\n\n const theme =\n name && role === DEVELOPMENT_THEME_ROLE\n ? await findDevelopmentThemeByName(name, this.adminSession)\n : await fetchTheme(parseInt(this.themeId!, 10), this.adminSession)\n\n if (!theme) {\n this.removeTheme()\n }\n return theme\n }\n\n generateThemeName(context: string) {\n return generateThemeName(context)\n }\n\n async create(themeRole?: Role, themeName?: string) {\n const name = themeName ?? generateThemeName(this.context)\n const role = themeRole ?? DEVELOPMENT_THEME_ROLE\n const theme = await themeCreate(\n {\n name,\n role,\n },\n this.adminSession,\n )\n if (!theme) {\n throw new BugError(`Could not create theme with name \"${name}\" and role \"${role}\"`)\n }\n this.setTheme(theme.id.toString())\n return theme\n }\n}\n"]}
1
+ {"version":3,"file":"theme-manager.js","sourceRoot":"","sources":["../../../../src/public/node/themes/theme-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,0BAA0B,EAAE,WAAW,EAAC,MAAM,UAAU,CAAA;AAE5E,OAAO,EAAC,sBAAsB,EAAO,MAAM,YAAY,CAAA;AACvD,OAAO,EAAC,iBAAiB,EAAC,MAAM,qDAAqD,CAAA;AAErF,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AAEpC,MAAM,OAAgB,YAAY;IAMV;IALZ,OAAO,CAAoB;IAKrC,YAAsB,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAEpD,KAAK,CAAC,YAAY,CAAC,IAAa,EAAE,IAAW;QAC3C,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;QACpC,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QACvC,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAa,EAAE,IAAW;QACpC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3B,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GACT,IAAI,IAAI,IAAI,KAAK,sBAAsB;YACrC,CAAC,CAAC,MAAM,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC;YAC3D,CAAC,CAAC,MAAM,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAQ,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;QAEtE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,WAAW,EAAE,CAAA;QACpB,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,iBAAiB,CAAC,OAAe;QAC/B,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAgB,EAAE,SAAkB;QAC/C,MAAM,IAAI,GAAG,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzD,MAAM,IAAI,GAAG,SAAS,IAAI,sBAAsB,CAAA;QAChD,MAAM,KAAK,GAAG,MAAM,WAAW,CAC7B;YACE,IAAI;YACJ,IAAI;SACL,EACD,IAAI,CAAC,YAAY,CAClB,CAAA;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,QAAQ,CAAC,qCAAqC,IAAI,eAAe,IAAI,GAAG,CAAC,CAAA;QACrF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;CACF","sourcesContent":["import {fetchTheme, findDevelopmentThemeByName, themeCreate} from './api.js'\nimport {Theme} from './types.js'\nimport {DEVELOPMENT_THEME_ROLE, Role} from './utils.js'\nimport {generateThemeName} from '../../../private/node/themes/generate-theme-name.js'\nimport {AdminSession} from '../session.js'\nimport {BugError} from '../error.js'\n\nexport abstract class ThemeManager {\n protected themeId: string | undefined\n protected abstract setTheme(themeId: string): void\n protected abstract removeTheme(): void\n protected abstract context: string\n\n constructor(protected adminSession: AdminSession) {}\n\n async findOrCreate(name?: string, role?: Role): Promise<Theme> {\n let theme = await this.fetch(name, role)\n if (theme) {\n this.setTheme(theme.id.toString())\n } else {\n theme = await this.create(role, name)\n }\n return theme\n }\n\n async fetch(name?: string, role?: Role) {\n if (!this.themeId && !name) {\n return\n }\n\n const theme =\n name && role === DEVELOPMENT_THEME_ROLE\n ? await findDevelopmentThemeByName(name, this.adminSession)\n : await fetchTheme(parseInt(this.themeId!, 10), this.adminSession)\n\n if (!theme) {\n this.removeTheme()\n }\n return theme\n }\n\n generateThemeName(context: string) {\n return generateThemeName(context)\n }\n\n async create(themeRole?: Role, themeName?: string) {\n const name = themeName ?? generateThemeName(this.context)\n const role = themeRole ?? DEVELOPMENT_THEME_ROLE\n const theme = await themeCreate(\n {\n name,\n role,\n },\n this.adminSession,\n )\n if (!theme) {\n throw new BugError(`Could not create theme with name \"${name}\" and role \"${role}\"`)\n }\n this.setTheme(theme.id.toString())\n return theme\n }\n}\n"]}
@@ -6,18 +6,18 @@ export function themePreviewUrl(theme, session) {
6
6
  return `https://${store}?preview_theme_id=${theme.id}`;
7
7
  }
8
8
  export function themeEditorUrl(theme, session) {
9
- const store = session.storeFqdn;
10
- return `https://${store}/admin/themes/${theme.id}/editor`;
9
+ return adminUrl(session.storeFqdn, `/themes/${theme.id}/editor`);
11
10
  }
12
11
  export function codeEditorUrl(theme, session) {
13
- const store = session.storeFqdn;
14
- return `https://${store}/admin/themes/${theme.id}`;
12
+ return adminUrl(session.storeFqdn, `/themes/${theme.id}`);
15
13
  }
16
14
  export function storeAdminUrl(session) {
17
- const store = session.storeFqdn;
18
- return `https://${store}/admin`;
15
+ return adminUrl(session.storeFqdn);
19
16
  }
20
17
  export function storePasswordPage(store) {
21
- return `https://${store}/admin/online_store/preferences`;
18
+ return adminUrl(store, '/online_store/preferences');
19
+ }
20
+ function adminUrl(store, path = '') {
21
+ return `https://${store}/admin${path}`;
22
22
  }
23
23
  //# sourceMappingURL=urls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../../src/public/node/themes/urls.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,eAAe,CAAC,KAAY,EAAE,OAAqB;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,WAAW,KAAK,EAAE,CAAA;IAC3B,CAAC;IAED,OAAO,WAAW,KAAK,qBAAqB,KAAK,CAAC,EAAE,EAAE,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,OAAqB;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,OAAO,WAAW,KAAK,iBAAiB,KAAK,CAAC,EAAE,SAAS,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,OAAqB;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,OAAO,WAAW,KAAK,iBAAiB,KAAK,CAAC,EAAE,EAAE,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAqB;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,OAAO,WAAW,KAAK,QAAQ,CAAA;AACjC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgC;IAChE,OAAO,WAAW,KAAK,iCAAiC,CAAA;AAC1D,CAAC","sourcesContent":["import {Theme} from './types.js'\nimport {AdminSession} from '../session.js'\n\nexport function themePreviewUrl(theme: Theme, session: AdminSession) {\n const store = session.storeFqdn\n if (theme.role === 'live') {\n return `https://${store}`\n }\n\n return `https://${store}?preview_theme_id=${theme.id}`\n}\n\nexport function themeEditorUrl(theme: Theme, session: AdminSession) {\n const store = session.storeFqdn\n return `https://${store}/admin/themes/${theme.id}/editor`\n}\n\nexport function codeEditorUrl(theme: Theme, session: AdminSession) {\n const store = session.storeFqdn\n return `https://${store}/admin/themes/${theme.id}`\n}\n\nexport function storeAdminUrl(session: AdminSession) {\n const store = session.storeFqdn\n return `https://${store}/admin`\n}\n\nexport function storePasswordPage(store: AdminSession['storeFqdn']) {\n return `https://${store}/admin/online_store/preferences`\n}\n"]}
1
+ {"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../../src/public/node/themes/urls.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,eAAe,CAAC,KAAY,EAAE,OAAqB;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,OAAO,WAAW,KAAK,EAAE,CAAA;IAC3B,CAAC;IAED,OAAO,WAAW,KAAK,qBAAqB,KAAK,CAAC,EAAE,EAAE,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,OAAqB;IAChE,OAAO,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,KAAK,CAAC,EAAE,SAAS,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,OAAqB;IAC/D,OAAO,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,KAAK,CAAC,EAAE,EAAE,CAAC,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAqB;IACjD,OAAO,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgC;IAChE,OAAO,QAAQ,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAA;AACrD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa,EAAE,IAAI,GAAG,EAAE;IACxC,OAAO,WAAW,KAAK,SAAS,IAAI,EAAE,CAAA;AACxC,CAAC","sourcesContent":["import {Theme} from './types.js'\nimport {AdminSession} from '../session.js'\n\nexport function themePreviewUrl(theme: Theme, session: AdminSession) {\n const store = session.storeFqdn\n if (theme.role === 'live') {\n return `https://${store}`\n }\n\n return `https://${store}?preview_theme_id=${theme.id}`\n}\n\nexport function themeEditorUrl(theme: Theme, session: AdminSession) {\n return adminUrl(session.storeFqdn, `/themes/${theme.id}/editor`)\n}\n\nexport function codeEditorUrl(theme: Theme, session: AdminSession) {\n return adminUrl(session.storeFqdn, `/themes/${theme.id}`)\n}\n\nexport function storeAdminUrl(session: AdminSession) {\n return adminUrl(session.storeFqdn)\n}\n\nexport function storePasswordPage(store: AdminSession['storeFqdn']) {\n return adminUrl(store, '/online_store/preferences')\n}\n\nfunction adminUrl(store: string, path = ''): string {\n return `https://${store}/admin${path}`\n}\n"]}