@shopify/cli-kit 3.44.1 → 3.45.0-pre.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.
- package/README.md +15 -7
- package/assets/cli-ruby/lib/project_types/extension/messages/messages.rb +0 -2
- package/assets/cli-ruby/lib/project_types/theme/commands/pull.rb +6 -0
- package/assets/cli-ruby/lib/project_types/theme/commands/push.rb +6 -0
- package/assets/cli-ruby/lib/shopify_cli/constants.rb +1 -0
- package/assets/cli-ruby/lib/shopify_cli/environment.rb +4 -0
- package/assets/cli-ruby/lib/shopify_cli/theme/dev_server/proxy.rb +3 -0
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/dev_server.rb +3 -3
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/host_theme.rb +4 -4
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/syncer/extension_serve_job.rb +4 -6
- package/assets/cli-ruby/lib/shopify_cli/theme/extension/ui/host_theme_raw_progress_bar.rb +40 -0
- package/assets/cli-ruby/vendor/deps/cli-ui/lib/cli/ui/progress_plain.rb +50 -0
- package/assets/cli-ruby/vendor/deps/cli-ui/lib/cli/ui.rb +15 -14
- package/dist/private/node/api/graphql.js +12 -23
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/api.d.ts +1 -1
- package/dist/private/node/api.js +28 -9
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/constants.d.ts +0 -1
- package/dist/private/node/constants.js +0 -1
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/testing/ui.d.ts +11 -0
- package/dist/private/node/testing/ui.js +15 -1
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/ui/alert.d.ts +5 -1
- package/dist/private/node/ui/alert.js +2 -2
- package/dist/private/node/ui/alert.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.js +38 -12
- package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +56 -36
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.d.ts +5 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +15 -13
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +20 -11
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/FullScreen.js +1 -1
- package/dist/private/node/ui/components/FullScreen.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.d.ts +7 -2
- package/dist/private/node/ui/components/SelectInput.js +73 -60
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.test.js +72 -2
- package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.js +38 -12
- package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js +52 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.js +9 -1
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextAnimation.js +4 -4
- package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.js +4 -4
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/hooks/use-layout.d.ts +6 -0
- package/dist/private/node/ui/hooks/use-layout.js +31 -12
- package/dist/private/node/ui/hooks/use-layout.js.map +1 -1
- package/dist/private/node/ui.d.ts +11 -3
- package/dist/private/node/ui.js +14 -10
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/object.d.ts +1 -1
- package/dist/public/common/object.js +1 -1
- package/dist/public/common/object.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/base-command.d.ts +1 -4
- package/dist/public/node/base-command.js +17 -19
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/context/local.d.ts +0 -7
- package/dist/public/node/context/local.js +0 -9
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/environments.d.ts +7 -8
- package/dist/public/node/environments.js +23 -25
- package/dist/public/node/environments.js.map +1 -1
- package/dist/public/node/node-package-manager.d.ts +1 -1
- package/dist/public/node/node-package-manager.js.map +1 -1
- package/dist/public/node/output.d.ts +1 -1
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/path.js +1 -1
- package/dist/public/node/path.js.map +1 -1
- package/dist/public/node/ruby.d.ts +1 -0
- package/dist/public/node/ruby.js +35 -15
- package/dist/public/node/ruby.js.map +1 -1
- package/dist/public/node/themes/theme-manager.d.ts +1 -1
- package/dist/public/node/themes/theme-manager.js.map +1 -1
- package/dist/public/node/ui.d.ts +182 -121
- package/dist/public/node/ui.js +172 -120
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -18
- package/dist/private/node/ui/components/TextWithBackground.d.ts +0 -12
- package/dist/private/node/ui/components/TextWithBackground.js +0 -39
- package/dist/private/node/ui/components/TextWithBackground.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<a href="https://github.com/Shopify/cli/actions/workflows/shopify-cli.yml"></a>
|
|
7
7
|
|
|
8
8
|
With the Shopify command line interface (Shopify CLI 3.0), you can:
|
|
9
|
+
- initialize, build, dev, and deploy Shopify apps, extensions, functions and themes
|
|
9
10
|
- build custom storefronts and manage their hosting
|
|
10
|
-
- initialize, build, dev, and deploy Shopify apps — and generate app extensions
|
|
11
11
|
|
|
12
12
|
<p> </p>
|
|
13
13
|
|
|
@@ -30,15 +30,23 @@ Learn more in the docs: [Create an app](https://shopify.dev/apps/getting-started
|
|
|
30
30
|
|
|
31
31
|
<p> </p>
|
|
32
32
|
|
|
33
|
+
## Developing themes with Shopify CLI
|
|
34
|
+
|
|
35
|
+
To work with themes, the CLI needs to be installed globally with:
|
|
36
|
+
|
|
37
|
+
- `npm install -g @shopify/cli @shopify/theme`
|
|
38
|
+
|
|
39
|
+
You can also use do it through Homebrew on macOS: `brew install shopify-cli`
|
|
40
|
+
|
|
41
|
+
Learn more in the docs: [Shopify CLI for themes](https://shopify.dev/docs/themes/tools/cli)
|
|
42
|
+
|
|
43
|
+
<p> </p>
|
|
44
|
+
|
|
33
45
|
## Developing Hydrogen custom storefronts with Shopify CLI ##
|
|
34
46
|
|
|
35
|
-
|
|
47
|
+
The Hydrogen code lives here: https://github.com/Shopify/hydrogen/tree/main/packages/cli
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
- `npm init @shopify/hydrogen@latest`
|
|
39
|
-
- `npx @shopify/create-hydrogen@latest`
|
|
40
|
-
- `pnpm create @shopify/create-hydrogen@latest`
|
|
41
|
-
- `yarn create @shopify/hydrogen`
|
|
49
|
+
Learn more in the docs: [Shopify CLI for Hydrogen storefronts](https://shopify.dev/docs/custom-storefronts/hydrogen/cli)
|
|
42
50
|
|
|
43
51
|
<p> </p>
|
|
44
52
|
|
|
@@ -35,12 +35,18 @@ module Theme
|
|
|
35
35
|
flags[:ignores] |= pattern
|
|
36
36
|
end
|
|
37
37
|
parser.on("-f", "--force") { flags[:force] = true }
|
|
38
|
+
parser.on("--development-theme-id=DEVELOPMENT_THEME_ID") do |development_theme_id|
|
|
39
|
+
flags[:development_theme_id] = development_theme_id.to_i
|
|
40
|
+
end
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
def call(_args, name)
|
|
41
44
|
root = root_value(options, name)
|
|
42
45
|
return if exist_and_not_empty?(root) && !valid_theme_directory?(root)
|
|
43
46
|
|
|
47
|
+
development_theme_id = options.flags[:development_theme_id]
|
|
48
|
+
ShopifyCLI::DB.set(development_theme_id: development_theme_id) unless development_theme_id.nil?
|
|
49
|
+
|
|
44
50
|
delete = !options.flags[:nodelete]
|
|
45
51
|
theme = find_theme(root, **options.flags)
|
|
46
52
|
return if theme.nil?
|
|
@@ -40,12 +40,18 @@ module Theme
|
|
|
40
40
|
flags[:ignores] |= pattern
|
|
41
41
|
end
|
|
42
42
|
parser.on("-f", "--force") { flags[:force] = true }
|
|
43
|
+
parser.on("--development-theme-id=DEVELOPMENT_THEME_ID") do |development_theme_id|
|
|
44
|
+
flags[:development_theme_id] = development_theme_id.to_i
|
|
45
|
+
end
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
def call(_args, name)
|
|
46
49
|
root = root_value(options, name)
|
|
47
50
|
return unless valid_theme_directory?(root)
|
|
48
51
|
|
|
52
|
+
development_theme_id = options.flags[:development_theme_id]
|
|
53
|
+
ShopifyCLI::DB.set(development_theme_id: development_theme_id) unless development_theme_id.nil?
|
|
54
|
+
|
|
49
55
|
delete = !options.flags[:nodelete]
|
|
50
56
|
theme = find_theme(root, **options.flags)
|
|
51
57
|
return if theme.nil?
|
|
@@ -109,6 +109,10 @@ module ShopifyCLI
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
def self.spin_url_override(env_variables: ENV)
|
|
112
|
+
return env_variables[Constants::EnvironmentVariables::SPIN_FQDN] if env_variables.key?(
|
|
113
|
+
Constants::EnvironmentVariables::SPIN_FQDN
|
|
114
|
+
)
|
|
115
|
+
|
|
112
116
|
tokens = SPIN_OVERRIDE_ENV_NAMES.map do |name|
|
|
113
117
|
env_variables[name]
|
|
114
118
|
end
|
|
@@ -28,6 +28,7 @@ module ShopifyCLI
|
|
|
28
28
|
SESSION_COOKIE_NAME = "_secure_session_id"
|
|
29
29
|
SESSION_COOKIE_REGEXP = /#{SESSION_COOKIE_NAME}=(\h+)/
|
|
30
30
|
SESSION_COOKIE_MAX_AGE = 60 * 60 * 23 # 1 day - leeway of 1h
|
|
31
|
+
IGNORED_ENDPOINTS = ["shopify/monorail", "mini-profiler-resources", "web-pixels-manager"]
|
|
31
32
|
|
|
32
33
|
def initialize(ctx, theme, param_builder)
|
|
33
34
|
@ctx = ctx
|
|
@@ -40,6 +41,8 @@ module ShopifyCLI
|
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
def call(env)
|
|
44
|
+
return [204, {}, []] if IGNORED_ENDPOINTS.any? { |endpoint| env["PATH_INFO"].include?(endpoint) }
|
|
45
|
+
|
|
43
46
|
headers = extract_http_request_headers(env)
|
|
44
47
|
headers["Host"] = shop
|
|
45
48
|
headers["Cookie"] = add_session_cookie(headers["Cookie"])
|
|
@@ -119,9 +119,9 @@ module ShopifyCLI
|
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def setup_server
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
ctx.puts("\n--------- #{frame_title}")
|
|
123
|
+
ctx.puts(preview_message)
|
|
124
|
+
ctx.puts("------------------\n")
|
|
125
125
|
|
|
126
126
|
watcher.start
|
|
127
127
|
syncer.start
|
|
@@ -4,7 +4,7 @@ require "fileutils"
|
|
|
4
4
|
require_relative "../syncer"
|
|
5
5
|
require_relative "../development_theme"
|
|
6
6
|
require "shopify_cli/git"
|
|
7
|
-
require "shopify_cli/theme/extension/ui/
|
|
7
|
+
require "shopify_cli/theme/extension/ui/host_theme_raw_progress_bar"
|
|
8
8
|
require "tmpdir"
|
|
9
9
|
|
|
10
10
|
require "shopify_cli/git"
|
|
@@ -77,9 +77,9 @@ module ShopifyCLI
|
|
|
77
77
|
|
|
78
78
|
begin
|
|
79
79
|
syncer.start_threads
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
ctx.puts("\n--------- #{ctx.message("theme.push.info.pushing", name, id, shop)}")
|
|
81
|
+
UI::HostThemeRawProgressBar.new(syncer, dir).progress(:upload_theme!, delete: false)
|
|
82
|
+
ctx.puts("------------------\n")
|
|
83
83
|
rescue Errno::ENOENT => e
|
|
84
84
|
ctx.debug(e.message)
|
|
85
85
|
ensure
|
|
@@ -30,6 +30,8 @@ module ShopifyCLI
|
|
|
30
30
|
|
|
31
31
|
@job_in_progress = false
|
|
32
32
|
@job_in_progress_mutex = Mutex.new
|
|
33
|
+
|
|
34
|
+
$stdout.sync = true
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
def perform!
|
|
@@ -81,16 +83,12 @@ module ShopifyCLI
|
|
|
81
83
|
Time.now - @syncer.latest_sync < PUSH_INTERVAL
|
|
82
84
|
end
|
|
83
85
|
|
|
84
|
-
def timestamp
|
|
85
|
-
Time.now.strftime("%T")
|
|
86
|
-
end
|
|
87
|
-
|
|
88
86
|
def success_message(project)
|
|
89
|
-
"
|
|
87
|
+
"{{green:Pushed}} {{>}} {{blue:'#{project}'}} to a draft"
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
def error_message(project)
|
|
93
|
-
"
|
|
91
|
+
"{{red:Error}} {{>}} {{blue:'#{project}'}} could not be pushed:"
|
|
94
92
|
end
|
|
95
93
|
|
|
96
94
|
def print_file_success(file)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
module ShopifyCLI
|
|
3
|
+
module Theme
|
|
4
|
+
module Extension
|
|
5
|
+
module UI
|
|
6
|
+
class HostThemeRawProgressBar
|
|
7
|
+
GIT_CLONE_PROGRESS_SHARE = 0.2
|
|
8
|
+
SYNC_PROGRESS_SHARE = 0.8
|
|
9
|
+
|
|
10
|
+
def initialize(syncer, dir)
|
|
11
|
+
@syncer = syncer
|
|
12
|
+
@dir = dir
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def progress(method, **args)
|
|
16
|
+
@syncer.lock_io!
|
|
17
|
+
old_sync = $stdout.sync
|
|
18
|
+
$stdout.sync = true
|
|
19
|
+
CLI::UI::ProgressPlain.progress(prefix: "Pushing theme...") do |bar|
|
|
20
|
+
bar.tick(set_percent: 0)
|
|
21
|
+
|
|
22
|
+
Git.public_send(:raw_clone, "https://github.com/Shopify/dawn.git", @dir) do |percent|
|
|
23
|
+
bar.tick(set_percent: percent * GIT_CLONE_PROGRESS_SHARE)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
@syncer.public_send(method, **args) do |left, total|
|
|
27
|
+
next if total == 0
|
|
28
|
+
bar.tick(set_percent: (1 - left.to_f / total) * SYNC_PROGRESS_SHARE + GIT_CLONE_PROGRESS_SHARE)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
bar.tick(set_percent: 1)
|
|
32
|
+
end
|
|
33
|
+
$stdout.sync = old_sync
|
|
34
|
+
@syncer.unlock_io!
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'cli/ui'
|
|
2
|
+
|
|
3
|
+
module CLI
|
|
4
|
+
module UI
|
|
5
|
+
class ProgressPlain
|
|
6
|
+
# Add a plain progress bar to the terminal output
|
|
7
|
+
#
|
|
8
|
+
# ==== Example Usage:
|
|
9
|
+
#
|
|
10
|
+
# Set the percent to X
|
|
11
|
+
# CLI::UI::ProgressPlain.progress do |bar|
|
|
12
|
+
# bar.tick(set_percent: percent)
|
|
13
|
+
# end
|
|
14
|
+
def self.progress(prefix: "")
|
|
15
|
+
bar = ProgressPlain.new(prefix: prefix)
|
|
16
|
+
yield(bar)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Initialize a plain progress bar. Typically used in a +ProgressPlain.progress+ block
|
|
20
|
+
#
|
|
21
|
+
def initialize(prefix: "")
|
|
22
|
+
@percent_done = 0
|
|
23
|
+
@prefix = prefix
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Set the progress of the bar. Typically used in a +ProgressPlain.progress+ block
|
|
27
|
+
#
|
|
28
|
+
# ==== Options
|
|
29
|
+
# * +:set_percent+ - Set progress to a specific percent
|
|
30
|
+
#
|
|
31
|
+
# *Note:* The +:set_percent must be between 0.00 and 1.0
|
|
32
|
+
#
|
|
33
|
+
def tick(set_percent: nil)
|
|
34
|
+
return if @percent_done >= 1.0 # Don't print if we're already done
|
|
35
|
+
# Print only if we've moved up a whole 10% (e.g. 10%, 20%, 30%)q
|
|
36
|
+
return if (@percent_done * 100).floor != 0 && ((@percent_done * 100).floor / 10 == (set_percent * 100).floor / 10)
|
|
37
|
+
@percent_done = set_percent
|
|
38
|
+
@percent_done = [@percent_done, 1.0].min # Make sure we can't go above 1.0
|
|
39
|
+
|
|
40
|
+
print("#{to_s}\n")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Format the progress bar to be printed to terminal
|
|
44
|
+
#
|
|
45
|
+
def to_s
|
|
46
|
+
"#{@prefix} #{(@percent_done * 100).floor.to_s.rjust(5)}%"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
module CLI
|
|
2
2
|
module UI
|
|
3
|
-
autoload :ANSI,
|
|
4
|
-
autoload :Glyph,
|
|
5
|
-
autoload :Color,
|
|
6
|
-
autoload :Frame,
|
|
7
|
-
autoload :OS,
|
|
8
|
-
autoload :Printer,
|
|
9
|
-
autoload :Progress,
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
12
|
-
autoload :
|
|
13
|
-
autoload :
|
|
14
|
-
autoload :
|
|
15
|
-
autoload :
|
|
16
|
-
autoload :
|
|
3
|
+
autoload :ANSI, 'cli/ui/ansi'
|
|
4
|
+
autoload :Glyph, 'cli/ui/glyph'
|
|
5
|
+
autoload :Color, 'cli/ui/color'
|
|
6
|
+
autoload :Frame, 'cli/ui/frame'
|
|
7
|
+
autoload :OS, 'cli/ui/os'
|
|
8
|
+
autoload :Printer, 'cli/ui/printer'
|
|
9
|
+
autoload :Progress, 'cli/ui/progress'
|
|
10
|
+
autoload :ProgressPlain, 'cli/ui/progress_plain'
|
|
11
|
+
autoload :Prompt, 'cli/ui/prompt'
|
|
12
|
+
autoload :Terminal, 'cli/ui/terminal'
|
|
13
|
+
autoload :Truncater, 'cli/ui/truncater'
|
|
14
|
+
autoload :Formatter, 'cli/ui/formatter'
|
|
15
|
+
autoload :Spinner, 'cli/ui/spinner'
|
|
16
|
+
autoload :Widgets, 'cli/ui/widgets'
|
|
17
|
+
autoload :Wrap, 'cli/ui/wrap'
|
|
17
18
|
|
|
18
19
|
# Convenience accessor to +CLI::UI::Spinner::SpinGroup+
|
|
19
20
|
SpinGroup = Spinner::SpinGroup
|
|
@@ -3,21 +3,13 @@ import { stringifyMessage, outputContent, outputToken, outputDebug } from '../..
|
|
|
3
3
|
import { AbortError } from '../../../public/node/error.js';
|
|
4
4
|
import { debugLogResponseInfo } from '../api.js';
|
|
5
5
|
import { ClientError, GraphQLClient } from 'graphql-request';
|
|
6
|
-
export function graphqlRequest(query, api, url, token, variables, handleErrors = true) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return response.data;
|
|
14
|
-
};
|
|
15
|
-
if (handleErrors) {
|
|
16
|
-
return handlingErrors(api, action);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
return action();
|
|
20
|
-
}
|
|
6
|
+
export async function graphqlRequest(query, api, url, token, variables, handleErrors = true) {
|
|
7
|
+
const headers = buildHeaders(token);
|
|
8
|
+
debugLogRequestInfo(api, query, variables, headers);
|
|
9
|
+
const clientOptions = { agent: await httpsAgent(), headers };
|
|
10
|
+
const client = new GraphQLClient(url, clientOptions);
|
|
11
|
+
const response = await debugLogResponseInfo({ request: client.rawRequest(query, variables), url }, handleErrors ? errorHandler(api) : undefined);
|
|
12
|
+
return response.data;
|
|
21
13
|
}
|
|
22
14
|
function debugLogRequestInfo(api, query, variables, headers = {}) {
|
|
23
15
|
outputDebug(outputContent `Sending ${outputToken.json(api)} GraphQL request:
|
|
@@ -27,11 +19,8 @@ With request headers:
|
|
|
27
19
|
${sanitizedHeadersOutput(headers)}
|
|
28
20
|
`);
|
|
29
21
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return await action();
|
|
33
|
-
}
|
|
34
|
-
catch (error) {
|
|
22
|
+
function errorHandler(api) {
|
|
23
|
+
return (error) => {
|
|
35
24
|
if (error instanceof ClientError) {
|
|
36
25
|
const errorMessage = stringifyMessage(outputContent `
|
|
37
26
|
The ${outputToken.raw(api)} GraphQL API responded unsuccessfully with the HTTP status ${`${error.response.status}`} and errors:
|
|
@@ -46,11 +35,11 @@ async function handlingErrors(api, action) {
|
|
|
46
35
|
mappedError = new AbortError(errorMessage);
|
|
47
36
|
}
|
|
48
37
|
mappedError.stack = error.stack;
|
|
49
|
-
|
|
38
|
+
return mappedError;
|
|
50
39
|
}
|
|
51
40
|
else {
|
|
52
|
-
|
|
41
|
+
return error;
|
|
53
42
|
}
|
|
54
|
-
}
|
|
43
|
+
};
|
|
55
44
|
}
|
|
56
45
|
//# sourceMappingURL=graphql.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../../src/private/node/api/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,sBAAsB,EAAC,MAAM,cAAc,CAAA;AACjG,OAAO,EAAC,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,gCAAgC,CAAA;AACxG,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,EAAC,oBAAoB,EAAC,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAC,WAAW,EAAE,aAAa,EAA6B,MAAM,iBAAiB,CAAA;AAOtF,MAAM,UAAU,cAAc,
|
|
1
|
+
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../../src/private/node/api/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,sBAAsB,EAAC,MAAM,cAAc,CAAA;AACjG,OAAO,EAAC,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,gCAAgC,CAAA;AACxG,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,EAAC,oBAAoB,EAAC,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAC,WAAW,EAAE,aAAa,EAA6B,MAAM,iBAAiB,CAAA;AAOtF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAsB,EACtB,GAAW,EACX,GAAW,EACX,KAAa,EACb,SAAqB,EACrB,YAAY,GAAG,IAAI;IAEnB,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IACnC,mBAAmB,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IACnD,MAAM,aAAa,GAAG,EAAC,KAAK,EAAE,MAAM,UAAU,EAAE,EAAE,OAAO,EAAC,CAAA;IAC1D,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IACpD,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CACzC,EAAC,OAAO,EAAE,MAAM,CAAC,UAAU,CAAI,KAAe,EAAE,SAAS,CAAC,EAAE,GAAG,EAAC,EAChE,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAC7C,CAAA;IACD,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC;AAED,SAAS,mBAAmB,CAC1B,GAAW,EACX,KAAsB,EACtB,SAAqB,EACrB,UAAmC,EAAE;IAErC,WAAW,CAAC,aAAa,CAAA,WAAW,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;IACvD,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;EAC1C,SAAS,CAAC,CAAC,CAAC,sBAAsB,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;;EAE7E,sBAAsB,CAAC,OAAO,CAAC;CAChC,CAAC,CAAA;AACF,CAAC;AAED,SAAS,YAAY,CAAI,GAAW;IAClC,OAAO,CAAC,KAAc,EAAE,EAAE;QACxB,IAAI,KAAK,YAAY,WAAW,EAAE;YAChC,MAAM,YAAY,GAAG,gBAAgB,CAAC,aAAa,CAAA;QACjD,WAAW,CAAC,GAAG,CACnB,GAAG,CACJ,8DAA8D,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE;;IAEvF,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;OACpC,CAAC,CAAA;YACF,IAAI,WAAkB,CAAA;YACtB,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;gBAC/B,WAAW,GAAG,IAAI,kBAAkB,CAAC,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;aAC1E;iBAAM;gBACL,WAAW,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,CAAA;aAC3C;YACD,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;YAC/B,OAAO,WAAW,CAAA;SACnB;aAAM;YACL,OAAO,KAAK,CAAA;SACb;IACH,CAAC,CAAA;AACH,CAAC","sourcesContent":["import {buildHeaders, httpsAgent, RequestClientError, sanitizedHeadersOutput} from './headers.js'\nimport {stringifyMessage, outputContent, outputToken, outputDebug} from '../../../public/node/output.js'\nimport {AbortError} from '../../../public/node/error.js'\nimport {debugLogResponseInfo} from '../api.js'\nimport {ClientError, GraphQLClient, RequestDocument, Variables} from 'graphql-request'\n\nexport interface GraphQLVariables {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any\n}\n\nexport async function graphqlRequest<T>(\n query: RequestDocument,\n api: string,\n url: string,\n token: string,\n variables?: Variables,\n handleErrors = true,\n): Promise<T> {\n const headers = buildHeaders(token)\n debugLogRequestInfo(api, query, variables, headers)\n const clientOptions = {agent: await httpsAgent(), headers}\n const client = new GraphQLClient(url, clientOptions)\n const response = await debugLogResponseInfo(\n {request: client.rawRequest<T>(query as string, variables), url},\n handleErrors ? errorHandler(api) : undefined,\n )\n return response.data\n}\n\nfunction debugLogRequestInfo<T>(\n api: string,\n query: RequestDocument,\n variables?: Variables,\n headers: {[key: string]: string} = {},\n) {\n outputDebug(outputContent`Sending ${outputToken.json(api)} GraphQL request:\n ${outputToken.raw(query.toString().trim())}\n${variables ? `\\nWith variables:\\n${JSON.stringify(variables, null, 2)}\\n` : ''}\nWith request headers:\n${sanitizedHeadersOutput(headers)}\n`)\n}\n\nfunction errorHandler<T>(api: string): (error: unknown) => Error | unknown {\n return (error: unknown) => {\n if (error instanceof ClientError) {\n const errorMessage = stringifyMessage(outputContent`\n The ${outputToken.raw(\n api,\n )} GraphQL API responded unsuccessfully with the HTTP status ${`${error.response.status}`} and errors:\n\n ${outputToken.json(error.response.errors)}\n `)\n let mappedError: Error\n if (error.response.status < 500) {\n mappedError = new RequestClientError(errorMessage, error.response.status)\n } else {\n mappedError = new AbortError(errorMessage)\n }\n mappedError.stack = error.stack\n return mappedError\n } else {\n return error\n }\n }\n}\n"]}
|
|
@@ -7,5 +7,5 @@ interface RequestOptions<T> {
|
|
|
7
7
|
export declare function debugLogResponseInfo<T extends {
|
|
8
8
|
headers: Headers;
|
|
9
9
|
status: number;
|
|
10
|
-
}>({ request, url
|
|
10
|
+
}>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown) => Error | unknown): Promise<T>;
|
|
11
11
|
export {};
|
package/dist/private/node/api.js
CHANGED
|
@@ -1,21 +1,40 @@
|
|
|
1
1
|
import { sanitizedHeadersOutput } from './api/headers.js';
|
|
2
2
|
import { outputDebug } from '@shopify/cli-kit/node/output';
|
|
3
|
+
import { ClientError } from 'graphql-request';
|
|
3
4
|
import { performance } from 'perf_hooks';
|
|
4
5
|
export const allAPIs = ['admin', 'storefront-renderer', 'partners'];
|
|
5
6
|
const interestingResponseHeaders = new Set(['cache-control', 'content-type', 'etag', 'x-request-id']);
|
|
6
|
-
export async function debugLogResponseInfo({ request, url,
|
|
7
|
+
export async function debugLogResponseInfo({ request, url }, errorHandler) {
|
|
7
8
|
const t0 = performance.now();
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
let headers = new Headers();
|
|
10
|
+
let response = {};
|
|
11
|
+
try {
|
|
12
|
+
response = await request;
|
|
13
|
+
headers = response.headers;
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err instanceof ClientError) {
|
|
17
|
+
headers = err.response?.headers;
|
|
18
|
+
}
|
|
19
|
+
if (errorHandler) {
|
|
20
|
+
throw errorHandler(err);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
const t1 = performance.now();
|
|
28
|
+
const responseHeaders = {};
|
|
29
|
+
headers.forEach((value, key) => {
|
|
30
|
+
if (interestingResponseHeaders.has(key))
|
|
31
|
+
responseHeaders[key] = value;
|
|
32
|
+
});
|
|
33
|
+
outputDebug(`Request to ${url} completed in ${Math.round(t1 - t0)} ms
|
|
16
34
|
With response headers:
|
|
17
35
|
${sanitizedHeadersOutput(responseHeaders)}
|
|
18
36
|
`);
|
|
37
|
+
}
|
|
19
38
|
return response;
|
|
20
39
|
}
|
|
21
40
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAA;AACxD,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAA;AAItC,MAAM,CAAC,MAAM,OAAO,GAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,UAAU,CAAC,CAAA;AAO1E,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;AAErG,MAAM,CAAC,KAAK,UAAU,oBAAoB,
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAA;AACxD,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAA;AAItC,MAAM,CAAC,MAAM,OAAO,GAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,UAAU,CAAC,CAAA;AAO1E,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;AAErG,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAC,OAAO,EAAE,GAAG,EAAoB,EACjC,YAAkD;IAElD,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;IAC5B,IAAI,OAAO,GAAY,IAAI,OAAO,EAAE,CAAA;IACpC,IAAI,QAAQ,GAAM,EAAO,CAAA;IACzB,IAAI;QACF,QAAQ,GAAG,MAAM,OAAO,CAAA;QACxB,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAA;KAC3B;IAAC,OAAO,GAAG,EAAE;QACZ,IAAI,GAAG,YAAY,WAAW,EAAE;YAC9B,OAAO,GAAG,GAAG,CAAC,QAAQ,EAAE,OAAkB,CAAA;SAC3C;QACD,IAAI,YAAY,EAAE;YAChB,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;SACxB;aAAM;YACL,MAAM,GAAG,CAAA;SACV;KACF;YAAS;QACR,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QAC5B,MAAM,eAAe,GAA4B,EAAE,CAAA;QACnD,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YAC7B,IAAI,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACvE,CAAC,CAAC,CAAA;QACF,WAAW,CAAC,cAAc,GAAG,iBAAiB,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;;EAEnE,sBAAsB,CAAC,eAAe,CAAC;KACpC,CAAC,CAAA;KACH;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {outputDebug} from '@shopify/cli-kit/node/output'\nimport {ClientError} from 'graphql-request'\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners']\n\ninterface RequestOptions<T> {\n request: Promise<T>\n url: string\n}\n\nconst interestingResponseHeaders = new Set(['cache-control', 'content-type', 'etag', 'x-request-id'])\n\nexport async function debugLogResponseInfo<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown) => Error | unknown,\n): Promise<T> {\n const t0 = performance.now()\n let headers: Headers = new Headers()\n let response: T = {} as T\n try {\n response = await request\n headers = response.headers\n } catch (err) {\n if (err instanceof ClientError) {\n headers = err.response?.headers as Headers\n }\n if (errorHandler) {\n throw errorHandler(err)\n } else {\n throw err\n }\n } finally {\n const t1 = performance.now()\n const responseHeaders: {[key: string]: string} = {}\n headers.forEach((value, key) => {\n if (interestingResponseHeaders.has(key)) responseHeaders[key] = value\n })\n outputDebug(`Request to ${url} completed in ${Math.round(t1 - t0)} ms\nWith response headers:\n${sanitizedHeadersOutput(responseHeaders)}\n `)\n }\n return response\n}\n"]}
|
|
@@ -22,7 +22,6 @@ export const environmentVariables = {
|
|
|
22
22
|
unitTest: 'SHOPIFY_UNIT_TEST',
|
|
23
23
|
verbose: 'SHOPIFY_FLAG_VERBOSE',
|
|
24
24
|
themeBundling: 'SHOPIFY_CLI_THEME_BUNDLING',
|
|
25
|
-
javascriptFunctions: 'SHOPIFY_CLI_FUNCTIONS_JAVASCRIPT',
|
|
26
25
|
// Variables to detect if the CLI is running in a cloud environment
|
|
27
26
|
codespaceName: 'CODESPACE_NAME',
|
|
28
27
|
codespaces: 'CODESPACES',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAA;AAClD,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,EAAE,kCAAkC;IACtD,UAAU,EAAE,yBAAyB;IACrC,iBAAiB,EAAE,iCAAiC;IACpD,GAAG,EAAE,iBAAiB;IACtB,aAAa,EAAE,oBAAoB;IACnC,WAAW,EAAE,0BAA0B;IACvC,aAAa,EAAE,4BAA4B;IAC3C,SAAS,EAAE,qBAAqB;IAChC,UAAU,EAAE,qBAAqB;IACjC,eAAe,EAAE,+BAA+B;IAChD,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,yBAAyB;IACrC,QAAQ,EAAE,mBAAmB;IAC7B,OAAO,EAAE,sBAAsB;IAC/B,aAAa,EAAE,4BAA4B;IAC3C,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAA;AAClD,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,EAAE,kCAAkC;IACtD,UAAU,EAAE,yBAAyB;IACrC,iBAAiB,EAAE,iCAAiC;IACpD,GAAG,EAAE,iBAAiB;IACtB,aAAa,EAAE,oBAAoB;IACnC,WAAW,EAAE,0BAA0B;IACvC,aAAa,EAAE,4BAA4B;IAC3C,SAAS,EAAE,qBAAqB;IAChC,UAAU,EAAE,qBAAqB;IACjC,eAAe,EAAE,+BAA+B;IAChD,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,yBAAyB;IACrC,QAAQ,EAAE,mBAAmB;IAC7B,OAAO,EAAE,sBAAsB;IAC/B,aAAa,EAAE,4BAA4B;IAC3C,mEAAmE;IACnE,aAAa,EAAE,gBAAgB;IAC/B,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,sBAAsB;IAC9B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,eAAe;CAC7B,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW,EAAE;QACX,GAAG,EAAE,kBAAkB;KACxB;IACD,WAAW,EAAE;QACX,KAAK,EAAE;YACL,IAAI,EAAE,GAAG,EAAE;gBACT,OAAO,WAAW,EAAE,CAAA;YACtB,CAAC;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,GAAG,EAAE;oBACT,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAA;gBAC1C,CAAC;gBACD,QAAQ,EAAE,GAAG,EAAE;oBACb,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;gBACtD,CAAC;aACF;SACF;KACF;CACF,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,OAAO,EAAE,aAAa;CACvB,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,6BAA6B,EAAE,CAAC;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,kCAAkC,CAAA","sourcesContent":["import {joinPath} from '../../public/node/path.js'\nimport envPaths from 'env-paths'\n\nconst identifier = 'shopify-cli'\n\nconst cacheFolder = () => {\n if (process.env.XDG_CACHE_HOME) return process.env.XDG_CACHE_HOME\n return envPaths(identifier).cache\n}\n\nexport const environmentVariables = {\n alwaysLogAnalytics: 'SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS',\n deviceAuth: 'SHOPIFY_CLI_DEVICE_AUTH',\n enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',\n env: 'SHOPIFY_CLI_ENV',\n firstPartyDev: 'SHOPIFY_CLI_1P_DEV',\n noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',\n partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',\n runAsUser: 'SHOPIFY_RUN_AS_USER',\n serviceEnv: 'SHOPIFY_SERVICE_ENV',\n skipCliRedirect: 'SHOPIFY_CLI_SKIP_CLI_REDIRECT',\n spinInstance: 'SPIN_INSTANCE',\n themeToken: 'SHOPIFY_CLI_THEME_TOKEN',\n unitTest: 'SHOPIFY_UNIT_TEST',\n verbose: 'SHOPIFY_FLAG_VERBOSE',\n themeBundling: 'SHOPIFY_CLI_THEME_BUNDLING',\n // Variables to detect if the CLI is running in a cloud environment\n codespaceName: 'CODESPACE_NAME',\n codespaces: 'CODESPACES',\n gitpod: 'GITPOD_WORKSPACE_URL',\n spin: 'SPIN',\n spinAppPort: 'SERVER_PORT',\n spinAppHost: 'SPIN_APP_HOST',\n}\n\nexport const pathConstants = {\n executables: {\n dev: '/opt/dev/bin/dev',\n },\n directories: {\n cache: {\n path: () => {\n return cacheFolder()\n },\n vendor: {\n path: () => {\n return joinPath(cacheFolder(), 'vendor')\n },\n binaries: () => {\n return joinPath(cacheFolder(), 'vendor', 'binaries')\n },\n },\n },\n },\n}\n\nexport const keychainConstants = {\n service: 'shopify-cli',\n}\n\nexport const sessionConstants = {\n expirationTimeMarginInMinutes: 4,\n}\n\nexport const bugsnagApiKey = '9e1e6889176fd0c795d5c659225e0fae'\n"]}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
1
2
|
import { render } from 'ink-testing-library';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
export declare class Stdin extends EventEmitter {
|
|
5
|
+
isTTY: boolean;
|
|
6
|
+
write: (data: string) => void;
|
|
7
|
+
setEncoding(): void;
|
|
8
|
+
setRawMode(): void;
|
|
9
|
+
resume(): void;
|
|
10
|
+
pause(): void;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* Wait for the component to be ready to accept input.
|
|
4
14
|
*/
|
|
@@ -7,6 +17,7 @@ export declare function waitForInputsToBeReady(): Promise<unknown>;
|
|
|
7
17
|
* Wait for the last frame to change to anything.
|
|
8
18
|
*/
|
|
9
19
|
export declare function waitForChange(func: () => void, getChangingValue: () => string | number | undefined): Promise<void>;
|
|
20
|
+
export declare function waitFor(func: () => void, condition: () => boolean): Promise<void>;
|
|
10
21
|
/**
|
|
11
22
|
* Wait for the last frame to contain specific text.
|
|
12
23
|
*/
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
import { isTruthy } from '../context/utilities.js';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export class Stdin extends EventEmitter {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.isTTY = true;
|
|
7
|
+
this.write = (data) => {
|
|
8
|
+
this.emit('data', data);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
setEncoding() { }
|
|
12
|
+
setRawMode() { }
|
|
13
|
+
resume() { }
|
|
14
|
+
pause() { }
|
|
15
|
+
}
|
|
2
16
|
/**
|
|
3
17
|
* Wait for the component to be ready to accept input.
|
|
4
18
|
*/
|
|
@@ -20,7 +34,7 @@ export function waitForChange(func, getChangingValue) {
|
|
|
20
34
|
}, 10);
|
|
21
35
|
});
|
|
22
36
|
}
|
|
23
|
-
function waitFor(func, condition) {
|
|
37
|
+
export function waitFor(func, condition) {
|
|
24
38
|
return new Promise((resolve) => {
|
|
25
39
|
func();
|
|
26
40
|
const interval = setInterval(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../../src/private/node/testing/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../../src/private/node/testing/ui.ts"],"names":[],"mappings":"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","sourcesContent":["import {isTruthy} from '../context/utilities.js'\nimport {render} from 'ink-testing-library'\nimport {EventEmitter} from 'events'\n\nexport class Stdin extends EventEmitter {\n isTTY = true\n\n write = (data: string) => {\n this.emit('data', data)\n }\n\n setEncoding() {}\n\n setRawMode() {}\n\n resume() {}\n\n pause() {}\n}\n\n/**\n * Wait for the component to be ready to accept input.\n */\nexport function waitForInputsToBeReady() {\n return new Promise((resolve) => setTimeout(resolve, 100))\n}\n\n/**\n * Wait for the last frame to change to anything.\n */\nexport function waitForChange(func: () => void, getChangingValue: () => string | number | undefined) {\n return new Promise<void>((resolve) => {\n const initialValue = getChangingValue()\n\n func()\n\n const interval = setInterval(() => {\n if (getChangingValue() !== initialValue) {\n clearInterval(interval)\n resolve()\n }\n }, 10)\n })\n}\n\nexport function waitFor(func: () => void, condition: () => boolean) {\n return new Promise<void>((resolve) => {\n func()\n\n const interval = setInterval(() => {\n if (condition()) {\n clearInterval(interval)\n resolve()\n }\n }, 10)\n })\n}\n\n/**\n * Wait for the last frame to contain specific text.\n */\nexport function waitForContent(\n renderInstance: ReturnType<typeof render>,\n content: string,\n func: () => void = () => {},\n) {\n return waitFor(\n () => func(),\n () => renderInstance.lastFrame()!.includes(content),\n )\n}\n\n/**\n * Send input and wait for the last frame to change.\n *\n * Useful when you want to send some input and wait for anything to change in the interface.\n * If you need to wait for a specific change instead, you can use sendInputAndWaitForContent.\n */\nexport async function sendInputAndWaitForChange(renderInstance: ReturnType<typeof render>, ...inputs: string[]) {\n await waitForChange(() => inputs.forEach((input) => renderInstance.stdin.write(input)), renderInstance.lastFrame)\n // wait for another tick so we give time to react to update caches\n await new Promise((resolve) => setTimeout(resolve, 0))\n}\n\n/** Send input and wait a number of milliseconds.\n *\n * Useful if you know some what will happen after input will take a certain amount of time\n * and it will not cause any visible change so you can't use sendInputAndWaitForChange.\n * This function can also be used if you want to test that nothing changes after some input has been sent.\n */\nexport async function sendInputAndWait(\n renderInstance: ReturnType<typeof render>,\n waitTime: number,\n ...inputs: string[]\n) {\n inputs.forEach((input) => renderInstance.stdin.write(input))\n await new Promise((resolve) => setTimeout(resolve, waitTime))\n}\n\n/**\n * Send input and wait for the last frame to contain specific text.\n *\n * Useful when you want to send some input and wait for a specific change to happen.\n * If you need to wait for any change instead, you can use sendInputAndWaitForChange.\n */\nexport async function sendInputAndWaitForContent(\n renderInstance: ReturnType<typeof render>,\n content: string,\n ...inputs: string[]\n) {\n await waitForContent(renderInstance, content, () => inputs.forEach((input) => renderInstance.stdin.write(input)))\n}\n\n/** Function that is useful when you want to check the last frame of a component that unmounted.\n *\n * The reason this function exists is that in CI Ink will clear the last frame on unmount.\n */\nexport function getLastFrameAfterUnmount(renderInstance: ReturnType<typeof render>) {\n return isTruthy(process.env.CI) ? renderInstance.frames[renderInstance.frames.length - 2] : renderInstance.lastFrame()\n}\n"]}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { AlertProps } from './components/Alert.js';
|
|
2
|
-
|
|
2
|
+
import { RenderOptions } from 'ink';
|
|
3
|
+
export interface AlertOptions extends AlertProps {
|
|
4
|
+
renderOptions?: RenderOptions;
|
|
5
|
+
}
|
|
6
|
+
export declare function alert({ type, headline, body, nextSteps, reference, link, customSections, orderedNextSteps, renderOptions, }: AlertOptions): string | undefined;
|
|
@@ -12,7 +12,7 @@ const typeToLogger = {
|
|
|
12
12
|
warning: consoleWarn,
|
|
13
13
|
success: consoleLog,
|
|
14
14
|
};
|
|
15
|
-
export function alert({ type, headline, body, nextSteps, reference, link, customSections, orderedNextSteps = false, }) {
|
|
16
|
-
renderOnce(React.createElement(Alert, { type: type, headline: headline, body: body, nextSteps: nextSteps, reference: reference, link: link, orderedNextSteps: orderedNextSteps, customSections: customSections }), typeToLogLevel[type], typeToLogger[type]);
|
|
15
|
+
export function alert({ type, headline, body, nextSteps, reference, link, customSections, orderedNextSteps = false, renderOptions, }) {
|
|
16
|
+
return renderOnce(React.createElement(Alert, { type: type, headline: headline, body: body, nextSteps: nextSteps, reference: reference, link: link, orderedNextSteps: orderedNextSteps, customSections: customSections }), { logLevel: typeToLogLevel[type], logger: typeToLogger[type], renderOptions });
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=alert.js.map
|