shopify-cli 1.2.0 → 1.5.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +2 -2
  3. data/.github/CONTRIBUTING.md +9 -1
  4. data/.github/PULL_REQUEST_TEMPLATE.md +9 -1
  5. data/.github/workflows/release.yml +61 -0
  6. data/.github/workflows/triage.yml +22 -0
  7. data/.gitignore +0 -1
  8. data/.rubocop.yml +61 -8
  9. data/.rubocop_todo.yml +11 -0
  10. data/CHANGELOG.md +25 -0
  11. data/Gemfile +3 -2
  12. data/Gemfile.lock +39 -37
  13. data/RELEASING.md +19 -29
  14. data/docs/core/index.md +16 -0
  15. data/lib/project_types/extension/cli.rb +7 -2
  16. data/lib/project_types/extension/commands/register.rb +1 -1
  17. data/lib/project_types/extension/features/argo/admin.rb +20 -0
  18. data/lib/project_types/extension/features/argo/base.rb +129 -0
  19. data/lib/project_types/extension/features/argo/checkout.rb +20 -0
  20. data/lib/project_types/extension/messages/messages.rb +8 -2
  21. data/lib/project_types/extension/models/type.rb +4 -0
  22. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +2 -2
  23. data/lib/project_types/extension/models/types/product_subscription.rb +24 -0
  24. data/lib/project_types/node/cli.rb +4 -1
  25. data/lib/project_types/node/commands/connect.rb +15 -0
  26. data/lib/project_types/node/commands/create.rb +8 -4
  27. data/lib/project_types/node/messages/messages.rb +7 -6
  28. data/lib/project_types/rails/cli.rb +4 -1
  29. data/lib/project_types/rails/commands/connect.rb +15 -0
  30. data/lib/project_types/rails/commands/create.rb +8 -4
  31. data/lib/project_types/rails/messages/messages.rb +7 -4
  32. data/lib/project_types/script/cli.rb +2 -1
  33. data/lib/project_types/script/commands/enable.rb +12 -4
  34. data/lib/project_types/script/config/extension_points.yml +13 -12
  35. data/lib/project_types/script/errors.rb +4 -0
  36. data/lib/project_types/script/layers/application/build_script.rb +12 -16
  37. data/lib/project_types/script/layers/domain/errors.rb +3 -0
  38. data/lib/project_types/script/layers/domain/extension_point.rb +0 -1
  39. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +15 -50
  40. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +28 -7
  41. data/lib/project_types/script/layers/infrastructure/errors.rb +16 -0
  42. data/lib/project_types/script/layers/infrastructure/script_repository.rb +0 -12
  43. data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -0
  44. data/lib/project_types/script/messages/messages.rb +23 -5
  45. data/lib/project_types/script/ui/error_handler.rb +31 -6
  46. data/lib/shopify-cli/api.rb +8 -10
  47. data/lib/shopify-cli/commands/config.rb +57 -1
  48. data/lib/shopify-cli/commands/connect.rb +32 -15
  49. data/lib/shopify-cli/commands/system.rb +9 -0
  50. data/lib/shopify-cli/core/entry_point.rb +1 -1
  51. data/lib/shopify-cli/core/monorail.rb +6 -4
  52. data/lib/shopify-cli/http_request.rb +15 -0
  53. data/lib/shopify-cli/js_deps.rb +1 -1
  54. data/lib/shopify-cli/js_system.rb +22 -5
  55. data/lib/shopify-cli/messages/messages.rb +44 -9
  56. data/lib/shopify-cli/partners_api.rb +17 -1
  57. data/lib/shopify-cli/process_supervision.rb +1 -1
  58. data/lib/shopify-cli/project.rb +12 -8
  59. data/lib/shopify-cli/project_type.rb +17 -1
  60. data/lib/shopify-cli/shopifolk.rb +86 -0
  61. data/lib/shopify-cli/task.rb +8 -0
  62. data/lib/shopify-cli/tasks/create_api_client.rb +13 -2
  63. data/lib/shopify-cli/tasks/ensure_env.rb +3 -0
  64. data/lib/shopify-cli/tasks/select_org_and_shop.rb +4 -0
  65. data/lib/shopify-cli/tunnel.rb +1 -1
  66. data/lib/shopify-cli/version.rb +1 -1
  67. data/lib/shopify_cli.rb +1 -0
  68. metadata +13 -5
  69. data/lib/project_types/extension/features/argo.rb +0 -48
  70. data/lib/project_types/extension/models/types/subscription_management.rb +0 -20
  71. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +0 -38
