shopify-cli 1.0.2 → 1.0.3

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/project_types/extension/cli.rb +1 -1
  4. data/lib/project_types/extension/commands/build.rb +1 -1
  5. data/lib/project_types/rails/cli.rb +0 -1
  6. data/lib/project_types/script/cli.rb +2 -3
  7. data/lib/project_types/script/commands/create.rb +4 -4
  8. data/lib/project_types/script/commands/disable.rb +4 -14
  9. data/lib/project_types/script/commands/enable.rb +35 -11
  10. data/lib/project_types/script/commands/push.rb +9 -9
  11. data/lib/project_types/script/config/extension_points.yml +9 -3
  12. data/lib/project_types/script/forms/script_form.rb +5 -2
  13. data/lib/project_types/script/layers/application/create_script.rb +7 -6
  14. data/lib/project_types/script/layers/application/disable_script.rb +9 -7
  15. data/lib/project_types/script/layers/application/enable_script.rb +11 -9
  16. data/lib/project_types/script/layers/application/push_script.rb +6 -4
  17. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +2 -2
  18. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +1 -1
  19. data/lib/project_types/script/layers/infrastructure/errors.rb +1 -0
  20. data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -0
  21. data/lib/project_types/script/messages/messages.rb +16 -19
  22. data/lib/project_types/script/script_project.rb +6 -2
  23. data/lib/project_types/script/templates/ts/as-pect.config.js +6 -0
  24. data/lib/project_types/script/ui/error_handler.rb +4 -0
  25. data/lib/project_types/script/ui/printing_spinner.rb +75 -0
  26. data/lib/shopify-cli/admin_api/schema.rb +20 -18
  27. data/lib/shopify-cli/command.rb +2 -5
  28. data/lib/shopify-cli/commands.rb +1 -0
  29. data/lib/shopify-cli/commands/config.rb +44 -0
  30. data/lib/shopify-cli/commands/connect.rb +17 -10
  31. data/lib/shopify-cli/commands/create.rb +1 -1
  32. data/lib/shopify-cli/commands/help.rb +1 -1
  33. data/lib/shopify-cli/commands/system.rb +1 -1
  34. data/lib/shopify-cli/core.rb +0 -1
  35. data/lib/shopify-cli/feature.rb +97 -0
  36. data/lib/shopify-cli/messages/messages.rb +31 -2
  37. data/lib/shopify-cli/partners_api/organizations.rb +7 -7
  38. data/lib/shopify-cli/project_type.rb +2 -5
  39. data/lib/shopify-cli/tasks/ensure_env.rb +0 -1
  40. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +4 -3
  41. data/lib/shopify-cli/tunnel.rb +33 -9
  42. data/lib/shopify-cli/version.rb +1 -1
  43. data/lib/shopify_cli.rb +1 -0
  44. metadata +5 -4
  45. data/lib/project_types/script/forms/enable.rb +0 -24
  46. data/lib/project_types/script/forms/push.rb +0 -19
@@ -19,12 +19,16 @@ module Script
19
19
  }
20
20
  end
21
21
 
22
+ def file_name
23
+ "script.#{language}"
24
+ end
25
+
22
26
  def source_file
23
27
  "#{SOURCE_DIR}/#{file_name}"
24
28
  end
25
29
 
26
- def file_name
27
- "script.#{language}"
30
+ def source_path
31
+ "#{script_name}/#{source_file}"
28
32
  end
29
33
 
30
34
  private
@@ -17,5 +17,11 @@ module.exports = {
17
17
  reportMax: false,
18
18
  reportMin: false,
19
19
  },
20
+ wasi: {
21
+ args: [],
22
+ env: process.env,
23
+ preopens: {},
24
+ returnOnExit: false,
25
+ },
20
26
  outputBinary: false,
21
27
  };
@@ -92,6 +92,10 @@ module Script
92
92
  {
93
93
  cause_of_error: ShopifyCli::Context.message('script.error.app_not_installed_cause'),
94
94
  }
