@shopify/cli-kit 3.19.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/api/graphql/all_app_extension_registrations.d.ts +6 -0
  3. package/dist/api/graphql/all_app_extension_registrations.js +6 -0
  4. package/dist/api/graphql/all_app_extension_registrations.js.map +1 -1
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.js +5 -0
  7. package/dist/cli.js.map +1 -1
  8. package/dist/constants.d.ts +2 -0
  9. package/dist/constants.js +2 -0
  10. package/dist/constants.js.map +1 -1
  11. package/dist/environment/local.d.ts +2 -0
  12. package/dist/environment/local.js +6 -0
  13. package/dist/environment/local.js.map +1 -1
  14. package/dist/error.d.ts +13 -4
  15. package/dist/error.js +20 -2
  16. package/dist/error.js.map +1 -1
  17. package/dist/node/base-command.d.ts +11 -5
  18. package/dist/node/base-command.js +126 -3
  19. package/dist/node/base-command.js.map +1 -1
  20. package/dist/node/cli.js +3 -1
  21. package/dist/node/cli.js.map +1 -1
  22. package/dist/node/ruby.d.ts +3 -1
  23. package/dist/node/ruby.js +2 -1
  24. package/dist/node/ruby.js.map +1 -1
  25. package/dist/private/node/ui/components/Link.d.ts +1 -1
  26. package/dist/private/node/ui/components/Link.js +1 -1
  27. package/dist/private/node/ui/components/Link.js.map +1 -1
  28. package/dist/private/node/ui/components/TokenizedText.d.ts +1 -1
  29. package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
  30. package/dist/public/node/presets.d.ts +3 -1
  31. package/dist/public/node/presets.js +3 -3
  32. package/dist/public/node/presets.js.map +1 -1
  33. package/dist/session.d.ts +3 -3
  34. package/dist/session.js +6 -6
  35. package/dist/session.js.map +1 -1
  36. package/dist/testing/fixtures/render-concurrent.js +1 -3
  37. package/dist/testing/fixtures/render-concurrent.js.map +1 -1
  38. package/dist/testing/ui.js +5 -3
  39. package/dist/testing/ui.js.map +1 -1
  40. package/dist/tsconfig.tsbuildinfo +1 -1
  41. package/package.json +5 -1
@@ -1,11 +1,13 @@
1
1
  /// <reference types="node" />
2
2
  import { AdminSession } from '../session.js';
3
+ import { AbortSignal } from 'abort-controller';
3
4
  import { Writable } from 'node:stream';
4
5
  interface ExecCLI2Options {
5
6
  adminSession?: AdminSession;
6
7
  storefrontToken?: string;
7
8
  token?: string;
8
9
  directory?: string;
10
+ signal?: AbortSignal;
9
11
  }
10
12
  /**
11
13
  * Execute CLI 2.0 commands.
@@ -15,7 +17,7 @@ interface ExecCLI2Options {
15
17
  * @param args - List of argumets to execute. (ex: ['theme', 'pull'])
16
18
  * @param options - Options to customize the execution of cli2.
17
19
  */