@@ -68,3 +68,19 @@ Log out of the currently authenticated partner organization and store. The `logo
68
68
  $ shopify logout
69
69
  ```
70
70
 
71
+ ## `config`
72
+
73
+ Configure Shopify App CLI options. Currently there are two available options.
74
+
75
+ ### `analytics`
76
+
77
+ Configure anonymous usage reporting by enabling or disabling analytics
78
+ ```console
79
+ $ shopify config analytics [ --status | --enable | --disable ]
80
+ ```
81
+
82
+ ### `feature`
83
+ Configure active [feature sets](https://github.com/Shopify/shopify-app-cli/wiki/Feature-Sets) in the CLI. This command is used for development and debugging work on the CLI tool itself. Only alter it if you know what you're doing. Check the [Shopify App CLI development guide](https://github.com/Shopify/shopify-app-cli/wiki) for more information.
84
+ ```console
85
+ $ shopify config feature [ feature_name ] [ --status | --enable | --disable ]
86
+ ```
@@ -3,7 +3,8 @@
3
3
  module Extension
4
4
  class Project < ShopifyCli::ProjectType
5
5
  hidden_feature
6
- creator 'App Extension', 'Extension::Commands::Create'
6
+ title('App Extension')
7
+ creator('Extension::Commands::Create')
7
8
 
8
9
  register_command('Extension::Commands::Build', "build")
9
10
  register_command('Extension::Commands::Register', "register")
@@ -48,12 +49,16 @@ module Extension
48
49
  end
49
50
 
50
51
  module Features
51
- autoload :Argo, Project.project_filepath('features/argo')
52
52
  autoload :ArgoSetup, Project.project_filepath('features/argo_setup')
53
53
  autoload :ArgoSetupStep, Project.project_filepath('features/argo_setup_step')
54
54
  autoload :ArgoSetupSteps, Project.project_filepath('features/argo_setup_steps')
55
55
  autoload :ArgoDependencies, Project.project_filepath('features/argo_dependencies')
56
56
  autoload :ArgoConfig, Project.project_filepath('features/argo_config')
57
+ module Argo
58
+ autoload :Base, Project.project_filepath('features/argo/base')
59
+ autoload :Admin, Project.project_filepath('features/argo/admin')
60
+ autoload :Checkout, Project.project_filepath('features/argo/checkout')
61
+ end
57
62
  end
58
63
 
59
64
  module Models
@@ -52,7 +52,7 @@ module Extension
52
52
  Tasks::CreateExtension.call(
53
53
  context: @ctx,
54
54
  api_key: app.api_key,
55
- type: extension_type.identifier,
55
+ type: extension_type.graphql_identifier,
56
56
  title: project.title,
57
57
  config: {},
58
58
  extension_context: extension_type.extension_context(@ctx)
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Extension
3
+ module Features
4
+ module Argo
5
+ class Admin < Base
6
+ GIT_TEMPLATE = 'https://github.com/Shopify/argo-admin-template.git'
7
+ RENDERER_PACKAGE = '@shopify/argo-admin'
8
+ private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE
9
+
10
+ def git_template
11
+ GIT_TEMPLATE
12
+ end
13
+
14
+ def renderer_package_name
15
+ RENDERER_PACKAGE
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ require 'base64'
3
+ require 'shopify_cli'
4
+ require 'semantic/semantic'
5
+
6
+ module Extension
7
+ module Features
8
+ module Argo
9
+ class Base
10
+ include SmartProperties
11
+
12
+ SCRIPT_PATH = %w(build main.js).freeze
13
+
14
+ NPM_LIST_COMMAND = %w(list).freeze
15
+ YARN_LIST_COMMAND = %w(list --pattern).freeze
16
+ NPM_LIST_PARAMETERS = %w(--prod).freeze
17
+ YARN_LIST_PARAMETERS = %w(--production).freeze
18
+ private_constant :NPM_LIST_COMMAND, :YARN_LIST_COMMAND, :NPM_LIST_PARAMETERS, :YARN_LIST_PARAMETERS
19
+
20
+ YARN_INSTALL_COMMAND = %w(install).freeze
21
+ YARN_INSTALL_PARAMETERS = %w(--silent).freeze
22
+ YARN_RUN_COMMAND = %w(run).freeze
23
+ YARN_RUN_SCRIPT_NAME = %w(build).freeze
24
+ private_constant :YARN_INSTALL_COMMAND, :YARN_INSTALL_PARAMETERS, :YARN_RUN_COMMAND, :YARN_RUN_SCRIPT_NAME
25
+
26
+ def create(directory_name, identifier, context)
27
+ Features::ArgoSetup.new(git_template: git_template).call(directory_name, identifier, context)
28
+ end
29
+
30
+ def config(context)
31
+ js_system = ShopifyCli::JsSystem.new(ctx: context)
32
+ if js_system.package_manager == 'yarn'
33
+ run_yarn_install(context, js_system)
34
+ run_yarn_run_script(context, js_system)
35
+ end
36
+ filepath = File.join(context.root, SCRIPT_PATH)
37
+ context.abort(context.message('features.argo.missing_file_error')) unless File.exist?(filepath)
38
+ begin
39
+ {
40
+ renderer_version: extract_argo_renderer_version(context),
41
+ serialized_script: Base64.strict_encode64(File.read(filepath).chomp),
42
+ }
43
+ rescue StandardError
44
+ context.abort(context.message('features.argo.script_prepare_error'))
45
+ end
46
+ end
47
+
48
+ def git_template
49
+ raise NotImplementedError, "'#{__method__}' must be implemented for #{self.class}"
50
+ end
51
+
52
+ def renderer_package_name
53
+ # The renderer_package_name is used as a regex pattern to
54
+ # find a match in the output of yarn or npm list command.
55
+ # Use the full package name as it appears in the template without targeting a version.
56
+ # Examples: "@shopify/some-renderer-package", "argo-renderer-package"
57
+
58
+ raise NotImplementedError, "'#{__method__}' must be implemented for #{self.class}"
59
+ end
60
+
61
+ private
62
+
63
+ def extract_argo_renderer_version(context)
64
+ result = run_list_command(context)
65
+ found_version = find_version_number(context, result)
66
+ context.abort(
67
+ context.message('features.argo.dependencies.argo_renderer_package_invalid_version_error')
68
+ ) if found_version.nil?
69
+ ::Semantic::Version.new(found_version).to_s
70
+ rescue ArgumentError
71
+ context.abort(
72
+ context.message('features.argo.dependencies.argo_renderer_package_invalid_version_error')
73
+ )
74
+ end
75
+
76
+ def find_version_number(context, result)
77
+ packages = result.to_json.split('\n')
78
+ found_package = packages.find do |package|
79
+ package.match(/#{renderer_package_name}@/)
80
+ end
81
+ if found_package.nil?
82
+ error = "'#{renderer_package_name}' not found."
83
+ context.abort(
84
+ context.message('features.argo.dependencies.argo_missing_renderer_package_error', error)
85
+ )
86
+ end
87
+ found_package.split('@')[2]&.strip
88
+ end
89
+
90
+ def run_list_command(context)
91
+ js_system = ShopifyCli::JsSystem.new(ctx: context)
92
+ result, error, status = js_system.call(
93
+ yarn: YARN_LIST_COMMAND + [renderer_package_name] + YARN_LIST_PARAMETERS,
94
+ npm: NPM_LIST_COMMAND + [renderer_package_name] + NPM_LIST_PARAMETERS,
95
+ capture_response: true
96
+ )
97
+ context.abort(
98
+ context.message('features.argo.dependencies.argo_missing_renderer_package_error', error)
99
+ ) unless status.success?
100
+ result
101
+ end
102
+
103
+ def run_yarn_install(context, js_system)
104
+ _result, error, status = js_system.call(
105
+ yarn: YARN_INSTALL_COMMAND + YARN_INSTALL_PARAMETERS,
106
+ npm: [],
107
+ capture_response: true
108
+ )
109
+
110
+ context.abort(
111
+ context.message('features.argo.dependencies.yarn_install_error', error)
112
+ ) unless status.success?
113
+ end
114
+
115
+ def run_yarn_run_script(context, js_system)
116
+ _result, error, status = js_system.call(
117
+ yarn: YARN_RUN_COMMAND + YARN_RUN_SCRIPT_NAME,
118
+ npm: [],
119
+ capture_response: true
120
+ )
121
+
122
+ context.abort(
123
+ context.message('features.argo.dependencies.yarn_run_script_error', error)
124
+ ) unless status.success?
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Extension
3
+ module Features
4
+ module Argo
5
+ class Checkout < Base
6
+ GIT_TEMPLATE = 'https://github.com/Shopify/argo-checkout-template.git'
7
+ RENDERER_PACKAGE = '@shopify/argo-checkout'
8
+ private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE
9
+
10
+ def git_template
11
+ GIT_TEMPLATE
12
+ end
13
+
14
+ def renderer_package_name
15
+ RENDERER_PACKAGE
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -95,6 +95,12 @@ module Extension
95
95
  node_not_installed: 'Node must be installed to create this extension.',
96
96
  version_too_low: 'Your node version %s does not meet the minimum required version %s',
97
97
  },
98
+ argo_missing_renderer_package_error: '%s Install the missing package and try again.',
99
+ argo_renderer_package_invalid_version_error: <<~MESSAGE,
100
+ The renderer package version is not a valid SemVer Version (http://semver.org)
101
+ MESSAGE
102
+ yarn_install_error: "Something went wrong while running 'yarn install'. %s.",
103
+ yarn_run_script_error: 'Something went wrong while running script. %s.',
98
104
  },
99
105
  config: {
100
106
  unpermitted_keys: '`%s` contains the following unpermitted keys: %s',
@@ -112,8 +118,8 @@ module Extension
112
118
  }
113
119
 
114
120
  TYPES = {
115
- subscription_management: {
116
- name: 'Subscription Management',
121
+ product_subscription: {
122
+ name: 'Product Subscription',
117
123
  tagline: '(limit 1 per app)',
118
124
  overrides: {
119
125
  register: {
@@ -38,6 +38,10 @@ module Extension
38
38
  self.class::IDENTIFIER
39
39
  end
40
40
 
41
+ def graphql_identifier
42
+ identifier
43
+ end
44
+
41
45
  def name
42
46
  message('name')
43
47
  end
@@ -8,13 +8,13 @@ module Extension
8
8
  IDENTIFIER = 'CHECKOUT_POST_PURCHASE'
9
9
  PERMITTED_CONFIG_KEYS = [:metafields]
10
10
  def create(directory_name, context)
11
- Features::Argo.checkout.create(directory_name, IDENTIFIER, context)
11
+ Features::Argo::Checkout.new.create(directory_name, IDENTIFIER, context)
12
12
  end
13
13
 
14
14
  def config(context)
15
15
  {
16
16
  **Features::ArgoConfig.parse_yaml(context, PERMITTED_CONFIG_KEYS),
17
- **Features::Argo.checkout.config(context),
17
+ **Features::Argo::Checkout.new.config(context),
18
18
  }
19
19
  end
20
20
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ require 'base64'
3
+
4
+ module Extension
5
+ module Models
6
+ module Types
7
+ class ProductSubscription < Models::Type
8
+ IDENTIFIER = 'PRODUCT_SUBSCRIPTION'
9
+
10
+ def graphql_identifier
11
+ 'SUBSCRIPTION_MANAGEMENT'
12
+ end
13
+
14
+ def create(directory_name, context)
15
+ Features::Argo::Admin.new.create(directory_name, IDENTIFIER, context)
16
+ end
17
+
18
+ def config(context)
19
+ Features::Argo::Admin.new.config(context)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  module Node
3
3
  class Project < ShopifyCli::ProjectType
4
- creator 'Node.js App', 'Node::Commands::Create'
4
+ title('Node.js App')
5
+ creator('Node::Commands::Create')
6
+ connector('Node::Commands::Connect')
5
7
 
6
8
  register_command('Node::Commands::Deploy', "deploy")
7
9
  register_command('Node::Commands::Generate', "generate")
@@ -17,6 +19,7 @@ module Node
17
19
 
18
20
  # define/autoload project specific Commands
19
21
  module Commands
22
+ autoload :Connect, Project.project_filepath('commands/connect')
20
23
  autoload :Create, Project.project_filepath('commands/create')
21
24
  autoload :Deploy, Project.project_filepath('commands/deploy')
22
25
  autoload :Generate, Project.project_filepath('commands/generate')
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Node
3
+ module Commands
4
+ class Connect < ShopifyCli::SubCommand
5
+ def call(*)
6
+ if ShopifyCli::Project.has_current? && ShopifyCli::Project.current.env
7
+ @ctx.puts(@ctx.message('node.connect.production_warning'))
8
+ end
9
+
10
+ app = ShopifyCli::Commands::Connect.new.default_connect('node')
11
+ @ctx.done(@ctx.message('node.connect.connected', app))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -40,11 +40,11 @@ module Node
40
40
  scopes: 'write_products,write_customers,write_draft_orders',
41
41
  ).write(@ctx)
42
42
 
43
- partners_url = "https://partners.shopify.com/#{form.organization_id}/apps/#{api_client['id']}"
43
+ partners_url = ShopifyCli::PartnersAPI.partners_url_for(form.organization_id, api_client['id'], local_debug?)
44
44
 
45
- @ctx.puts(@ctx.message('node.create.info.created', form.title, partners_url))
46
- @ctx.puts(@ctx.message('node.create.info.serve', form.name, ShopifyCli::TOOL_NAME))
47
- @ctx.puts(@ctx.message('node.create.info.install', partners_url, form.title))
45
+ @ctx.puts(@ctx.message('apps.create.info.created', form.title, partners_url))
46
+ @ctx.puts(@ctx.message('apps.create.info.serve', form.name, ShopifyCli::TOOL_NAME))
47
+ @ctx.puts(@ctx.message('apps.create.info.install', partners_url, form.title))
48
48
  end
49
49
 
50
50
  def self.help
@@ -112,6 +112,10 @@ module Node
112
112
  @ctx.debug(e)
113
113
  end
114
114
  end
115
+
116
+ def local_debug?
117
+ @ctx.getenv(ShopifyCli::PartnersAPI::LOCAL_DEBUG)
118
+ end
115
119
  end
116
120
  end
117
121
  end
@@ -8,6 +8,13 @@ module Node
8
8
  generic: "Error",
9
9
  },
10
10
 
11
+ connect: {
12
+ connected: "Project now connected to {{green:%s}}",
13
+ production_warning: <<~MESSAGE,
14
+ {{yellow:! Warning: if you have connected to an {{bold:app in production}}, running {{command:serve}} may update the app URL and cause an outage.
15
+ MESSAGE
16
+ },
17
+
11
18
  create: {
12
19
  help: <<~HELP,
13
20
  {{command:%s create node}}: Creates an embedded nodejs app.
@@ -26,12 +33,6 @@ module Node
26
33
  npm_version_failure: "Failed to get the current npm version. Please make sure it is installed as per " \
27
34
  "the instructions at https://www.npmjs.com/get-npm.",
28
35
  },
29
- info: {
30
- created: "{{v}} {{green:%s}} was created in your Partner Dashboard {{underline:%s}}",
31
- serve: "{{*}} Change directories to your new project folder {{green:%s}} and run {{command:%s serve}} " \
32
- "to start a local server",
33
- install: "{{*}} Then, visit {{underline:%s/test}} to install {{green:%s}} on your Dev Store",
34
- },
35
36
  node_version: "node %s",
36
37
  npm_version: "npm %s",
37
38
  },
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  module Rails
3
3
  class Project < ShopifyCli::ProjectType
4
- creator 'Ruby on Rails App', 'Rails::Commands::Create'
4
+ title('Ruby on Rails App')
5
+ creator('Rails::Commands::Create')
6
+ connector('Rails::Commands::Connect')
5
7
 
6
8
  register_command('Rails::Commands::Deploy', "deploy")
7
9
  register_command('Rails::Commands::Generate', "generate")
@@ -17,6 +19,7 @@ module Rails
17
19
 
18
20
  # define/autoload project specific Commands
19
21
  module Commands
22
+ autoload :Connect, Project.project_filepath('commands/connect')
20
23
  autoload :Create, Project.project_filepath('commands/create')
21
24
  autoload :Deploy, Project.project_filepath('commands/deploy')
22
25
  autoload :Generate, Project.project_filepath('commands/generate')
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Rails
3
+ module Commands
4
+ class Connect < ShopifyCli::SubCommand
5
+ def call(*)
6
+ if ShopifyCli::Project.has_current? && ShopifyCli::Project.current.env
7
+ @ctx.puts(@ctx.message('rails.connect.production_warning'))
8
+ end
9
+
10
+ app = ShopifyCli::Commands::Connect.new.default_connect('rails')
11
+ @ctx.done(@ctx.message('rails.connect.connected', app))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -55,11 +55,11 @@ module Rails
55
55
  scopes: 'write_products,write_customers,write_draft_orders',
56
56
  ).write(@ctx)
57
57
 
58
- partners_url = "https://partners.shopify.com/#{form.organization_id}/apps/#{api_client['id']}"
58
+ partners_url = ShopifyCli::PartnersAPI.partners_url_for(form.organization_id, api_client['id'], local_debug?)
59
59
 
60
- @ctx.puts(@ctx.message('rails.create.info.created', form.title, partners_url))
61
- @ctx.puts(@ctx.message('rails.create.info.serve', form.name, ShopifyCli::TOOL_NAME))
62
- @ctx.puts(@ctx.message('rails.create.info.install', partners_url, form.title))
60
+ @ctx.puts(@ctx.message('apps.create.info.created', form.title, partners_url))
61
+ @ctx.puts(@ctx.message('apps.create.info.serve', form.name, ShopifyCli::TOOL_NAME))
62
+ @ctx.puts(@ctx.message('apps.create.info.install', partners_url, form.title))
63
63
  end
64
64
 
65
65
  def self.help
@@ -172,6 +172,10 @@ module Rails
172
172
  def install_gem(name, version = nil)
173
173
  Gem.install(@ctx, name, version)
174
174
  end
175
+
176
+ def local_debug?
177
+ @ctx.getenv(ShopifyCli::PartnersAPI::LOCAL_DEBUG)
178
+ end
175
179
  end
176
180
  end
177
181
  end