95
+ when Layers::Infrastructure::Errors::AppScriptNotPushedError
96
+ {
97
+ cause_of_error: ShopifyCli::Context.message('script.error.app_script_not_pushed_help'),
98
+ }
95
99
  when Layers::Infrastructure::Errors::AppScriptUndefinedError
96
100
  {
97
101
  help_suggestion: ShopifyCli::Context.message('script.error.app_script_undefined_help'),
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Script
5
+ module UI
6
+ module PrintingSpinner
7
+ ##
8
+ # Creates a single spinner that runs the provided block.
9
+ # The block can take in a ctx argument that formats printed output to support
10
+ # printing from within the spin block.
11
+ #
12
+ # ==== Attributes
13
+ #
14
+ # * +ctx+ - The current context.
15
+ # * +title+ - Title of the spinner to use
16
+ #
17
+ # ==== Options
18
+ #
19
+ # * +:auto_debrief+ - Automatically debrief exceptions? Default to true
20
+ #
21
+ # ==== Block
22
+ #
23
+ # * +ctx+ - Instance of the PrintingSpinnerContext built from the ctx attribute.
24
+ # - +ctx.puts(...)+ formats output to enable support for printing within spinners
25
+ # * +spinner+ - Instance of the spinner. Can call +update_title+ to update the user of changes
26
+ #
27
+ def self.spin(ctx, title, auto_debrief: false)
28
+ StrictSpinner.spin(title, auto_debrief: auto_debrief) do |spinner, *args|
29
+ Thread.current[:cliui_output_hook] = nil
30
+ yield(PrintingSpinnerContext.from(ctx, spinner), spinner, *args)
31
+ end
32
+ end
33
+
34
+ ##
35
+ # Printing within spinners requires the manipulation of ANSI escape
36
+ # sequences in order to make sure the CLI::UI::Spinner does not overwrite
37
+ # previously printed content.
38
+ class PrintingSpinnerContext < ShopifyCli::Context
39
+ include SmartProperties
40
+ property :spinner, required: true
41
+
42
+ def self.from(ctx, spinner)
43
+ new_ctx = new(spinner: spinner)
44
+ ctx.instance_variables.each do |var|
45
+ new_ctx.instance_variable_set(var, ctx.instance_variable_get(var))
46
+ end
47
+ new_ctx
48
+ end
49
+
50
+ def puts(*input)
51
+ super(encoded_lines(*input) + "\n" + spinner_text)
52
+ end
53
+
54
+ private
55
+
56
+ def encoded_lines(*lines)
57
+ lines
58
+ .join("\n")
59
+ .split("\n")
60
+ .map { |line| encode_ansi(line) unless line.nil? }
61
+ .join(CLI::UI::ANSI.next_line + "\n")
62
+ end
63
+
64
+ def encode_ansi(line)
65
+ CLI::UI::ANSI.previous_line + line + CLI::UI::ANSI.clear_to_end_of_line
66
+ end
67
+
68
+ def spinner_text
69
+ spinner.render(0, true)
70
+ end
71
+ end
72
+ private_constant(:PrintingSpinnerContext)
73
+ end
74
+ end
75
+ end
@@ -3,16 +3,27 @@ require 'shopify_cli'
3
3
  module ShopifyCli
4
4
  class AdminAPI
5
5
  class Schema < Hash
6
- def self.get(ctx)
7
- unless ShopifyCli::DB.exists?(:shopify_admin_schema)
8
- shop = Project.current.env.shop || get_shop(@ctx)
9
- schema = AdminAPI.query(ctx, 'admin_introspection', shop: shop)
10
- ShopifyCli::DB.set(shopify_admin_schema: JSON.dump(schema))
6
+ class << self
7
+ def get(ctx)
8
+ unless ShopifyCli::DB.exists?(:shopify_admin_schema)
9
+ shop = Project.current.env.shop || get_shop(ctx)
10
+ schema = AdminAPI.query(ctx, 'admin_introspection', shop: shop)
11
+ ShopifyCli::DB.set(shopify_admin_schema: JSON.dump(schema))
12
+ end
13
+ # This is ruby magic for making a new hash with another hash.
14
+ # It wraps the JSON in our Schema Class to have the helper methods
15
+ # available
16
+ self[JSON.parse(ShopifyCli::DB.get(:shopify_admin_schema))]
17
+ end
18
+
19
+ private
20
+
21
+ def get_shop(ctx)
22
+ res = ShopifyCli::Tasks::SelectOrgAndShop.call(ctx)
23
+ domain = res[:shop_domain]
24
+ Project.current.env.update(ctx, :shop, domain)
25
+ domain
11
26
  end
12
- # This is ruby magic for making a new hash with another hash.
13
- # It wraps the JSON in our Schema Class to have the helper methods
14
- # available
15
- self[JSON.parse(ShopifyCli::DB.get(:shopify_admin_schema))]
16
27
  end
17
28
 
18
29
  def type(name)
@@ -28,15 +39,6 @@ module ShopifyCli
28
39
  object["name"]
29
40
  end
30
41
  end
31
-
32
- private
33
-
34
- def get_shop(ctx)
35
- res = ShopifyCli::Tasks::SelectOrgAndShop.call(ctx)
36
- domain = res[:shop_domain]
37
- Project.current.env.update(ctx, :shop, domain)
38
- domain
39
- end
40
42
  end
41
43
  end
42
44
  end
@@ -3,12 +3,13 @@ require 'shopify_cli'
3
3
 
4
4
  module ShopifyCli
5
5
  class Command < CLI::Kit::BaseCommand
6
+ extend Feature::Set
7
+
6
8
  attr_writer :ctx
7
9
  attr_accessor :options
8
10
 
9
11
  class << self
10
12
  attr_writer :ctx
11
- attr_reader :hidden
12
13
 
13
14
  def call(args, command_name)
14
15
  subcommand, resolved_name = subcommand_registry.lookup_command(args.first)
@@ -23,10 +24,6 @@ module ShopifyCli
23
24
  end
24
25
  end
25
26
 
26
- def hidden_command
27
- @hidden = true
28
- end
29
-
30
27
  def options(&block)
31
28
  @_options = block
32
29
  end
@@ -18,6 +18,7 @@ module ShopifyCli
18
18
  @core_commands.include?(cmd)
19
19
  end
20
20
 
21
+ register :Config, 'config', 'shopify-cli/commands/config', true
21
22
  register :Connect, 'connect', 'shopify-cli/commands/connect', true
22
23
  register :Create, 'create', 'shopify-cli/commands/create', true
23
24
  register :Help, 'help', 'shopify-cli/commands/help', true
@@ -0,0 +1,44 @@
1
+ require 'shopify_cli'
2
+
3
+ module ShopifyCli
4
+ module Commands
5
+ class Config < ShopifyCli::Command
6
+ hidden_feature(feature_set: :debug)
7
+
8
+ subcommand :Feature, 'feature'
9
+
10
+ def call(*)
11
+ @ctx.puts(self.class.help)
12
+ end
13
+
14
+ def self.help
15
+ ShopifyCli::Context.message('core.config.help', ShopifyCli::TOOL_NAME)
16
+ end
17
+
18
+ class Feature < ShopifyCli::SubCommand
19
+ options do |parser, flags|
20
+ parser.on('--enable') { flags[:action] = 'enable' }
21
+ parser.on('--disable') { flags[:action] = 'disable' }
22
+ parser.on('--status') { flags[:action] = 'status' }
23
+ end
24
+
25
+ def call(args, _name)
26
+ feature_name = args.shift
27
+ return @ctx.puts(@ctx.message('core.config.help', ShopifyCli::TOOL_NAME)) if feature_name.nil?
28
+ is_enabled = ShopifyCli::Feature.enabled?(feature_name)
29
+ if options.flags[:action] == 'disable' && is_enabled
30
+ ShopifyCli::Feature.disable(feature_name)
31
+ @ctx.puts(@ctx.message('core.config.feature.disabled', is_enabled))
32
+ elsif options.flags[:action] == 'enable' && !is_enabled
33
+ ShopifyCli::Feature.enable(feature_name)
34
+ @ctx.puts(@ctx.message('core.config.feature.enabled', feature_name))
35
+ elsif is_enabled
36
+ @ctx.puts(@ctx.message('core.config.feature.is_enabled', feature_name))
37
+ else
38
+ @ctx.puts(@ctx.message('core.config.feature.is_disabled', feature_name))
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -6,7 +6,7 @@ module ShopifyCli
6
6
  def call(*)
7
7
  project_type = ask_project_type unless Project.has_current?
8
8
 
9
- if Project.has_current? && Project.current
9
+ if Project.has_current? && Project.current && Project.current.env
10
10
  @ctx.puts @ctx.message('core.connect.already_connected_warning')
11
11
  prod_warning = @ctx.message('core.connect.production_warning')
12
12
  @ctx.puts prod_warning if [:rails, :node].include?(Project.current_project_type)
@@ -20,13 +20,13 @@ module ShopifyCli
20
20
 
21
21
  org = fetch_org
22
22
  id = org['id']
23
- app = get_app(org['apps'])
23
+ app = get_app(id, org['apps'])
24
24
  shop = get_shop(org['stores'], id)
25
25
 
26
26
  write_env(app, shop, env_data[:scopes], env_data[:extra])
27
27
  write_cli_yml(project_type, id) unless Project.has_current?
28
28
 
29
- @ctx.puts(@ctx.message('core.connect.connected', app.first['title']))
29
+ @ctx.puts(@ctx.message('core.connect.connected', app['title']))
30
30
  end
31
31
 
32
32
  def ask_project_type
@@ -54,15 +54,22 @@ module ShopifyCli
54
54
  org
55
55
  end
56
56
 
57
- def get_app(apps)
58
- app_id = if apps.count == 1
59
- apps.first["id"]
57
+ def get_app(org_id, apps)
58
+ if apps.count == 1
59
+ apps.first
60
+ elsif apps.count == 0
61
+ @ctx.puts(@ctx.message('core.connect.no_apps'))
62
+ title = CLI::UI::Prompt.ask(@ctx.message('core.connect.app_name'))
63
+ type = CLI::UI::Prompt.ask(@ctx.message('core.connect.app_type.select')) do |handler|
64
+ handler.option(@ctx.message('core.connect.app_type.select_public')) { 'public' }
65
+ handler.option(@ctx.message('core.connect.app_type.select_custom')) { 'custom' }
66
+ end
67
+ ShopifyCli::Tasks::CreateApiClient.call(@ctx, org_id: org_id, title: title, type: type)
60
68
  else
61
69
  CLI::UI::Prompt.ask(@ctx.message('core.connect.app_select')) do |handler|
62
- apps.each { |app| handler.option(app["title"]) { app["id"] } }
70
+ apps.each { |app| handler.option(app["title"]) { app } }
63
71
  end
64
72
  end
65
- apps.select { |app| app["id"] == app_id }
66
73
  end
67
74
 
68
75
  def get_shop(shops, id)
@@ -83,8 +90,8 @@ module ShopifyCli
83
90
  extra = {} if extra.nil?
84
91
 
85
92
  Resources::EnvFile.new(
86
- api_key: app.first["apiKey"],
87
- secret: app.first["apiSecretKeys"].first["secret"],
93
+ api_key: app["apiKey"],
94
+ secret: app["apiSecretKeys"].first["secret"],
88
95
  shop: shop,
89
96
  scopes: scopes,
90
97
  extra: extra,
@@ -28,7 +28,7 @@ module ShopifyCli
28
28
  def self.all_visible_type
29
29
  ProjectType
30
30
  .load_all
31
- .select { |type| !type.hidden }
31
+ .select { |type| !type.hidden? }
32
32
  end
33
33
 
34
34
  def self.help
@@ -47,7 +47,7 @@ module ShopifyCli
47
47
 
48
48
  def core_commands
49
49
  resolved_commands
50
- .select { |_name, c| !c.hidden }
50
+ .select { |_name, c| !c.hidden? }
51
51
  .select { |name, _c| Commands.core_command?(name) }
52
52
  end
53
53
 
@@ -4,7 +4,7 @@ require 'rbconfig'
4
4
  module ShopifyCli
5
5
  module Commands
6
6
  class System < ShopifyCli::Command
7
- hidden_command
7
+ hidden_feature(feature_set: :debug)
8
8
 
9
9
  def call(args, _name)
10
10
  show_all_details = false
@@ -4,6 +4,5 @@ module ShopifyCli
4
4
  autoload :Executor, 'shopify-cli/core/executor'
5
5
  autoload :HelpResolver, 'shopify-cli/core/help_resolver'
6
6
  autoload :Monorail, 'shopify-cli/core/monorail'
7
- autoload :Update, 'shopify-cli/core/update'
8
7
  end
9
8
  end
@@ -0,0 +1,97 @@
1
+ module ShopifyCli
2
+ ##
3
+ # ShopifyCli::Feature contains the logic to hide and show features across the CLI
4
+ # These features can be either commands or project types currently.
5
+ #
6
+ # Feature flags will persist between runs so if the flag is enabled or disabled,
7
+ # it will still be in that same state on the next cli invocation.
8
+ class Feature
9
+ SECTION = 'features'
10
+
11
+ ##
12
+ # ShopifyCli::Feature::Set is included on commands and projects to allow you to hide
13
+ # and enable projects and commands based on feature flags.
14
+ module Set
15
+ ##
16
+ # will hide a feature, either a project_type or a command
17
+ #
18
+ # #### Parameters
19
+ #
20
+ # * `feature_set` - either a single, or array of symbols that represent feature sets
21
+ #
22
+ # #### Example
23
+ #
24
+ # module ShopifyCli
25
+ # module Commands
26
+ # class Config < ShopifyCli::Command
27
+ # hidden_feature(feature_set: :basic)
28
+ # ....
29
+ #
30
+ def hidden_feature(feature_set: [])
31
+ @feature_hidden = true
32
+ @hidden_feature_set = Array(feature_set).compact
33
+ end
34
+
35
+ ##
36
+ # will return if the feature has been hidden or not
37
+ #
38
+ # #### Returns
39
+ #
40
+ # * `is_hidden` - returns true if the feature has been hidden and false otherwise
41
+ #
42
+ # #### Example
43
+ #
44
+ # ShopifyCli::Commands::Config.hidden?
45
+ #
46
+ def hidden?
47
+ enabled = (@hidden_feature_set || []).any? do |feature|
48
+ Feature.enabled?(feature)
49
+ end
50
+ @feature_hidden && !enabled
51
+ end
52
+ end
53
+
54
+ class << self
55
+ ##
56
+ # will enable a feature in the CLI.
57
+ #
58
+ # #### Parameters
59
+ #
60
+ # * `feature` - a symbol representing the flag to be enabled
61
+ def enable(feature)
62
+ set(feature, true)
63
+ end
64
+
65
+ ##
66
+ # will disable a feature in the CLI.
67
+ #
68
+ # #### Parameters
69
+ #
70
+ # * `feature` - a symbol representing the flag to be disabled
71
+ def disable(feature)
72
+ set(feature, false)
73
+ end
74
+
75
+ ##
76
+ # will check if the feature has been enabled
77
+ #
78
+ # #### Parameters
79
+ #
80
+ # * `feature` - a symbol representing a flag that the status should be requested
81
+ #
82
+ # #### Returns
83
+ #
84
+ # * `is_enabled` - will be true if the feature has been enabled.
85
+ def enabled?(feature)
86
+ return false if feature.nil?
87
+ ShopifyCli::Config.get_bool(SECTION, feature.to_s)
88
+ end
89
+
90
+ private
91
+
92
+ def set(feature, value)
93
+ ShopifyCli::Config.set(SECTION, feature.to_s, value)
94
+ end
95
+ end
96
+ end
97
+ end