18
- export declare function execCLI2(args: string[], { adminSession, storefrontToken, token, directory }?: ExecCLI2Options): Promise<void>;
20
+ export declare function execCLI2(args: string[], { adminSession, storefrontToken, token, directory, signal }?: ExecCLI2Options): Promise<void>;
19
21
  interface ExecThemeCheckCLIOptions {
20
22
  /** A list of directories in which theme-check should run */
21
23
  directories: string[];
package/dist/node/ruby.js CHANGED
@@ -19,7 +19,7 @@ const MinRubyVersion = '2.7.5';
19
19
  * @param args - List of argumets to execute. (ex: ['theme', 'pull'])
20
20
  * @param options - Options to customize the execution of cli2.
21
21
  */
22
- export async function execCLI2(args, { adminSession, storefrontToken, token, directory } = {}) {
22
+ export async function execCLI2(args, { adminSession, storefrontToken, token, directory, signal } = {}) {
23
23
  await installCLIDependencies();
24
24
  const env = {
25
25
  ...process.env,
@@ -38,6 +38,7 @@ export async function execCLI2(args, { adminSession, storefrontToken, token, dir
38
38
  stdio: 'inherit',
39
39
  cwd: directory ?? process.cwd(),
40
40
  env,
41
+ signal,
41
42
  });
42
43
  }
43
44
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../src/node/ruby.ts"],"names":[],"mappings":"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","sourcesContent":["import * as file from '../file.js'\nimport * as ui from '../ui.js'\nimport * as system from '../system.js'\nimport {Abort, AbortSilent} from '../error.js'\nimport {glob, join} from '../path.js'\nimport constants from '../constants.js'\nimport {coerce} from '../semver.js'\nimport {AdminSession} from '../session.js'\nimport {content, token} from '../output.js'\nimport {Writable} from 'node:stream'\n\nconst RubyCLIVersion = '2.29.0'\nconst ThemeCheckVersion = '1.10.3'\nconst MinBundlerVersion = '2.3.8'\nconst MinRubyVersion = '2.7.5'\n\ninterface ExecCLI2Options {\n // Contains token and store to pass to CLI 2.0, which will be set as environment variables\n adminSession?: AdminSession\n // Contains token for storefront access to pass to CLI 2.0 as environment variable\n storefrontToken?: string\n // Contains token for partners access to pass to CLI 2.0 as environment variable\n token?: string\n // Directory in which to execute the command. Otherwise the current directory will be used.\n directory?: string\n}\n/**\n * Execute CLI 2.0 commands.\n * Installs a version of RubyCLI as a vendor dependency in a hidden folder in the system.\n * User must have a valid ruby+bundler environment to run any command.\n *\n * @param args - List of argumets to execute. (ex: ['theme', 'pull'])\n * @param options - Options to customize the execution of cli2.\n */\nexport async function execCLI2(\n args: string[],\n {adminSession, storefrontToken, token, directory}: ExecCLI2Options = {},\n) {\n await installCLIDependencies()\n const env = {\n ...process.env,\n SHOPIFY_CLI_STOREFRONT_RENDERER_AUTH_TOKEN: storefrontToken,\n SHOPIFY_CLI_ADMIN_AUTH_TOKEN: adminSession?.token,\n SHOPIFY_SHOP: adminSession?.storeFqdn,\n SHOPIFY_CLI_AUTH_TOKEN: token,\n SHOPIFY_CLI_RUN_AS_SUBPROCESS: 'true',\n // Bundler uses this Gemfile to understand which gems are available in the\n // environment. We use this to specify our own Gemfile for CLI2, which exists\n // outside the user's project directory.\n BUNDLE_GEMFILE: join(shopifyCLIDirectory(), 'Gemfile'),\n }\n\n try {\n await system.exec(bundleExecutable(), ['exec', 'shopify'].concat(args), {\n stdio: 'inherit',\n cwd: directory ?? process.cwd(),\n env,\n })\n } catch (error) {\n // CLI2 will show it's own errors, we don't need to show an additional CLI3 error\n throw new AbortSilent()\n }\n}\n\ninterface ExecThemeCheckCLIOptions {\n /** A list of directories in which theme-check should run */\n directories: string[]\n /** Arguments to pass to the theme-check CLI */\n args?: string[]\n /** Writable to send standard output content through */\n stdout: Writable\n /** Writable to send standard error content through */\n stderr: Writable\n}\n\n/**\n * A function that installs (if needed) and runs the theme-check CLI.\n * @param options - Options to customize the execution of theme-check.\n * @returns A promise that resolves or rejects depending on the result of the underlying theme-check process.\n */\nexport async function execThemeCheckCLI({\n directories,\n args,\n stdout,\n stderr,\n}: ExecThemeCheckCLIOptions): Promise<void[]> {\n await installThemeCheckCLIDependencies(stdout)\n\n const processes = directories.map(async (directory): Promise<void> => {\n // Check that there are files aside from the extension TOML config file,\n // otherwise theme-check will return a false failure.\n const files = await glob(join(directory, '/**/*'))\n const fileCount = files.filter((file) => !file.match(/\\.toml$/)).length\n if (fileCount === 0) return\n\n const customStderr = new Writable({\n write(chunk, ...args) {\n // For some reason, theme-check reports this initial status line to stderr\n // See https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/diagnostics_engine.rb#L31\n // which leads to https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/io_messenger.rb#L65\n if (chunk.toString('ascii').match(/^Checking/)) {\n stdout.write(chunk, ...args)\n } else {\n stderr.write(chunk, ...args)\n }\n },\n })\n await system.exec(bundleExecutable(), ['exec', 'theme-check'].concat([directory, ...(args || [])]), {\n stdout,\n stderr: customStderr,\n cwd: themeCheckDirectory(),\n })\n })\n return Promise.all(processes)\n}\n\n/**\n * Validate Ruby Enviroment\n * Install Theme Check CLI and its dependencies\n * Shows a loading message if it's the first time installing dependencies\n * or if we are installing a new version of Theme Check CLI\n */\nasync function installThemeCheckCLIDependencies(stdout: Writable) {\n const exists = await file.exists(themeCheckDirectory())\n\n if (!exists) stdout.write('Installing theme dependencies...')\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n await validateRubyEnv()\n await createThemeCheckCLIWorkingDirectory()\n await createThemeCheckGemfile()\n await bundleInstallThemeCheck()\n },\n },\n ],\n {renderer: 'silent'},\n )\n await list.run()\n if (!exists) stdout.write('Installed theme dependencies!')\n}\n\n/**\n * Validate Ruby Enviroment\n * Install RubyCLI and its dependencies\n * Shows a loading spinner if it's the first time installing dependencies\n * or if we are installing a new version of RubyCLI\n */\nasync function installCLIDependencies() {\n const exists = await file.exists(shopifyCLIDirectory())\n const renderer = exists ? 'silent' : 'default'\n\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n const usingLocalCLI2 = Boolean(process.env.SHOPIFY_CLI_2_0_DIRECTORY)\n await validateRubyEnv()\n if (usingLocalCLI2) {\n await bundleInstallLocalShopifyCLI()\n } else {\n await createShopifyCLIWorkingDirectory()\n await createShopifyCLIGemfile()\n await bundleInstallShopifyCLI()\n }\n },\n },\n ],\n {renderer},\n )\n await list.run()\n}\n\nasync function validateRubyEnv() {\n await validateRuby()\n await validateBundler()\n}\n\nasync function validateRuby() {\n let version\n try {\n const stdout = await system.captureOutput(rubyExecutable(), ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Ruby environment not found',\n `Make sure you have Ruby installed on your system. ${\n content`${token.link('Documentation.', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinRubyVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Ruby version ${content`${token.yellow(version.raw)}`.value} is not supported`,\n `Make sure you have at least Ruby ${content`${token.yellow(MinRubyVersion)}`.value} installed on your system. ${\n content`${token.link('Documentation.', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n}\n\nasync function validateBundler() {\n let version\n try {\n const stdout = await system.captureOutput(bundleExecutable(), ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Bundler not found',\n `To install the latest version of Bundler, run ${\n content`${token.genericShellCommand(`${gemExecutable()} install bundler`)}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinBundlerVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Bundler version ${content`${token.yellow(version.raw)}`.value} is not supported`,\n `To update to the latest version of Bundler, run ${\n content`${token.genericShellCommand(`${gemExecutable()} install bundler`)}`.value\n }`,\n )\n }\n}\n\nfunction createShopifyCLIWorkingDirectory() {\n return file.mkdir(shopifyCLIDirectory())\n}\n\nfunction createThemeCheckCLIWorkingDirectory() {\n return file.mkdir(themeCheckDirectory())\n}\n\nasync function createShopifyCLIGemfile() {\n const gemPath = join(shopifyCLIDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'shopify-cli', '${RubyCLIVersion}'`)\n}\n\nasync function createThemeCheckGemfile() {\n const gemPath = join(themeCheckDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'theme-check', '${ThemeCheckVersion}'`)\n}\n\nasync function bundleInstallLocalShopifyCLI() {\n await system.exec(bundleExecutable(), ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallShopifyCLI() {\n await system.exec(bundleExecutable(), ['config', 'set', '--local', 'path', shopifyCLIDirectory()], {\n cwd: shopifyCLIDirectory(),\n })\n await system.exec(bundleExecutable(), ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallThemeCheck() {\n await system.exec(bundleExecutable(), ['config', 'set', '--local', 'path', themeCheckDirectory()], {\n cwd: themeCheckDirectory(),\n })\n await system.exec(bundleExecutable(), ['install'], {cwd: themeCheckDirectory()})\n}\n\nfunction shopifyCLIDirectory() {\n return (\n process.env.SHOPIFY_CLI_2_0_DIRECTORY ??\n join(constants.paths.directories.cache.vendor.path(), 'ruby-cli', RubyCLIVersion)\n )\n}\n\nfunction themeCheckDirectory() {\n return join(constants.paths.directories.cache.vendor.path(), 'theme-check', ThemeCheckVersion)\n}\n\nexport async function version(): Promise<string | undefined> {\n const parseOutput = (version: string) => version.match(/ruby (\\d+\\.\\d+\\.\\d+)/)?.[1]\n return system\n .captureOutput(rubyExecutable(), ['-v'])\n .then(parseOutput)\n .catch(() => undefined)\n}\n\nfunction getRubyBinDir(): string | undefined {\n return process.env.SHOPIFY_RUBY_BINDIR\n}\n\nfunction rubyExecutable(): string {\n const rubyBinDir = getRubyBinDir()\n return rubyBinDir ? join(rubyBinDir, 'ruby') : 'ruby'\n}\n\nfunction bundleExecutable(): string {\n const rubyBinDir = getRubyBinDir()\n return rubyBinDir ? join(rubyBinDir, 'bundle') : 'bundle'\n}\n\nfunction gemExecutable(): string {\n const rubyBinDir = getRubyBinDir()\n return rubyBinDir ? join(rubyBinDir, 'gem') : 'gem'\n}\n"]}
1
+ {"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../src/node/ruby.ts"],"names":[],"mappings":"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","sourcesContent":["import * as file from '../file.js'\nimport * as ui from '../ui.js'\nimport * as system from '../system.js'\nimport {Abort, AbortSilent} from '../error.js'\nimport {glob, join} from '../path.js'\nimport constants from '../constants.js'\nimport {coerce} from '../semver.js'\nimport {AdminSession} from '../session.js'\nimport {content, token} from '../output.js'\nimport {AbortSignal} from 'abort-controller'\nimport {Writable} from 'node:stream'\n\nconst RubyCLIVersion = '2.29.0'\nconst ThemeCheckVersion = '1.10.3'\nconst MinBundlerVersion = '2.3.8'\nconst MinRubyVersion = '2.7.5'\n\ninterface ExecCLI2Options {\n // Contains token and store to pass to CLI 2.0, which will be set as environment variables\n adminSession?: AdminSession\n // Contains token for storefront access to pass to CLI 2.0 as environment variable\n storefrontToken?: string\n // Contains token for partners access to pass to CLI 2.0 as environment variable\n token?: string\n // Directory in which to execute the command. Otherwise the current directory will be used.\n directory?: string\n\n signal?: AbortSignal\n}\n/**\n * Execute CLI 2.0 commands.\n * Installs a version of RubyCLI as a vendor dependency in a hidden folder in the system.\n * User must have a valid ruby+bundler environment to run any command.\n *\n * @param args - List of argumets to execute. (ex: ['theme', 'pull'])\n * @param options - Options to customize the execution of cli2.\n */\nexport async function execCLI2(\n args: string[],\n {adminSession, storefrontToken, token, directory, signal}: ExecCLI2Options = {},\n) {\n await installCLIDependencies()\n const env = {\n ...process.env,\n SHOPIFY_CLI_STOREFRONT_RENDERER_AUTH_TOKEN: storefrontToken,\n SHOPIFY_CLI_ADMIN_AUTH_TOKEN: adminSession?.token,\n SHOPIFY_SHOP: adminSession?.storeFqdn,\n SHOPIFY_CLI_AUTH_TOKEN: token,\n SHOPIFY_CLI_RUN_AS_SUBPROCESS: 'true',\n // Bundler uses this Gemfile to understand which gems are available in the\n // environment. We use this to specify our own Gemfile for CLI2, which exists\n // outside the user's project directory.\n BUNDLE_GEMFILE: join(shopifyCLIDirectory(), 'Gemfile'),\n }\n\n try {\n await system.exec(bundleExecutable(), ['exec', 'shopify'].concat(args), {\n stdio: 'inherit',\n cwd: directory ?? process.cwd(),\n env,\n signal,\n })\n } catch (error) {\n // CLI2 will show it's own errors, we don't need to show an additional CLI3 error\n throw new AbortSilent()\n }\n}\n\ninterface ExecThemeCheckCLIOptions {\n /** A list of directories in which theme-check should run */\n directories: string[]\n /** Arguments to pass to the theme-check CLI */\n args?: string[]\n /** Writable to send standard output content through */\n stdout: Writable\n /** Writable to send standard error content through */\n stderr: Writable\n}\n\n/**\n * A function that installs (if needed) and runs the theme-check CLI.\n * @param options - Options to customize the execution of theme-check.\n * @returns A promise that resolves or rejects depending on the result of the underlying theme-check process.\n */\nexport async function execThemeCheckCLI({\n directories,\n args,\n stdout,\n stderr,\n}: ExecThemeCheckCLIOptions): Promise<void[]> {\n await installThemeCheckCLIDependencies(stdout)\n\n const processes = directories.map(async (directory): Promise<void> => {\n // Check that there are files aside from the extension TOML config file,\n // otherwise theme-check will return a false failure.\n const files = await glob(join(directory, '/**/*'))\n const fileCount = files.filter((file) => !file.match(/\\.toml$/)).length\n if (fileCount === 0) return\n\n const customStderr = new Writable({\n write(chunk, ...args) {\n // For some reason, theme-check reports this initial status line to stderr\n // See https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/diagnostics_engine.rb#L31\n // which leads to https://github.com/Shopify/theme-check/blob/1092737cfb58a73ca397ffb1371665dc55df2976/lib/theme_check/language_server/io_messenger.rb#L65\n if (chunk.toString('ascii').match(/^Checking/)) {\n stdout.write(chunk, ...args)\n } else {\n stderr.write(chunk, ...args)\n }\n },\n })\n await system.exec(bundleExecutable(), ['exec', 'theme-check'].concat([directory, ...(args || [])]), {\n stdout,\n stderr: customStderr,\n cwd: themeCheckDirectory(),\n })\n })\n return Promise.all(processes)\n}\n\n/**\n * Validate Ruby Enviroment\n * Install Theme Check CLI and its dependencies\n * Shows a loading message if it's the first time installing dependencies\n * or if we are installing a new version of Theme Check CLI\n */\nasync function installThemeCheckCLIDependencies(stdout: Writable) {\n const exists = await file.exists(themeCheckDirectory())\n\n if (!exists) stdout.write('Installing theme dependencies...')\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n await validateRubyEnv()\n await createThemeCheckCLIWorkingDirectory()\n await createThemeCheckGemfile()\n await bundleInstallThemeCheck()\n },\n },\n ],\n {renderer: 'silent'},\n )\n await list.run()\n if (!exists) stdout.write('Installed theme dependencies!')\n}\n\n/**\n * Validate Ruby Enviroment\n * Install RubyCLI and its dependencies\n * Shows a loading spinner if it's the first time installing dependencies\n * or if we are installing a new version of RubyCLI\n */\nasync function installCLIDependencies() {\n const exists = await file.exists(shopifyCLIDirectory())\n const renderer = exists ? 'silent' : 'default'\n\n const list = ui.newListr(\n [\n {\n title: 'Installing theme dependencies',\n task: async () => {\n const usingLocalCLI2 = Boolean(process.env.SHOPIFY_CLI_2_0_DIRECTORY)\n await validateRubyEnv()\n if (usingLocalCLI2) {\n await bundleInstallLocalShopifyCLI()\n } else {\n await createShopifyCLIWorkingDirectory()\n await createShopifyCLIGemfile()\n await bundleInstallShopifyCLI()\n }\n },\n },\n ],\n {renderer},\n )\n await list.run()\n}\n\nasync function validateRubyEnv() {\n await validateRuby()\n await validateBundler()\n}\n\nasync function validateRuby() {\n let version\n try {\n const stdout = await system.captureOutput(rubyExecutable(), ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Ruby environment not found',\n `Make sure you have Ruby installed on your system. ${\n content`${token.link('Documentation.', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinRubyVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Ruby version ${content`${token.yellow(version.raw)}`.value} is not supported`,\n `Make sure you have at least Ruby ${content`${token.yellow(MinRubyVersion)}`.value} installed on your system. ${\n content`${token.link('Documentation.', 'https://www.ruby-lang.org/en/documentation/installation/')}`.value\n }`,\n )\n }\n}\n\nasync function validateBundler() {\n let version\n try {\n const stdout = await system.captureOutput(bundleExecutable(), ['-v'])\n version = coerce(stdout)\n } catch {\n throw new Abort(\n 'Bundler not found',\n `To install the latest version of Bundler, run ${\n content`${token.genericShellCommand(`${gemExecutable()} install bundler`)}`.value\n }`,\n )\n }\n\n const isValid = version?.compare(MinBundlerVersion)\n if (isValid === -1 || isValid === undefined) {\n throw new Abort(\n `Bundler version ${content`${token.yellow(version.raw)}`.value} is not supported`,\n `To update to the latest version of Bundler, run ${\n content`${token.genericShellCommand(`${gemExecutable()} install bundler`)}`.value\n }`,\n )\n }\n}\n\nfunction createShopifyCLIWorkingDirectory() {\n return file.mkdir(shopifyCLIDirectory())\n}\n\nfunction createThemeCheckCLIWorkingDirectory() {\n return file.mkdir(themeCheckDirectory())\n}\n\nasync function createShopifyCLIGemfile() {\n const gemPath = join(shopifyCLIDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'shopify-cli', '${RubyCLIVersion}'`)\n}\n\nasync function createThemeCheckGemfile() {\n const gemPath = join(themeCheckDirectory(), 'Gemfile')\n await file.write(gemPath, `source 'https://rubygems.org'\\ngem 'theme-check', '${ThemeCheckVersion}'`)\n}\n\nasync function bundleInstallLocalShopifyCLI() {\n await system.exec(bundleExecutable(), ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallShopifyCLI() {\n await system.exec(bundleExecutable(), ['config', 'set', '--local', 'path', shopifyCLIDirectory()], {\n cwd: shopifyCLIDirectory(),\n })\n await system.exec(bundleExecutable(), ['install'], {cwd: shopifyCLIDirectory()})\n}\n\nasync function bundleInstallThemeCheck() {\n await system.exec(bundleExecutable(), ['config', 'set', '--local', 'path', themeCheckDirectory()], {\n cwd: themeCheckDirectory(),\n })\n await system.exec(bundleExecutable(), ['install'], {cwd: themeCheckDirectory()})\n}\n\nfunction shopifyCLIDirectory() {\n return (\n process.env.SHOPIFY_CLI_2_0_DIRECTORY ??\n join(constants.paths.directories.cache.vendor.path(), 'ruby-cli', RubyCLIVersion)\n )\n}\n\nfunction themeCheckDirectory() {\n return join(constants.paths.directories.cache.vendor.path(), 'theme-check', ThemeCheckVersion)\n}\n\nexport async function version(): Promise<string | undefined> {\n const parseOutput = (version: string) => version.match(/ruby (\\d+\\.\\d+\\.\\d+)/)?.[1]\n return system\n .captureOutput(rubyExecutable(), ['-v'])\n .then(parseOutput)\n .catch(() => undefined)\n}\n\nfunction getRubyBinDir(): string | undefined {\n return process.env.SHOPIFY_RUBY_BINDIR\n}\n\nfunction rubyExecutable(): string {\n const rubyBinDir = getRubyBinDir()\n return rubyBinDir ? join(rubyBinDir, 'ruby') : 'ruby'\n}\n\nfunction bundleExecutable(): string {\n const rubyBinDir = getRubyBinDir()\n return rubyBinDir ? join(rubyBinDir, 'bundle') : 'bundle'\n}\n\nfunction gemExecutable(): string {\n const rubyBinDir = getRubyBinDir()\n return rubyBinDir ? join(rubyBinDir, 'gem') : 'gem'\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  interface Props {
3
3
  url: string;
4
- label: string;
4
+ label?: string;
5
5
  }
6
6
  /**
7
7
  * `Link` displays a clickable link when supported by the terminal.
@@ -6,7 +6,7 @@ import terminalLink from 'terminal-link';
6
6
  */
7
7
  const Link = ({ url, label }) => {
8
8
  return (React.createElement(Text, null,
9
- React.createElement(Text, { dimColor: true }, `${label}: `),
9
+ label && React.createElement(Text, { dimColor: true }, `${label}: `),
10
10
  React.createElement(Transform, { transform: (children) => terminalLink(children, url, { fallback: false }) },
11
11
  React.createElement(Text, { underline: true }, url))));
12
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,SAAS,EAAC,MAAM,KAAK,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,YAAY,MAAM,eAAe,CAAA;AAOxC;;GAEG;AACH,MAAM,IAAI,GAAoB,CAAC,EAAC,GAAG,EAAE,KAAK,EAAiC,EAAe,EAAE;IAC1F,OAAO,CACL,oBAAC,IAAI;QACH,oBAAC,IAAI,IAAC,QAAQ,UAAE,GAAG,KAAK,IAAI,CAAQ;QACpC,oBAAC,SAAS,IAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAC,QAAQ,EAAE,KAAK,EAAC,CAAC;YAChF,oBAAC,IAAI,IAAC,SAAS,UAAE,GAAG,CAAQ,CAClB,CACP,CACR,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import {Text, Transform} from 'ink'\nimport React from 'react'\nimport terminalLink from 'terminal-link'\n\ninterface Props {\n url: string\n label: string\n}\n\n/**\n * `Link` displays a clickable link when supported by the terminal.\n */\nconst Link: React.FC<Props> = ({url, label}: React.PropsWithChildren<Props>): JSX.Element => {\n return (\n <Text>\n <Text dimColor>{`${label}: `}</Text>\n <Transform transform={(children) => terminalLink(children, url, {fallback: false})}>\n <Text underline>{url}</Text>\n </Transform>\n </Text>\n )\n}\n\nexport {Link}\n"]}
1
+ {"version":3,"file":"Link.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,SAAS,EAAC,MAAM,KAAK,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,YAAY,MAAM,eAAe,CAAA;AAOxC;;GAEG;AACH,MAAM,IAAI,GAAoB,CAAC,EAAC,GAAG,EAAE,KAAK,EAAiC,EAAe,EAAE;IAC1F,OAAO,CACL,oBAAC,IAAI;QACF,KAAK,IAAI,oBAAC,IAAI,IAAC,QAAQ,UAAE,GAAG,KAAK,IAAI,CAAQ;QAC9C,oBAAC,SAAS,IAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,EAAC,QAAQ,EAAE,KAAK,EAAC,CAAC;YAChF,oBAAC,IAAI,IAAC,SAAS,UAAE,GAAG,CAAQ,CAClB,CACP,CACR,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import {Text, Transform} from 'ink'\nimport React from 'react'\nimport terminalLink from 'terminal-link'\n\ninterface Props {\n url: string\n label?: string\n}\n\n/**\n * `Link` displays a clickable link when supported by the terminal.\n */\nconst Link: React.FC<Props> = ({url, label}: React.PropsWithChildren<Props>): JSX.Element => {\n return (\n <Text>\n {label && <Text dimColor>{`${label}: `}</Text>}\n <Transform transform={(children) => terminalLink(children, url, {fallback: false})}>\n <Text underline>{url}</Text>\n </Transform>\n </Text>\n )\n}\n\nexport {Link}\n"]}
@@ -4,7 +4,7 @@ interface CommandToken {
4
4
  }
5
5
  interface LinkToken {
6
6
  link: {
7
- label: string;
7
+ label?: string;
8
8
  url: string;
9
9
  };
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TokenizedText.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,MAAM,OAAO,CAAA;AAoBzB;;;GAGG;AACH,MAAM,aAAa,GAAoB,CAAC,EAAC,IAAI,EAAC,EAAE,EAAE;IAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC5B,OAAO,oBAAC,IAAI,IAAC,QAAQ,UAAE,IAAI,CAAQ,CAAA;KACpC;SAAM,IAAI,SAAS,IAAI,IAAI,EAAE;QAC5B,OAAO,oBAAC,OAAO,IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,GAAI,CAAA;KAC1C;SAAM,IAAI,MAAM,IAAI,IAAI,EAAE;QACzB,OAAO,oBAAC,IAAI,OAAK,IAAI,CAAC,IAAI,GAAI,CAAA;KAC/B;SAAM;QACL,OAAO,CACL,oBAAC,IAAI,QACF,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAC7B,oBAAC,IAAI,IAAC,GAAG,EAAE,KAAK;YACd,oBAAC,aAAa,IAAC,IAAI,EAAE,QAAQ,GAAI;YAChC,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,oBAAC,IAAI,YAAS,CACrC,CACR,CAAC,CACG,CACR,CAAA;KACF;AACH,CAAC,CAAA;AAED,OAAO,EAAC,aAAa,EAAC,CAAA","sourcesContent":["import {Command} from './Command.js'\nimport {Link} from './Link.js'\nimport {Text} from 'ink'\nimport React from 'react'\n\ninterface CommandToken {\n command: string\n}\n\ninterface LinkToken {\n link: {\n label: string\n url: string\n }\n}\n\nexport type TextToken = string | CommandToken | LinkToken\nexport type TextTokenItem = TextToken | TextToken[]\n\ninterface Props {\n item: TextToken | TextToken[]\n}\n\n/**\n * `TokenizedText` renders a text string with tokens that can be either strings,\n * links, and commands.\n */\nconst TokenizedText: React.FC<Props> = ({item}) => {\n if (typeof item === 'string') {\n return <Text dimColor>{item}</Text>\n } else if ('command' in item) {\n return <Command command={item.command} />\n } else if ('link' in item) {\n return <Link {...item.link} />\n } else {\n return (\n <Text>\n {item.map((listItem, index) => (\n <Text key={index}>\n <TokenizedText item={listItem} />\n {index < item.length - 1 && <Text> </Text>}\n </Text>\n ))}\n </Text>\n )\n }\n}\n\nexport {TokenizedText}\n"]}
1
+ {"version":3,"file":"TokenizedText.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/TokenizedText.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,KAAK,MAAM,OAAO,CAAA;AAoBzB;;;GAGG;AACH,MAAM,aAAa,GAAoB,CAAC,EAAC,IAAI,EAAC,EAAE,EAAE;IAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC5B,OAAO,oBAAC,IAAI,IAAC,QAAQ,UAAE,IAAI,CAAQ,CAAA;KACpC;SAAM,IAAI,SAAS,IAAI,IAAI,EAAE;QAC5B,OAAO,oBAAC,OAAO,IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,GAAI,CAAA;KAC1C;SAAM,IAAI,MAAM,IAAI,IAAI,EAAE;QACzB,OAAO,oBAAC,IAAI,OAAK,IAAI,CAAC,IAAI,GAAI,CAAA;KAC/B;SAAM;QACL,OAAO,CACL,oBAAC,IAAI,QACF,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAC7B,oBAAC,IAAI,IAAC,GAAG,EAAE,KAAK;YACd,oBAAC,aAAa,IAAC,IAAI,EAAE,QAAQ,GAAI;YAChC,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,oBAAC,IAAI,YAAS,CACrC,CACR,CAAC,CACG,CACR,CAAA;KACF;AACH,CAAC,CAAA;AAED,OAAO,EAAC,aAAa,EAAC,CAAA","sourcesContent":["import {Command} from './Command.js'\nimport {Link} from './Link.js'\nimport {Text} from 'ink'\nimport React from 'react'\n\ninterface CommandToken {\n command: string\n}\n\ninterface LinkToken {\n link: {\n label?: string\n url: string\n }\n}\n\nexport type TextToken = string | CommandToken | LinkToken\nexport type TextTokenItem = TextToken | TextToken[]\n\ninterface Props {\n item: TextToken | TextToken[]\n}\n\n/**\n * `TokenizedText` renders a text string with tokens that can be either strings,\n * links, and commands.\n */\nconst TokenizedText: React.FC<Props> = ({item}) => {\n if (typeof item === 'string') {\n return <Text dimColor>{item}</Text>\n } else if ('command' in item) {\n return <Command command={item.command} />\n } else if ('link' in item) {\n return <Link {...item.link} />\n } else {\n return (\n <Text>\n {item.map((listItem, index) => (\n <Text key={index}>\n <TokenizedText item={listItem} />\n {index < item.length - 1 && <Text> </Text>}\n </Text>\n ))}\n </Text>\n )\n }\n}\n\nexport {TokenizedText}\n"]}
@@ -1,5 +1,7 @@
1
+ import { JsonMap } from '../../json.js';
2
+ export declare const presetsFilename = "shopify.presets.toml";
1
3
  export interface Presets {
2
- [name: string]: object;
4
+ [name: string]: JsonMap;
3
5
  }
4
6
  export declare function loadPresetsFromDirectory(dir: string, opts?: {
5
7
  findUp: boolean;
@@ -1,17 +1,17 @@
1
1
  import { exists as fileExists, read as fileRead } from '../../file.js';
2
2
  import { findUp, join as pathJoin } from '../../path.js';
3
3
  import { decode as tomlDecode } from '../../toml.js';
4
- const PRESETS_FILENAME = 'shopify.presets.toml';
4
+ export const presetsFilename = 'shopify.presets.toml';
5
5
  export async function loadPresetsFromDirectory(dir, opts) {
6
6
  let presetsFilePath;
7
7
  if (opts?.findUp) {
8
- presetsFilePath = await findUp(PRESETS_FILENAME, {
8
+ presetsFilePath = await findUp(presetsFilename, {
9
9
  cwd: dir,
10
10
  type: 'file',
11
11
  });
12
12
  }
13
13
  else {
14
- const allowedPresetsFilePath = pathJoin(dir, PRESETS_FILENAME);
14
+ const allowedPresetsFilePath = pathJoin(dir, presetsFilename);
15
15
  if (await fileExists(allowedPresetsFilePath)) {
16
16
  presetsFilePath = allowedPresetsFilePath;
17
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../src/public/node/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,IAAI,UAAU,EAAE,IAAI,IAAI,QAAQ,EAAC,MAAM,eAAe,CAAA;AACpE,OAAO,EAAC,MAAM,EAAE,IAAI,IAAI,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtD,OAAO,EAAC,MAAM,IAAI,UAAU,EAAC,MAAM,eAAe,CAAA;AAElD,MAAM,gBAAgB,GAAG,sBAAsB,CAAA;AAK/C,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,GAAW,EAAE,IAAwB;IAClF,IAAI,eAAmC,CAAA;IACvC,IAAI,IAAI,EAAE,MAAM,EAAE;QAChB,eAAe,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE;YAC/C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,MAAM;SACb,CAAC,CAAA;KACH;SAAM;QACL,MAAM,sBAAsB,GAAG,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAA;QAC9D,IAAI,MAAM,UAAU,CAAC,sBAAsB,CAAC,EAAE;YAC5C,eAAe,GAAG,sBAAsB,CAAA;SACzC;KACF;IACD,IAAI,eAAe,EAAE;QACnB,OAAO,UAAU,CAAC,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAY,CAAA;KAC9D;SAAM;QACL,OAAO,EAAE,CAAA;KACV;AACH,CAAC","sourcesContent":["import {exists as fileExists, read as fileRead} from '../../file.js'\nimport {findUp, join as pathJoin} from '../../path.js'\nimport {decode as tomlDecode} from '../../toml.js'\n\nconst PRESETS_FILENAME = 'shopify.presets.toml'\n\nexport interface Presets {\n [name: string]: object\n}\nexport async function loadPresetsFromDirectory(dir: string, opts?: {findUp: boolean}): Promise<Presets> {\n let presetsFilePath: string | undefined\n if (opts?.findUp) {\n presetsFilePath = await findUp(PRESETS_FILENAME, {\n cwd: dir,\n type: 'file',\n })\n } else {\n const allowedPresetsFilePath = pathJoin(dir, PRESETS_FILENAME)\n if (await fileExists(allowedPresetsFilePath)) {\n presetsFilePath = allowedPresetsFilePath\n }\n }\n if (presetsFilePath) {\n return tomlDecode(await fileRead(presetsFilePath)) as Presets\n } else {\n return {}\n }\n}\n"]}
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../src/public/node/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,IAAI,UAAU,EAAE,IAAI,IAAI,QAAQ,EAAC,MAAM,eAAe,CAAA;AAEpE,OAAO,EAAC,MAAM,EAAE,IAAI,IAAI,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtD,OAAO,EAAC,MAAM,IAAI,UAAU,EAAC,MAAM,eAAe,CAAA;AAElD,MAAM,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAA;AAKrD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,GAAW,EAAE,IAAwB;IAClF,IAAI,eAAmC,CAAA;IACvC,IAAI,IAAI,EAAE,MAAM,EAAE;QAChB,eAAe,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE;YAC9C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,MAAM;SACb,CAAC,CAAA;KACH;SAAM;QACL,MAAM,sBAAsB,GAAG,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;QAC7D,IAAI,MAAM,UAAU,CAAC,sBAAsB,CAAC,EAAE;YAC5C,eAAe,GAAG,sBAAsB,CAAA;SACzC;KACF;IACD,IAAI,eAAe,EAAE;QACnB,OAAO,UAAU,CAAC,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAY,CAAA;KAC9D;SAAM;QACL,OAAO,EAAa,CAAA;KACrB;AACH,CAAC","sourcesContent":["import {exists as fileExists, read as fileRead} from '../../file.js'\nimport {JsonMap} from '../../json.js'\nimport {findUp, join as pathJoin} from '../../path.js'\nimport {decode as tomlDecode} from '../../toml.js'\n\nexport const presetsFilename = 'shopify.presets.toml'\n\nexport interface Presets {\n [name: string]: JsonMap\n}\nexport async function loadPresetsFromDirectory(dir: string, opts?: {findUp: boolean}): Promise<Presets> {\n let presetsFilePath: string | undefined\n if (opts?.findUp) {\n presetsFilePath = await findUp(presetsFilename, {\n cwd: dir,\n type: 'file',\n })\n } else {\n const allowedPresetsFilePath = pathJoin(dir, presetsFilename)\n if (await fileExists(allowedPresetsFilePath)) {\n presetsFilePath = allowedPresetsFilePath\n }\n }\n if (presetsFilePath) {\n return tomlDecode(await fileRead(presetsFilePath)) as Presets\n } else {\n return {} as Presets\n }\n}\n"]}
package/dist/session.d.ts CHANGED
@@ -69,7 +69,7 @@ export declare function ensureAuthenticatedStorefront(scopes?: string[]): Promis
69
69
  * @param scopes - Optional array of extra scopes to authenticate with.
70
70
  * @returns The access token for the Admin API
71
71
  */
72
- export declare function ensureAuthenticatedAdmin(store: string, scopes?: string[]): Promise<AdminSession>;
72
+ export declare function ensureAuthenticatedAdmin(store: string, scopes?: string[], forceRefresh?: boolean): Promise<AdminSession>;
73
73
  /**
74
74
  * Ensure that we have a valid session to access the Theme API.
75
75
  * If a password is provided, that token will be used against Theme Access API.
@@ -79,13 +79,13 @@ export declare function ensureAuthenticatedAdmin(store: string, scopes?: string[
79
79
  * @param scopes - Optional array of extra scopes to authenticate with.
80
80
  * @returns The access token and store
81
81
  */
82
- export declare function ensureAuthenticatedThemes(store: string, password: string | undefined, scopes?: string[]): Promise<AdminSession>;
82
+ export declare function ensureAuthenticatedThemes(store: string, password: string | undefined, scopes?: string[], forceRefresh?: boolean): Promise<AdminSession>;
83
83
  /**
84
84
  * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.
85
85
  * @param applications - An object containing the applications we need to be authenticated with.
86
86
  * @returns An instance with the access tokens organized by application.
87
87
  */
88
- export declare function ensureAuthenticated(applications: OAuthApplications, env?: NodeJS.ProcessEnv): Promise<OAuthSession>;
88
+ export declare function ensureAuthenticated(applications: OAuthApplications, env?: NodeJS.ProcessEnv, forceRefresh?: boolean): Promise<OAuthSession>;
89
89
  export declare function hasPartnerAccount(partnersToken: string): Promise<boolean>;
90
90
  /**
91
91
  * If the user creates an account from the Identity website, the created
package/dist/session.js CHANGED
@@ -66,11 +66,11 @@ ${token.json(scopes)}
66
66
  * @param scopes - Optional array of extra scopes to authenticate with.
67
67
  * @returns The access token for the Admin API
68
68
  */
69
- export async function ensureAuthenticatedAdmin(store, scopes = []) {
69
+ export async function ensureAuthenticatedAdmin(store, scopes = [], forceRefresh = false) {
70
70
  debug(content `Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${token.raw(store)}:
71
71
  ${token.json(scopes)}
72
72
  `);
73
- const tokens = await ensureAuthenticated({ adminApi: { scopes, storeFqdn: store } });
73
+ const tokens = await ensureAuthenticated({ adminApi: { scopes, storeFqdn: store } }, process.env, forceRefresh);
74
74
  if (!tokens.admin) {
75
75
  throw MissingAdminTokenError;
76
76
  }
@@ -85,20 +85,20 @@ ${token.json(scopes)}
85
85
  * @param scopes - Optional array of extra scopes to authenticate with.
86
86
  * @returns The access token and store
87
87
  */
88
- export async function ensureAuthenticatedThemes(store, password, scopes = []) {
88
+ export async function ensureAuthenticatedThemes(store, password, scopes = [], forceRefresh = false) {
89
89
  debug(content `Ensuring that the user is authenticated with the Theme API with the following scopes:
90
90
  ${token.json(scopes)}
91
91
  `);
92
92
  if (password)
93
93
  return { token: password, storeFqdn: normalizeStoreName(store) };
94
- return ensureAuthenticatedAdmin(store, scopes);
94
+ return ensureAuthenticatedAdmin(store, scopes, forceRefresh);
95
95
  }
96
96
  /**
97
97
  * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.
98
98
  * @param applications - An object containing the applications we need to be authenticated with.
99
99
  * @returns An instance with the access tokens organized by application.
100
100
  */
101
- export async function ensureAuthenticated(applications, env = process.env) {
101
+ export async function ensureAuthenticated(applications, env = process.env, forceRefresh = false) {
102
102
  const fqdn = await identityFqdn();
103
103
  if (applications.adminApi?.storeFqdn) {
104
104
  applications.adminApi.storeFqdn = normalizeStoreName(applications.adminApi.storeFqdn);
@@ -117,7 +117,7 @@ ${token.json(applications)}
117
117
  debug(content `Initiating the full authentication flow...`);
118
118
  newSession = await executeCompleteFlow(applications, fqdn);
119
119
  }
120
- else if (validationResult === 'needs_refresh') {
120
+ else if (validationResult === 'needs_refresh' || forceRefresh) {
121
121
  debug(content `The current session is valid but needs refresh. Refreshing...`);
122
122
  try {
123
123
  newSession = await refreshTokens(fqdnSession.identity, applications, fqdn);
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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","sourcesContent":["import {applicationId} from './session/identity.js'\nimport {Abort, Bug} from './error.js'\nimport {validateSession} from './session/validate.js'\nimport {allDefaultScopes, apiScopes} from './session/scopes.js'\nimport {identity as identityFqdn, partners as partnersFqdn} from './environment/fqdn.js'\nimport {open} from './system.js'\nimport {\n exchangeAccessForApplicationTokens,\n exchangeCodeForAccessToken,\n exchangeCustomPartnerToken,\n ExchangeScopes,\n refreshAccessToken,\n InvalidGrantError,\n} from './session/exchange.js'\n\nimport {content, token, debug} from './output.js'\nimport {keypress} from './ui.js'\n\nimport {authorize} from './session/authorize.js'\nimport {IdentityToken, Session} from './session/schema.js'\nimport * as secureStore from './session/store.js'\nimport constants from './constants.js'\nimport {normalizeStoreName} from './string.js'\nimport * as output from './output.js'\nimport {partners} from './api.js'\nimport {RequestClientError} from './api/common.js'\nimport {firstPartyDev, useDeviceAuth} from './environment/local.js'\nimport {pollForDeviceAuthorization, requestDeviceAuthorization} from './session/device-authorization.js'\nimport {gql} from 'graphql-request'\n\nconst NoSessionError = new Bug('No session found after ensuring authenticated')\nconst MissingPartnerTokenError = new Bug('No partners token found after ensuring authenticated')\nconst MissingAdminTokenError = new Bug('No admin token found after ensuring authenticated')\nconst MissingStorefrontTokenError = new Bug('No storefront token found after ensuring authenticated')\n\n/**\n * A scope supported by the Shopify Admin API.\n */\ntype AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string\n\n/**\n * It represents the options to authenticate against the Shopify Admin API.\n */\ninterface AdminAPIOAuthOptions {\n /** Store to request permissions for */\n storeFqdn: string\n /** List of scopes to request permissions for */\n scopes: AdminAPIScope[]\n}\n\n/**\n * A scope supported by the Partners API.\n */\ntype PartnersAPIScope = 'cli' | string\ninterface PartnersAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: PartnersAPIScope[]\n}\n\n/**\n * A scope supported by the Storefront Renderer API.\n */\ntype StorefrontRendererScope = 'devtools' | string\ninterface StorefrontRendererAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: StorefrontRendererScope[]\n}\n\n/**\n * It represents the authentication requirements and\n * is the input necessary to trigger the authentication\n * flow.\n */\nexport interface OAuthApplications {\n adminApi?: AdminAPIOAuthOptions\n storefrontRendererApi?: StorefrontRendererAPIOAuthOptions\n partnersApi?: PartnersAPIOAuthOptions\n}\n\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\nexport interface OAuthSession {\n admin?: AdminSession\n partners?: string\n storefront?: string\n}\nexport const PartnerOrganizationNotFoundError = () => {\n return new Abort(\n `Couldn't find your Shopify Partners organization`,\n `Have you confirmed your accounts from the emails you received?`,\n )\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(scopes: string[] = [], env = process.env): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${token.json(scopes)}\n`)\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken) {\n return (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}})\n if (!tokens.partners) {\n throw MissingPartnerTokenError\n }\n return tokens.partners\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(scopes: string[] = []): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}})\n if (!tokens.storefront) {\n throw MissingStorefrontTokenError\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n * @param store - Store fqdn to request auth for\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Admin API\n */\nexport async function ensureAuthenticatedAdmin(store: string, scopes: string[] = []): Promise<AdminSession> {\n debug(content`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${token.raw(\n store,\n )}:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}})\n if (!tokens.admin) {\n throw MissingAdminTokenError\n }\n return tokens.admin\n}\n\n/**\n * Ensure that we have a valid session to access the Theme API.\n * If a password is provided, that token will be used against Theme Access API.\n * Otherwise, it will ensure that the user is authenticated with the Admin API.\n * @param store - Store fqdn to request auth for\n * @param password - Password generated from Theme Access app\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token and store\n */\nexport async function ensureAuthenticatedThemes(\n store: string,\n password: string | undefined,\n scopes: string[] = [],\n): Promise<AdminSession> {\n debug(content`Ensuring that the user is authenticated with the Theme API with the following scopes:\n${token.json(scopes)}\n`)\n if (password) return {token: password, storeFqdn: normalizeStoreName(store)}\n return ensureAuthenticatedAdmin(store, scopes)\n}\n\n/**\n * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.\n * @param applications - An object containing the applications we need to be authenticated with.\n * @returns An instance with the access tokens organized by application.\n */\nexport async function ensureAuthenticated(applications: OAuthApplications, env = process.env): Promise<OAuthSession> {\n const fqdn = await identityFqdn()\n\n if (applications.adminApi?.storeFqdn) {\n applications.adminApi.storeFqdn = normalizeStoreName(applications.adminApi.storeFqdn)\n }\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdnSession = currentSession[fqdn]!\n const scopes = getFlattenScopes(applications)\n\n debug(content`Validating existing session against the scopes:\n${token.json(scopes)}\nFor applications:\n${token.json(applications)}\n`)\n const validationResult = await validateSession(scopes, applications, fqdnSession)\n\n let newSession = {}\n\n if (validationResult === 'needs_full_auth') {\n debug(content`Initiating the full authentication flow...`)\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (validationResult === 'needs_refresh') {\n debug(content`The current session is valid but needs refresh. Refreshing...`)\n try {\n newSession = await refreshTokens(fqdnSession.identity, applications, fqdn)\n } catch (error) {\n if (error instanceof InvalidGrantError) {\n newSession = await executeCompleteFlow(applications, fqdn)\n } else {\n throw error\n }\n }\n }\n\n const completeSession: Session = {...currentSession, ...newSession}\n await secureStore.store(completeSession)\n const tokens = await tokensFor(applications, completeSession, fqdn)\n\n // Overwrite partners token if using a custom CLI Token\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken && applications.partnersApi) {\n tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n if (!envToken && tokens.partners) {\n await ensureUserHasPartnerAccount(tokens.partners)\n }\n\n return tokens\n}\n\nexport async function hasPartnerAccount(partnersToken: string): Promise<boolean> {\n try {\n await partners.request(\n gql`\n {\n organizations(first: 1) {\n nodes {\n id\n }\n }\n }\n `,\n partnersToken,\n )\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n if (error instanceof RequestClientError && error.statusCode === 404) {\n return false\n } else {\n return true\n }\n }\n}\n\n/**\n * If the user creates an account from the Identity website, the created\n * account won't get a Partner organization created. We need to detect that\n * and take the user to create a partner organization.\n * @param partnersToken - Partners token\n */\nexport async function ensureUserHasPartnerAccount(partnersToken: string) {\n debug(content`Verifying that the user has a Partner organization`)\n if (!(await hasPartnerAccount(partnersToken))) {\n output.info(`\\nA Shopify Partners organization is needed to proceed.`)\n output.info(`👉 Press any key to create one`)\n await keypress()\n await open(`https://${await partnersFqdn()}/signup`)\n output.info(output.content`👉 Press any key when you have ${output.token.cyan('created the organization')}`)\n output.warn(output.content`Make sure you've confirmed your Shopify and the Partner organization from the email`)\n await keypress()\n if (!(await hasPartnerAccount(partnersToken))) {\n throw PartnerOrganizationNotFoundError()\n }\n }\n}\n\nasync function executeCompleteFlow(applications: OAuthApplications, identityFqdn: string): Promise<Session> {\n const scopes = getFlattenScopes(applications)\n const exchangeScopes = getExchangeScopes(applications)\n const store = applications.adminApi?.storeFqdn\n if (firstPartyDev()) {\n debug(content`Authenticating as Shopify Employee...`)\n scopes.push('employee')\n }\n\n let identityToken: IdentityToken\n if (useDeviceAuth()) {\n // Request a device code to authorize without a browser redirect.\n debug(content`Requesting device authorization code...`)\n const deviceAuth = await requestDeviceAuthorization(scopes)\n\n // Poll for the identity token\n debug(content`Starting polling for the identity token...`)\n identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval)\n } else {\n // Authorize user via browser\n debug(content`Authorizing through Identity's website...`)\n const code = await authorize(scopes)\n\n // Exchange code for identity token\n debug(content`Authorization code received. Exchanging it for a CLI token...`)\n identityToken = await exchangeCodeForAccessToken(code)\n }\n\n // Exchange identity token for application tokens\n debug(content`CLI token received. Exchanging it for application tokens...`)\n const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store)\n\n const session: Session = {\n [identityFqdn]: {\n identity: identityToken,\n applications: result,\n },\n }\n\n output.completed('Logged in.')\n\n return session\n}\n\nasync function refreshTokens(token: IdentityToken, applications: OAuthApplications, fqdn: string): Promise<Session> {\n // Refresh Identity Token\n const identityToken = await refreshAccessToken(token)\n\n // Exchange new identity token for application tokens\n const exchangeScopes = getExchangeScopes(applications)\n const applicationTokens = await exchangeAccessForApplicationTokens(\n identityToken,\n exchangeScopes,\n applications.adminApi?.storeFqdn,\n )\n\n return {\n [fqdn]: {\n identity: identityToken,\n applications: applicationTokens,\n },\n }\n}\n\nasync function tokensFor(applications: OAuthApplications, session: Session, fqdn: string): Promise<OAuthSession> {\n const fqdnSession = session[fqdn]\n if (!fqdnSession) {\n throw NoSessionError\n }\n const tokens: OAuthSession = {}\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = fqdnSession.applications[realAppId]?.accessToken\n if (token) {\n tokens.admin = {token, storeFqdn: applications.adminApi.storeFqdn}\n }\n }\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n tokens.partners = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n tokens.storefront = fqdnSession.applications[appId]?.accessToken\n }\n return tokens\n}\n\n// Scope Helpers\nfunction getFlattenScopes(apps: OAuthApplications): string[] {\n const admin = apps.adminApi?.scopes || []\n const partner = apps.partnersApi?.scopes || []\n const storefront = apps.storefrontRendererApi?.scopes || []\n const requestedScopes = [...admin, ...partner, ...storefront]\n return allDefaultScopes(requestedScopes)\n}\n\nfunction getExchangeScopes(apps: OAuthApplications): ExchangeScopes {\n const adminScope = apps.adminApi?.scopes || []\n const partnerScope = apps.partnersApi?.scopes || []\n const storefrontScopes = apps.storefrontRendererApi?.scopes || []\n return {\n admin: apiScopes('admin', adminScope),\n partners: apiScopes('partners', partnerScope),\n storefront: apiScopes('storefront-renderer', storefrontScopes),\n }\n}\n\nexport function logout() {\n return secureStore.remove()\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAC,KAAK,EAAE,GAAG,EAAC,MAAM,YAAY,CAAA;AACrC,OAAO,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAC,gBAAgB,EAAE,SAAS,EAAC,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAC,QAAQ,IAAI,YAAY,EAAE,QAAQ,IAAI,YAAY,EAAC,MAAM,uBAAuB,CAAA;AACxF,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAA;AAChC,OAAO,EACL,kCAAkC,EAClC,0BAA0B,EAC1B,0BAA0B,EAE1B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAC,MAAM,aAAa,CAAA;AACjD,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAA;AAEhC,OAAO,EAAC,SAAS,EAAC,MAAM,wBAAwB,CAAA;AAEhD,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AACjD,OAAO,SAAS,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAC,QAAQ,EAAC,MAAM,UAAU,CAAA;AACjC,OAAO,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAC,aAAa,EAAE,aAAa,EAAC,MAAM,wBAAwB,CAAA;AACnE,OAAO,EAAC,0BAA0B,EAAE,0BAA0B,EAAC,MAAM,mCAAmC,CAAA;AACxG,OAAO,EAAC,GAAG,EAAC,MAAM,iBAAiB,CAAA;AAEnC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,+CAA+C,CAAC,CAAA;AAC/E,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC,sDAAsD,CAAC,CAAA;AAChG,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,mDAAmD,CAAC,CAAA;AAC3F,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,wDAAwD,CAAC,CAAA;AAwDrG,MAAM,CAAC,MAAM,gCAAgC,GAAG,GAAG,EAAE;IACnD,OAAO,IAAI,KAAK,CACd,kDAAkD,EAClD,gEAAgE,CACjE,CAAA;AACH,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,SAAmB,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG;IACxF,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;IAClE,IAAI,QAAQ,EAAE;QACZ,OAAO,CAAC,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAA;KAChE;IACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,WAAW,EAAE,EAAC,MAAM,EAAC,EAAC,CAAC,CAAA;IACjE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;QACpB,MAAM,wBAAwB,CAAA;KAC/B;IACD,OAAO,MAAM,CAAC,QAAQ,CAAA;AACxB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,SAAmB,EAAE;IACvE,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,qBAAqB,EAAE,EAAC,MAAM,EAAC,EAAC,CAAC,CAAA;IAC3E,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACtB,MAAM,2BAA2B,CAAA;KAClC;IACD,OAAO,MAAM,CAAC,UAAU,CAAA;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,KAAa,EACb,SAAmB,EAAE,EACrB,YAAY,GAAG,KAAK;IAEpB,KAAK,CAAC,OAAO,CAAA,sGAAsG,KAAK,CAAC,GAAG,CAC1H,KAAK,CACN;EACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAC,QAAQ,EAAE,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAC,EAAC,EAAE,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAC3G,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;QACjB,MAAM,sBAAsB,CAAA;KAC7B;IACD,OAAO,MAAM,CAAC,KAAK,CAAA;AACrB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAa,EACb,QAA4B,EAC5B,SAAmB,EAAE,EACrB,YAAY,GAAG,KAAK;IAEpB,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;CACnB,CAAC,CAAA;IACA,IAAI,QAAQ;QAAE,OAAO,EAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAC,CAAA;IAC5E,OAAO,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,CAAC,CAAA;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAA+B,EAC/B,GAAG,GAAG,OAAO,CAAC,GAAG,EACjB,YAAY,GAAG,KAAK;IAEpB,MAAM,IAAI,GAAG,MAAM,YAAY,EAAE,CAAA;IAEjC,IAAI,YAAY,CAAC,QAAQ,EAAE,SAAS,EAAE;QACpC,YAAY,CAAC,QAAQ,CAAC,SAAS,GAAG,kBAAkB,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;KACtF;IAED,MAAM,cAAc,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAA;IACxD,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAE,CAAA;IACzC,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAE7C,KAAK,CAAC,OAAO,CAAA;EACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;;EAElB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;CACzB,CAAC,CAAA;IACA,MAAM,gBAAgB,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,CAAA;IAEjF,IAAI,UAAU,GAAG,EAAE,CAAA;IAEnB,IAAI,gBAAgB,KAAK,iBAAiB,EAAE;QAC1C,KAAK,CAAC,OAAO,CAAA,4CAA4C,CAAC,CAAA;QAC1D,UAAU,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;KAC3D;SAAM,IAAI,gBAAgB,KAAK,eAAe,IAAI,YAAY,EAAE;QAC/D,KAAK,CAAC,OAAO,CAAA,+DAA+D,CAAC,CAAA;QAC7E,IAAI;YACF,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,CAAC,CAAA;SAC3E;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,iBAAiB,EAAE;gBACtC,UAAU,GAAG,MAAM,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;aAC3D;iBAAM;gBACL,MAAM,KAAK,CAAA;aACZ;SACF;KACF;IAED,MAAM,eAAe,GAAY,EAAC,GAAG,cAAc,EAAE,GAAG,UAAU,EAAC,CAAA;IACnE,MAAM,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;IACxC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,EAAE,eAAe,EAAE,IAAI,CAAC,CAAA;IAEnE,uDAAuD;IACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;IAClE,IAAI,QAAQ,IAAI,YAAY,CAAC,WAAW,EAAE;QACxC,MAAM,CAAC,QAAQ,GAAG,CAAC,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAA;KAC3E;IACD,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE;QAChC,MAAM,2BAA2B,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;KACnD;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,aAAqB;IAC3D,IAAI;QACF,MAAM,QAAQ,CAAC,OAAO,CACpB,GAAG,CAAA;;;;;;;;OAQF,EACD,aAAa,CACd,CAAA;QACD,OAAO,IAAI,CAAA;QACX,qDAAqD;KACtD;IAAC,OAAO,KAAK,EAAE;QACd,IAAI,KAAK,YAAY,kBAAkB,IAAI,KAAK,CAAC,UAAU,KAAK,GAAG,EAAE;YACnE,OAAO,KAAK,CAAA;SACb;aAAM;YACL,OAAO,IAAI,CAAA;SACZ;KACF;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,aAAqB;IACrE,KAAK,CAAC,OAAO,CAAA,oDAAoD,CAAC,CAAA;IAClE,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC,EAAE;QAC7C,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;QACtE,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;QAC7C,MAAM,QAAQ,EAAE,CAAA;QAChB,MAAM,IAAI,CAAC,WAAW,MAAM,YAAY,EAAE,SAAS,CAAC,CAAA;QACpD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA,kCAAkC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAA;QAC5G,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA,qFAAqF,CAAC,CAAA;QAChH,MAAM,QAAQ,EAAE,CAAA;QAChB,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC,EAAE;YAC7C,MAAM,gCAAgC,EAAE,CAAA;SACzC;KACF;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,YAA+B,EAAE,YAAoB;IACtF,MAAM,MAAM,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAA;IAC7C,MAAM,cAAc,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC9C,IAAI,aAAa,EAAE,EAAE;QACnB,KAAK,CAAC,OAAO,CAAA,uCAAuC,CAAC,CAAA;QACrD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;KACxB;IAED,IAAI,aAA4B,CAAA;IAChC,IAAI,aAAa,EAAE,EAAE;QACnB,iEAAiE;QACjE,KAAK,CAAC,OAAO,CAAA,yCAAyC,CAAC,CAAA;QACvD,MAAM,UAAU,GAAG,MAAM,0BAA0B,CAAC,MAAM,CAAC,CAAA;QAE3D,8BAA8B;QAC9B,KAAK,CAAC,OAAO,CAAA,4CAA4C,CAAC,CAAA;QAC1D,aAAa,GAAG,MAAM,0BAA0B,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;KAC7F;SAAM;QACL,6BAA6B;QAC7B,KAAK,CAAC,OAAO,CAAA,2CAA2C,CAAC,CAAA;QACzD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAA;QAEpC,mCAAmC;QACnC,KAAK,CAAC,OAAO,CAAA,+DAA+D,CAAC,CAAA;QAC7E,aAAa,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,CAAA;KACvD;IAED,iDAAiD;IACjD,KAAK,CAAC,OAAO,CAAA,6DAA6D,CAAC,CAAA;IAC3E,MAAM,MAAM,GAAG,MAAM,kCAAkC,CAAC,aAAa,EAAE,cAAc,EAAE,KAAK,CAAC,CAAA;IAE7F,MAAM,OAAO,GAAY;QACvB,CAAC,YAAY,CAAC,EAAE;YACd,QAAQ,EAAE,aAAa;YACvB,YAAY,EAAE,MAAM;SACrB;KACF,CAAA;IAED,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;IAE9B,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAAoB,EAAE,YAA+B,EAAE,IAAY;IAC9F,yBAAyB;IACzB,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAA;IACrD,qDAAqD;IACrD,MAAM,cAAc,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAA;IACtD,MAAM,iBAAiB,GAAG,MAAM,kCAAkC,CAChE,aAAa,EACb,cAAc,EACd,YAAY,CAAC,QAAQ,EAAE,SAAS,CACjC,CAAA;IAED,OAAO;QACL,CAAC,IAAI,CAAC,EAAE;YACN,QAAQ,EAAE,aAAa;YACvB,YAAY,EAAE,iBAAiB;SAChC;KACF,CAAA;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,YAA+B,EAAE,OAAgB,EAAE,IAAY;IACtF,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,cAAc,CAAA;KACrB;IACD,MAAM,MAAM,GAAiB,EAAE,CAAA;IAC/B,IAAI,YAAY,CAAC,QAAQ,EAAE;QACzB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QACpC,MAAM,SAAS,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,SAAS,IAAI,KAAK,EAAE,CAAA;QAC/D,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,WAAW,CAAA;QAC9D,IAAI,KAAK,EAAE;YACT,MAAM,CAAC,KAAK,GAAG,EAAC,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAC,CAAA;SACnE;KACF;IAED,IAAI,YAAY,CAAC,WAAW,EAAE;QAC5B,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;QACvC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAC/D;IAED,IAAI,YAAY,CAAC,qBAAqB,EAAE;QACtC,MAAM,KAAK,GAAG,aAAa,CAAC,qBAAqB,CAAC,CAAA;QAClD,MAAM,CAAC,UAAU,GAAG,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KACjE;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,gBAAgB;AAChB,SAAS,gBAAgB,CAAC,IAAuB;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAA;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,CAAA;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE,MAAM,IAAI,EAAE,CAAA;IAC3D,MAAM,eAAe,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC,CAAA;IAC7D,OAAO,gBAAgB,CAAC,eAAe,CAAC,CAAA;AAC1C,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAuB;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAA;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,CAAA;IACnD,MAAM,gBAAgB,GAAG,IAAI,CAAC,qBAAqB,EAAE,MAAM,IAAI,EAAE,CAAA;IACjE,OAAO;QACL,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC;QACrC,QAAQ,EAAE,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC;QAC7C,UAAU,EAAE,SAAS,CAAC,qBAAqB,EAAE,gBAAgB,CAAC;KAC/D,CAAA;AACH,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,WAAW,CAAC,MAAM,EAAE,CAAA;AAC7B,CAAC","sourcesContent":["import {applicationId} from './session/identity.js'\nimport {Abort, Bug} from './error.js'\nimport {validateSession} from './session/validate.js'\nimport {allDefaultScopes, apiScopes} from './session/scopes.js'\nimport {identity as identityFqdn, partners as partnersFqdn} from './environment/fqdn.js'\nimport {open} from './system.js'\nimport {\n exchangeAccessForApplicationTokens,\n exchangeCodeForAccessToken,\n exchangeCustomPartnerToken,\n ExchangeScopes,\n refreshAccessToken,\n InvalidGrantError,\n} from './session/exchange.js'\n\nimport {content, token, debug} from './output.js'\nimport {keypress} from './ui.js'\n\nimport {authorize} from './session/authorize.js'\nimport {IdentityToken, Session} from './session/schema.js'\nimport * as secureStore from './session/store.js'\nimport constants from './constants.js'\nimport {normalizeStoreName} from './string.js'\nimport * as output from './output.js'\nimport {partners} from './api.js'\nimport {RequestClientError} from './api/common.js'\nimport {firstPartyDev, useDeviceAuth} from './environment/local.js'\nimport {pollForDeviceAuthorization, requestDeviceAuthorization} from './session/device-authorization.js'\nimport {gql} from 'graphql-request'\n\nconst NoSessionError = new Bug('No session found after ensuring authenticated')\nconst MissingPartnerTokenError = new Bug('No partners token found after ensuring authenticated')\nconst MissingAdminTokenError = new Bug('No admin token found after ensuring authenticated')\nconst MissingStorefrontTokenError = new Bug('No storefront token found after ensuring authenticated')\n\n/**\n * A scope supported by the Shopify Admin API.\n */\ntype AdminAPIScope = 'graphql' | 'themes' | 'collaborator' | string\n\n/**\n * It represents the options to authenticate against the Shopify Admin API.\n */\ninterface AdminAPIOAuthOptions {\n /** Store to request permissions for */\n storeFqdn: string\n /** List of scopes to request permissions for */\n scopes: AdminAPIScope[]\n}\n\n/**\n * A scope supported by the Partners API.\n */\ntype PartnersAPIScope = 'cli' | string\ninterface PartnersAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: PartnersAPIScope[]\n}\n\n/**\n * A scope supported by the Storefront Renderer API.\n */\ntype StorefrontRendererScope = 'devtools' | string\ninterface StorefrontRendererAPIOAuthOptions {\n /** List of scopes to request permissions for */\n scopes: StorefrontRendererScope[]\n}\n\n/**\n * It represents the authentication requirements and\n * is the input necessary to trigger the authentication\n * flow.\n */\nexport interface OAuthApplications {\n adminApi?: AdminAPIOAuthOptions\n storefrontRendererApi?: StorefrontRendererAPIOAuthOptions\n partnersApi?: PartnersAPIOAuthOptions\n}\n\nexport interface AdminSession {\n token: string\n storeFqdn: string\n}\n\nexport interface OAuthSession {\n admin?: AdminSession\n partners?: string\n storefront?: string\n}\nexport const PartnerOrganizationNotFoundError = () => {\n return new Abort(\n `Couldn't find your Shopify Partners organization`,\n `Have you confirmed your accounts from the emails you received?`,\n )\n}\n\n/**\n * Ensure that we have a valid session to access the Partners API.\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, that token will be used to obtain a valid Partners Token\n * If SHOPIFY_CLI_PARTNERS_TOKEN exists, scopes will be ignored\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Partners API.\n */\nexport async function ensureAuthenticatedPartners(scopes: string[] = [], env = process.env): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Partners API with the following scopes:\n${token.json(scopes)}\n`)\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken) {\n return (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n const tokens = await ensureAuthenticated({partnersApi: {scopes}})\n if (!tokens.partners) {\n throw MissingPartnerTokenError\n }\n return tokens.partners\n}\n\n/**\n * Ensure that we have a valid session to access the Storefront API.\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Storefront API.\n */\nexport async function ensureAuthenticatedStorefront(scopes: string[] = []): Promise<string> {\n debug(content`Ensuring that the user is authenticated with the Storefront API with the following scopes:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({storefrontRendererApi: {scopes}})\n if (!tokens.storefront) {\n throw MissingStorefrontTokenError\n }\n return tokens.storefront\n}\n\n/**\n * Ensure that we have a valid Admin session for the given store.\n * @param store - Store fqdn to request auth for\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token for the Admin API\n */\nexport async function ensureAuthenticatedAdmin(\n store: string,\n scopes: string[] = [],\n forceRefresh = false,\n): Promise<AdminSession> {\n debug(content`Ensuring that the user is authenticated with the Admin API with the following scopes for the store ${token.raw(\n store,\n )}:\n${token.json(scopes)}\n`)\n const tokens = await ensureAuthenticated({adminApi: {scopes, storeFqdn: store}}, process.env, forceRefresh)\n if (!tokens.admin) {\n throw MissingAdminTokenError\n }\n return tokens.admin\n}\n\n/**\n * Ensure that we have a valid session to access the Theme API.\n * If a password is provided, that token will be used against Theme Access API.\n * Otherwise, it will ensure that the user is authenticated with the Admin API.\n * @param store - Store fqdn to request auth for\n * @param password - Password generated from Theme Access app\n * @param scopes - Optional array of extra scopes to authenticate with.\n * @returns The access token and store\n */\nexport async function ensureAuthenticatedThemes(\n store: string,\n password: string | undefined,\n scopes: string[] = [],\n forceRefresh = false,\n): Promise<AdminSession> {\n debug(content`Ensuring that the user is authenticated with the Theme API with the following scopes:\n${token.json(scopes)}\n`)\n if (password) return {token: password, storeFqdn: normalizeStoreName(store)}\n return ensureAuthenticatedAdmin(store, scopes, forceRefresh)\n}\n\n/**\n * This method ensures that we have a valid session to authenticate against the given applications using the provided scopes.\n * @param applications - An object containing the applications we need to be authenticated with.\n * @returns An instance with the access tokens organized by application.\n */\nexport async function ensureAuthenticated(\n applications: OAuthApplications,\n env = process.env,\n forceRefresh = false,\n): Promise<OAuthSession> {\n const fqdn = await identityFqdn()\n\n if (applications.adminApi?.storeFqdn) {\n applications.adminApi.storeFqdn = normalizeStoreName(applications.adminApi.storeFqdn)\n }\n\n const currentSession = (await secureStore.fetch()) || {}\n const fqdnSession = currentSession[fqdn]!\n const scopes = getFlattenScopes(applications)\n\n debug(content`Validating existing session against the scopes:\n${token.json(scopes)}\nFor applications:\n${token.json(applications)}\n`)\n const validationResult = await validateSession(scopes, applications, fqdnSession)\n\n let newSession = {}\n\n if (validationResult === 'needs_full_auth') {\n debug(content`Initiating the full authentication flow...`)\n newSession = await executeCompleteFlow(applications, fqdn)\n } else if (validationResult === 'needs_refresh' || forceRefresh) {\n debug(content`The current session is valid but needs refresh. Refreshing...`)\n try {\n newSession = await refreshTokens(fqdnSession.identity, applications, fqdn)\n } catch (error) {\n if (error instanceof InvalidGrantError) {\n newSession = await executeCompleteFlow(applications, fqdn)\n } else {\n throw error\n }\n }\n }\n\n const completeSession: Session = {...currentSession, ...newSession}\n await secureStore.store(completeSession)\n const tokens = await tokensFor(applications, completeSession, fqdn)\n\n // Overwrite partners token if using a custom CLI Token\n const envToken = env[constants.environmentVariables.partnersToken]\n if (envToken && applications.partnersApi) {\n tokens.partners = (await exchangeCustomPartnerToken(envToken)).accessToken\n }\n if (!envToken && tokens.partners) {\n await ensureUserHasPartnerAccount(tokens.partners)\n }\n\n return tokens\n}\n\nexport async function hasPartnerAccount(partnersToken: string): Promise<boolean> {\n try {\n await partners.request(\n gql`\n {\n organizations(first: 1) {\n nodes {\n id\n }\n }\n }\n `,\n partnersToken,\n )\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n if (error instanceof RequestClientError && error.statusCode === 404) {\n return false\n } else {\n return true\n }\n }\n}\n\n/**\n * If the user creates an account from the Identity website, the created\n * account won't get a Partner organization created. We need to detect that\n * and take the user to create a partner organization.\n * @param partnersToken - Partners token\n */\nexport async function ensureUserHasPartnerAccount(partnersToken: string) {\n debug(content`Verifying that the user has a Partner organization`)\n if (!(await hasPartnerAccount(partnersToken))) {\n output.info(`\\nA Shopify Partners organization is needed to proceed.`)\n output.info(`👉 Press any key to create one`)\n await keypress()\n await open(`https://${await partnersFqdn()}/signup`)\n output.info(output.content`👉 Press any key when you have ${output.token.cyan('created the organization')}`)\n output.warn(output.content`Make sure you've confirmed your Shopify and the Partner organization from the email`)\n await keypress()\n if (!(await hasPartnerAccount(partnersToken))) {\n throw PartnerOrganizationNotFoundError()\n }\n }\n}\n\nasync function executeCompleteFlow(applications: OAuthApplications, identityFqdn: string): Promise<Session> {\n const scopes = getFlattenScopes(applications)\n const exchangeScopes = getExchangeScopes(applications)\n const store = applications.adminApi?.storeFqdn\n if (firstPartyDev()) {\n debug(content`Authenticating as Shopify Employee...`)\n scopes.push('employee')\n }\n\n let identityToken: IdentityToken\n if (useDeviceAuth()) {\n // Request a device code to authorize without a browser redirect.\n debug(content`Requesting device authorization code...`)\n const deviceAuth = await requestDeviceAuthorization(scopes)\n\n // Poll for the identity token\n debug(content`Starting polling for the identity token...`)\n identityToken = await pollForDeviceAuthorization(deviceAuth.deviceCode, deviceAuth.interval)\n } else {\n // Authorize user via browser\n debug(content`Authorizing through Identity's website...`)\n const code = await authorize(scopes)\n\n // Exchange code for identity token\n debug(content`Authorization code received. Exchanging it for a CLI token...`)\n identityToken = await exchangeCodeForAccessToken(code)\n }\n\n // Exchange identity token for application tokens\n debug(content`CLI token received. Exchanging it for application tokens...`)\n const result = await exchangeAccessForApplicationTokens(identityToken, exchangeScopes, store)\n\n const session: Session = {\n [identityFqdn]: {\n identity: identityToken,\n applications: result,\n },\n }\n\n output.completed('Logged in.')\n\n return session\n}\n\nasync function refreshTokens(token: IdentityToken, applications: OAuthApplications, fqdn: string): Promise<Session> {\n // Refresh Identity Token\n const identityToken = await refreshAccessToken(token)\n // Exchange new identity token for application tokens\n const exchangeScopes = getExchangeScopes(applications)\n const applicationTokens = await exchangeAccessForApplicationTokens(\n identityToken,\n exchangeScopes,\n applications.adminApi?.storeFqdn,\n )\n\n return {\n [fqdn]: {\n identity: identityToken,\n applications: applicationTokens,\n },\n }\n}\n\nasync function tokensFor(applications: OAuthApplications, session: Session, fqdn: string): Promise<OAuthSession> {\n const fqdnSession = session[fqdn]\n if (!fqdnSession) {\n throw NoSessionError\n }\n const tokens: OAuthSession = {}\n if (applications.adminApi) {\n const appId = applicationId('admin')\n const realAppId = `${applications.adminApi.storeFqdn}-${appId}`\n const token = fqdnSession.applications[realAppId]?.accessToken\n if (token) {\n tokens.admin = {token, storeFqdn: applications.adminApi.storeFqdn}\n }\n }\n\n if (applications.partnersApi) {\n const appId = applicationId('partners')\n tokens.partners = fqdnSession.applications[appId]?.accessToken\n }\n\n if (applications.storefrontRendererApi) {\n const appId = applicationId('storefront-renderer')\n tokens.storefront = fqdnSession.applications[appId]?.accessToken\n }\n return tokens\n}\n\n// Scope Helpers\nfunction getFlattenScopes(apps: OAuthApplications): string[] {\n const admin = apps.adminApi?.scopes || []\n const partner = apps.partnersApi?.scopes || []\n const storefront = apps.storefrontRendererApi?.scopes || []\n const requestedScopes = [...admin, ...partner, ...storefront]\n return allDefaultScopes(requestedScopes)\n}\n\nfunction getExchangeScopes(apps: OAuthApplications): ExchangeScopes {\n const adminScope = apps.adminApi?.scopes || []\n const partnerScope = apps.partnersApi?.scopes || []\n const storefrontScopes = apps.storefrontRendererApi?.scopes || []\n return {\n admin: apiScopes('admin', adminScope),\n partners: apiScopes('partners', partnerScope),\n storefront: apiScopes('storefront-renderer', storefrontScopes),\n }\n}\n\nexport function logout() {\n return secureStore.remove()\n}\n"]}
@@ -1,6 +1,4 @@
1
1
  import { renderConcurrent } from '@shopify/cli-kit/node/ui';
2
- import { AbortController } from 'abort-controller';
3
- const abortController = new AbortController();
4
2
  let backendPromiseResolve;
5
3
  const backendPromise = new Promise(function (resolve, _reject) {
6
4
  backendPromiseResolve = resolve;
@@ -24,5 +22,5 @@ const frontendProcess = {
24
22
  },
25
23
  };
26
24
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
27
- renderConcurrent({ processes: [backendProcess, frontendProcess], abortController });
25
+ renderConcurrent({ processes: [backendProcess, frontendProcess] });
28
26
  //# sourceMappingURL=render-concurrent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-concurrent.js","sourceRoot":"","sources":["../../../src/testing/fixtures/render-concurrent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAA;AAEhD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;AAC7C,IAAI,qBAAiC,CAAA;AAErC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,UAAU,OAAO,EAAE,OAAO;IACjE,qBAAqB,GAAG,OAAO,CAAA;AACjC,CAAC,CAAC,CAAA;AAEF,MAAM,cAAc,GAAG;IACrB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,KAAK,EAAE,MAAgB,EAAE,OAAiB,EAAE,OAAe,EAAE,EAAE;QACrE,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACrC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACtC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QAErC,qBAAqB,EAAE,CAAA;IACzB,CAAC;CACF,CAAA;AAED,MAAM,eAAe,GAAG;IACtB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,KAAK,EAAE,MAAgB,EAAE,OAAiB,EAAE,OAAe,EAAE,EAAE;QACrE,MAAM,cAAc,CAAA;QAEpB,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACtC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAA;QACvC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;IACxC,CAAC;CACF,CAAA;AAED,mEAAmE;AACnE,gBAAgB,CAAC,EAAC,SAAS,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC,EAAE,eAAe,EAAC,CAAC,CAAA","sourcesContent":["import {Signal} from '../../abort.js'\nimport {Writable} from 'form-data'\nimport {renderConcurrent} from '@shopify/cli-kit/node/ui'\nimport {AbortController} from 'abort-controller'\n\nconst abortController = new AbortController()\nlet backendPromiseResolve: () => void\n\nconst backendPromise = new Promise<void>(function (resolve, _reject) {\n backendPromiseResolve = resolve\n})\n\nconst backendProcess = {\n prefix: 'backend',\n action: async (stdout: Writable, _stderr: Writable, _signal: Signal) => {\n stdout.write('first backend message')\n stdout.write('second backend message')\n stdout.write('third backend message')\n\n backendPromiseResolve()\n },\n}\n\nconst frontendProcess = {\n prefix: 'frontend',\n action: async (stdout: Writable, _stderr: Writable, _signal: Signal) => {\n await backendPromise\n\n stdout.write('first frontend message')\n stdout.write('second frontend message')\n stdout.write('third frontend message')\n },\n}\n\n// eslint-disable-next-line @typescript-eslint/no-floating-promises\nrenderConcurrent({processes: [backendProcess, frontendProcess], abortController})\n"]}
1
+ {"version":3,"file":"render-concurrent.js","sourceRoot":"","sources":["../../../src/testing/fixtures/render-concurrent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AAEzD,IAAI,qBAAiC,CAAA;AAErC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,UAAU,OAAO,EAAE,OAAO;IACjE,qBAAqB,GAAG,OAAO,CAAA;AACjC,CAAC,CAAC,CAAA;AAEF,MAAM,cAAc,GAAG;IACrB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,KAAK,EAAE,MAAgB,EAAE,OAAiB,EAAE,OAAe,EAAE,EAAE;QACrE,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACrC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACtC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;QAErC,qBAAqB,EAAE,CAAA;IACzB,CAAC;CACF,CAAA;AAED,MAAM,eAAe,GAAG;IACtB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,KAAK,EAAE,MAAgB,EAAE,OAAiB,EAAE,OAAe,EAAE,EAAE;QACrE,MAAM,cAAc,CAAA;QAEpB,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACtC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAA;QACvC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;IACxC,CAAC;CACF,CAAA;AAED,mEAAmE;AACnE,gBAAgB,CAAC,EAAC,SAAS,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC,EAAC,CAAC,CAAA","sourcesContent":["import {Signal} from '../../abort.js'\nimport {Writable} from 'form-data'\nimport {renderConcurrent} from '@shopify/cli-kit/node/ui'\n\nlet backendPromiseResolve: () => void\n\nconst backendPromise = new Promise<void>(function (resolve, _reject) {\n backendPromiseResolve = resolve\n})\n\nconst backendProcess = {\n prefix: 'backend',\n action: async (stdout: Writable, _stderr: Writable, _signal: Signal) => {\n stdout.write('first backend message')\n stdout.write('second backend message')\n stdout.write('third backend message')\n\n backendPromiseResolve()\n },\n}\n\nconst frontendProcess = {\n prefix: 'frontend',\n action: async (stdout: Writable, _stderr: Writable, _signal: Signal) => {\n await backendPromise\n\n stdout.write('first frontend message')\n stdout.write('second frontend message')\n stdout.write('third frontend message')\n },\n}\n\n// eslint-disable-next-line @typescript-eslint/no-floating-promises\nrenderConcurrent({processes: [backendProcess, frontendProcess]})\n"]}
@@ -1,5 +1,5 @@
1
1
  import * as path from '../path';
2
- import { execa } from 'execa';
2
+ import { execaNode } from 'execa';
3
3
  export const run = (fixture, props) => {
4
4
  const env = {
5
5
  ...process.env,
@@ -7,9 +7,11 @@ export const run = (fixture, props) => {
7
7
  // we need this because ink treats the CI environment differently
8
8
  // by only writing the last frame to stdout on unmount
9
9
  // See more here https://github.com/vadimdemedes/ink/pull/266
10
- CI: 'false',
10
+ // this way local and CI tests behave the same
11
+ CI: 'true',
11
12
  };
12
- return execa('ts-node-esm', [path.resolve(__dirname, `fixtures/${fixture}.ts`)], {
13
+ // we want to load the compiled js directly in order avoid unnecessary transpilation
14
+ return execaNode(path.resolve(__dirname, `../../dist/testing/fixtures/${fixture}.js`), {
13
15
  cwd: __dirname,
14
16
  env,
15
17
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/testing/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAC,KAAK,EAAoB,MAAM,OAAO,CAAA;AAI9C,MAAM,CAAC,MAAM,GAAG,GAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;IACzC,MAAM,GAAG,GAAG;QACV,GAAG,OAAO,CAAC,GAAG;QACd,GAAG,KAAK,EAAE,GAAG;QACb,iEAAiE;QACjE,sDAAsD;QACtD,6DAA6D;QAC7D,EAAE,EAAE,OAAO;KACZ,CAAA;IAED,OAAO,KAAK,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,OAAO,KAAK,CAAC,CAAC,EAAE;QAC/E,GAAG,EAAE,SAAS;QACd,GAAG;KACJ,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import * as path from '../path'\nimport {execa, ExecaChildProcess} from 'execa'\n\ntype Run = (fixture: string, props?: {env?: {[key: string]: unknown}}) => ExecaChildProcess<string>\n\nexport const run: Run = (fixture, props) => {\n const env = {\n ...process.env,\n ...props?.env,\n // we need this because ink treats the CI environment differently\n // by only writing the last frame to stdout on unmount\n // See more here https://github.com/vadimdemedes/ink/pull/266\n CI: 'false',\n }\n\n return execa('ts-node-esm', [path.resolve(__dirname, `fixtures/${fixture}.ts`)], {\n cwd: __dirname,\n env,\n })\n}\n"]}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/testing/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAoB,SAAS,EAAC,MAAM,OAAO,CAAA;AAIlD,MAAM,CAAC,MAAM,GAAG,GAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;IACzC,MAAM,GAAG,GAAG;QACV,GAAG,OAAO,CAAC,GAAG;QACd,GAAG,KAAK,EAAE,GAAG;QACb,iEAAiE;QACjE,sDAAsD;QACtD,6DAA6D;QAC7D,8CAA8C;QAC9C,EAAE,EAAE,MAAM;KACX,CAAA;IAED,oFAAoF;IACpF,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,+BAA+B,OAAO,KAAK,CAAC,EAAE;QACrF,GAAG,EAAE,SAAS;QACd,GAAG;KACJ,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import * as path from '../path'\nimport {ExecaChildProcess, execaNode} from 'execa'\n\ntype Run = (fixture: string, props?: {env?: {[key: string]: unknown}}) => ExecaChildProcess<string>\n\nexport const run: Run = (fixture, props) => {\n const env = {\n ...process.env,\n ...props?.env,\n // we need this because ink treats the CI environment differently\n // by only writing the last frame to stdout on unmount\n // See more here https://github.com/vadimdemedes/ink/pull/266\n // this way local and CI tests behave the same\n CI: 'true',\n }\n\n // we want to load the compiled js directly in order avoid unnecessary transpilation\n return execaNode(path.resolve(__dirname, `../../dist/testing/fixtures/${fixture}.js`), {\n cwd: __dirname,\n env,\n })\n}\n"]}