shopify-cli 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +13 -13
  4. data/lib/docgen/markdown.rb +1 -1
  5. data/lib/graphql/fetch_specifications.graphql +14 -0
  6. data/lib/project_types/extension/cli.rb +0 -10
  7. data/lib/project_types/extension/commands/create.rb +2 -2
  8. data/lib/project_types/extension/commands/extension_command.rb +6 -2
  9. data/lib/project_types/extension/commands/register.rb +2 -2
  10. data/lib/project_types/extension/commands/serve.rb +9 -1
  11. data/lib/project_types/extension/extension_project.rb +4 -0
  12. data/lib/project_types/extension/forms/questions/ask_type.rb +16 -5
  13. data/lib/project_types/extension/messages/messages.rb +4 -2
  14. data/lib/project_types/extension/models/specification.rb +4 -2
  15. data/lib/project_types/extension/models/specification_handlers/default.rb +1 -1
  16. data/lib/project_types/extension/models/specifications.rb +12 -1
  17. data/lib/project_types/extension/tasks/configure_features.rb +1 -1
  18. data/lib/project_types/extension/tasks/fetch_specifications.rb +8 -28
  19. data/lib/project_types/node/forms/create.rb +10 -1
  20. data/lib/project_types/node/messages/messages.rb +1 -0
  21. data/lib/project_types/rails/forms/create.rb +11 -1
  22. data/lib/project_types/rails/messages/messages.rb +1 -0
  23. data/lib/project_types/script/config/extension_points.yml +13 -0
  24. data/lib/project_types/script/layers/application/create_script.rb +10 -6
  25. data/lib/project_types/script/layers/domain/extension_point.rb +6 -1
  26. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +29 -3
  27. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +1 -36
  28. data/lib/project_types/script/layers/infrastructure/errors.rb +0 -9
  29. data/lib/project_types/script/layers/infrastructure/script_service.rb +4 -4
  30. data/lib/project_types/script/messages/messages.rb +0 -3
  31. data/lib/project_types/script/ui/error_handler.rb +0 -11
  32. data/lib/shopify-cli/tasks/ensure_dev_store.rb +1 -1
  33. data/lib/shopify-cli/transform_data_structure.rb +1 -1
  34. data/lib/shopify-cli/version.rb +1 -1
  35. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 810ed674eed1f0938f1e4fdb55703fe8bcbcf10d13293a27f7e59f28cc39d384
4
- data.tar.gz: 0f7572e8d715e589bbe3cc23d6835e6256063a54b99504f3f6975b5008a0ed24
3
+ metadata.gz: 30e766112b0e09d6de0e907ecf7e002377fe8a0ecb6776bf0975ec1677a5858a
4
+ data.tar.gz: 3fbcc004481a0b06c8ccfcd0fb5890d7ab4bf6ee778a6b4dc43c773508376a05
5
5
  SHA512:
6
- metadata.gz: 7681161d8502e8e728bac04b339b06d84334b1ec0edfc8a58c3f8eb5d4a85ba873c79810c63d30e784508cb9b155c3f39d672e88689b53fc0dd5cff32be865ff
7
- data.tar.gz: ac283b1b16d617b27c2f61dc948e77adead2910f218c0649783884ee6debc6c4135c18dccf35bf73931ded907dadab0ba9c70598238874d941107fa471970041
6
+ metadata.gz: d3b9f2da8984619e58cb73a5a066bd67b7b0e3f050a82f794b36079d3f0850d8c57e4e346e7f6ae0c0ea01601d07e26d54359cced3e132d23246ad88bbed314f
7
+ data.tar.gz: 1ec7d262e39e6b112cf25a35b85788faeb77fce56febdeb46e0f8630608ca19ec0eb032b668302515e23fbfa0831ad25492439cc8cb35e5fb376c6e2277e4596
data/CHANGELOG.md CHANGED
@@ -1,12 +1,18 @@
1
1
  Unreleased
2
2
  ------
3
3
 
4
+ Version 1.8.0
5
+ -------------
6
+
7
+ * [1119](https://github.com/Shopify/shopify-app-cli/pull/1119): Enable guest serialization for scripts
8
+
4
9
  Version 1.7.1
5
10
  ------
6
11
  * Updating internal features in development
7
12
 
8
13
  Version 1.7.0
9
14
  -----
15
+ * [#1109](https://github.com/Shopify/shopify-app-cli/pull/1109): Abort app generation if name contains disallowed text.
10
16
  * [#1075](https://github.com/Shopify/shopify-app-cli/pull/1075): Add support for kebab-case flags
11
17
 
12
18
  Version 1.6.0
data/Gemfile.lock CHANGED
@@ -4,7 +4,7 @@ GEM
4
4
  addressable (2.7.0)
5
5
  public_suffix (>= 2.0.2, < 5.0)
6
6
  ansi (1.5.0)
7
- ast (2.4.1)
7
+ ast (2.4.2)
8
8
  builder (3.2.4)
9
9
  byebug (11.1.3)
10
10
  coderay (1.1.3)
@@ -22,7 +22,7 @@ GEM
22
22
  ruby-progressbar
23
23
  mocha (1.11.2)
24
24
  parallel (1.20.1)
25
- parser (2.7.2.0)
25
+ parser (3.0.0.0)
26
26
  ast (~> 2.4.1)
27
27
  pry (0.13.1)
28
28
  coderay (~> 1.1)
@@ -33,26 +33,26 @@ GEM
33
33
  public_suffix (4.0.6)
34
34
  rainbow (3.0.0)
35
35
  rake (13.0.1)
36
- regexp_parser (1.8.2)
36
+ regexp_parser (2.1.1)
37
37
  rexml (3.2.4)
38
- rubocop (1.4.1)
38
+ rubocop (1.11.0)
39
39
  parallel (~> 1.10)
40
- parser (>= 2.7.1.5)
40
+ parser (>= 3.0.0.0)
41
41
  rainbow (>= 2.2.2, < 4.0)
42
- regexp_parser (>= 1.8)
42
+ regexp_parser (>= 1.8, < 3.0)
43
43
  rexml
44
- rubocop-ast (>= 1.1.1)
44
+ rubocop-ast (>= 1.2.0, < 2.0)
45
45
  ruby-progressbar (~> 1.7)
46
- unicode-display_width (>= 1.4.0, < 2.0)
47
- rubocop-ast (1.1.1)
46
+ unicode-display_width (>= 1.4.0, < 3.0)
47
+ rubocop-ast (1.4.1)
48
48
  parser (>= 2.7.1.5)
49
49
  rubocop-minitest (0.10.1)
50
50
  rubocop (>= 0.87)
51
- rubocop-shopify (1.0.7)
52
- rubocop (~> 1.4)
53
- ruby-progressbar (1.10.1)
51
+ rubocop-shopify (2.0.1)
52
+ rubocop (~> 1.11)
53
+ ruby-progressbar (1.11.0)
54
54
  timecop (0.9.2)
55
- unicode-display_width (1.7.0)
55
+ unicode-display_width (2.0.0)
56
56
  webmock (3.9.3)
57
57
  addressable (>= 2.3.6)
58
58
  crack (>= 0.3.2)
@@ -89,7 +89,7 @@ module RDoc
89
89
  lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment
90
90
  lines.each do |line|
91
91
  next unless line =~ /^ *(?=\S)/
92
- n = $&.length
92
+ n = Regexp.last_match(0).length
93
93
  indent = n if n < indent
94
94
  break if n == 0
95
95
  end
@@ -0,0 +1,14 @@
1
+ query fetchSpecifications($api_key: String!) {
2
+ extensionSpecifications(apiKey: $api_key) {
3
+ name
4
+ identifier
5
+ options {
6
+ managementExperience
7
+ }
8
+ features {
9
+ argo {
10
+ surface
11
+ }
12
+ }
13
+ }
14
+ }
@@ -81,14 +81,4 @@ module Extension
81
81
 
82
82
  autoload :ExtensionProjectKeys, Project.project_filepath("extension_project_keys")
83
83
  autoload :ExtensionProject, Project.project_filepath("extension_project")
84
-
85
- def self.specifications
86
- @specifications ||= Models::Specifications.new(
87
- fetch_specifications: Tasks::FetchSpecifications
88
- )
89
- end
90
-
91
- def self.specifications=(specifications)
92
- @specifications = specifications
93
- end
94
84
  end
@@ -38,8 +38,8 @@ module Extension
38
38
  Usage: {{command:#{ShopifyCli::TOOL_NAME} create extension}}
39
39
  Options:
40
40
  {{command:--type=TYPE}} The type of extension you would like to create.
41
- {{command:--name=NAME}} The name of your extension (50 characters).”
42
- {{command:--api-key=KEY}} The API key of your app.”
41
+ {{command:--name=NAME}} The name of your extension (50 characters).
42
+ {{command:--api-key=KEY}} The API key of your app.
43
43
  HELP
44
44
  end
45
45
 
@@ -12,11 +12,15 @@ module Extension
12
12
  @extension_type ||= begin
13
13
  identifier = project.extension_type_identifier
14
14
  Models::LazySpecificationHandler.new(identifier) do
15
- unless Extension.specifications.valid?(identifier)
15
+ specifications = Models::Specifications.new(
16
+ fetch_specifications: Tasks::FetchSpecifications.new(api_key: project.app.api_key, context: @ctx)
17
+ )
18
+
19
+ unless specifications.valid?(identifier)
16
20
  @ctx.abort(@ctx.message("errors.unknown_type", project.extension_type_identifier))
17
21
  end
18
22
 
19
- Extension.specifications[identifier]
23
+ specifications[identifier]
20
24
  end
21
25
  end
22
26
  end
@@ -12,7 +12,7 @@ module Extension
12
12
 
13
13
  update_project_files(registration)
14
14
 
15
- @ctx.puts(@ctx.message("register.success", project.title, app.title))
15
+ @ctx.puts(@ctx.message("register.success", project.title))
16
16
  @ctx.puts(@ctx.message("register.success_info"))
17
17
  end
18
18
  end
@@ -28,7 +28,7 @@ module Extension
28
28
 
29
29
  def confirm_registration
30
30
  @ctx.puts(@ctx.message("register.confirm_info", extension_type.name))
31
- CLI::UI::Prompt.confirm(@ctx.message("register.confirm_question", app.title))
31
+ CLI::UI::Prompt.confirm(@ctx.message("register.confirm_question"))
32
32
  end
33
33
 
34
34
  def register_extension
@@ -10,6 +10,7 @@ module Extension
10
10
  if argo_admin?
11
11
  ShopifyCli::Tasks::EnsureEnv.call(@ctx, required: [:api_key, :secret, :shop])
12
12
  ShopifyCli::Tasks::EnsureDevStore.call(@ctx)
13
+ validate_env
13
14
  end
14
15
 
15
16
  CLI::UI::Frame.open(@ctx.message("serve.frame_title")) do
@@ -37,7 +38,14 @@ module Extension
37
38
  def argo_admin?
38
39
  ShopifyCli::Shopifolk.check &&
39
40
  ShopifyCli::Feature.enabled?(:argo_admin_beta) &&
40
- extension_type.specification.features&.argo&.surface_area == "admin"
41
+ extension_type.specification.features&.argo&.surface == "admin"
42
+ end
43
+
44
+ def validate_env
45
+ ExtensionProject.reload
46
+ @ctx.abort(@ctx.message("serve.serve_missing_information")) if
47
+ project.env.shop.nil? || project.env.api_key.nil? ||
48
+ project.env.shop.strip.empty? || project.env.api_key.strip.empty?
41
49
  end
42
50
  end
43
51
  end
@@ -23,6 +23,10 @@ module Extension
23
23
  }.compact
24
24
  ).write(context)
25
25
 
26
+ reload
27
+ end
28
+
29
+ def reload
26
30
  current.reload unless project_empty?
27
31
  end
28
32
 
@@ -11,25 +11,36 @@ module Extension
11
11
  default: -> { CLI::UI::Prompt.method(:ask) }
12
12
 
13
13
  def call(project_details)
14
+ specifications = Models::Specifications.new(
15
+ fetch_specifications: Tasks::FetchSpecifications.new(context: ctx, api_key: project_details.app.api_key)
16
+ )
17
+
14
18
  project_details.tap do |p|
15
- p.type = type.nil? ? choose_type : validate_given_type(type)
19
+ p.type = type.nil? ? choose_type(specifications) : validate_given_type(specifications, type)
16
20
  end
17
21
  end
18
22
 
19
23
  private
20
24
 
21
- def validate_given_type(type)
22
- return Extension.specifications[type] if Extension.specifications.valid?(type)
25
+ def validate_given_type(specifications, type)
26
+ return specifications[type] if specifications.valid?(type)
23
27
  ctx.abort(ctx.message("create.invalid_type")) unless type.nil?
24
28
  end
25
29
 
26
- def choose_type
30
+ def choose_type(specifications)
31
+ abort_due_to_missing_specifications if specifications.none?
32
+
27
33
  prompt.call(ctx.message("create.ask_type")) do |handler|
28
- Extension.specifications.each do |type|
34
+ specifications.each do |type|
29
35
  handler.option("#{type.name} #{type.tagline}") { type }
30
36
  end
31
37
  end
32
38
  end
39
+
40
+ def abort_due_to_missing_specifications
41
+ ctx.puts(@ctx.message("create.no_available_extensions"))
42
+ raise ShopifyCli::AbortSilent
43
+ end
33
44
  end
34
45
  end
35
46
  end
@@ -30,6 +30,7 @@ module Extension
30
30
  learn_about_apps: "{{*}} Learn more about building apps at <https://shopify.dev/concepts/apps>, " \
31
31
  "or try creating a new app using {{command:shopify create}}.",
32
32
  loading_apps: "Loading your apps...",
33
+ no_available_extensions: "{{x}} There are no available extensions for this app.",
33
34
  },
34
35
  build: {
35
36
  frame_title: "Building extension with: %s...",
@@ -40,9 +41,9 @@ module Extension
40
41
  waiting_text: "Registering with Shopify...",
41
42
  already_registered: "Extension is already registered.",
42
43
  confirm_info: "This will create a new extension registration for %s, which can’t be undone.",
43
- confirm_question: "Would you like to register this extension with {{green:%s}}? (y/n)",
44
+ confirm_question: "Would you like to register this extension? (y/n)",
44
45
  confirm_abort: "Extension was not registered.",
45
- success: "{{v}} Registered {{green:%s}} with {{green:%s}}.",
46
+ success: "{{v}} Registered {{green:%s}}.",
46
47
  success_info: "{{*}} Run {{command:shopify push}} to push your extension to Shopify.",
47
48
  },
48
49
  push: {
@@ -56,6 +57,7 @@ module Extension
56
57
  serve: {
57
58
  frame_title: "Serving extension...",
58
59
  serve_failure_message: "Failed to run extension code.",
60
+ serve_missing_information: "Missing shop or api_key.",
59
61
  },
60
62
  tunnel: {
61
63
  missing_token: "{{x}} {{red:auth requires a token argument}}. "\
@@ -7,7 +7,7 @@ module Extension
7
7
  class Argo
8
8
  include SmartProperties
9
9
 
10
- property! :surface_area, converts: :to_str
10
+ property! :surface, converts: :to_str
11
11
  property! :renderer_package_name, converts: :to_str
12
12
  property! :git_template, converts: :to_str
13
13
  end
@@ -18,14 +18,16 @@ module Extension
18
18
  .call(identifier, namespace: Features)
19
19
  .rescue { OpenStruct }
20
20
  .then { |c| c.new(**feature_attributes) }
21
- .unwrap { |error| raise error }
21
+ .unwrap { |error| raise(error) }
22
22
  end
23
23
  end
24
24
  end
25
25
 
26
26
  property! :identifier
27
+ property :name, converts: :to_str
27
28
  property :graphql_identifier, converts: :to_str
28
29
  property! :features, converts: Features.method(:build), default: -> { [] }
30
+ property! :options, converts: ->(options) { OpenStruct.new(options) }, default: -> { OpenStruct.new }
29
31
 
30
32
  def graphql_identifier
31
33
  super || identifier
@@ -19,7 +19,7 @@ module Extension
19
19
  end
20
20
 
21
21
  def name
22
- message("name")
22
+ message("name") || specification.name
23
23
  end
24
24
 
25
25
  def tagline
@@ -26,6 +26,10 @@ module Extension
26
26
  handlers.values.each(&block)
27
27
  end
28
28
 
29
+ def none?
30
+ each.none?
31
+ end
32
+
29
33
  protected
30
34
 
31
35
  def handlers
@@ -37,6 +41,8 @@ module Extension
37
41
  def fetch_specifications_and_build_handlers
38
42
  ShopifyCli::Result
39
43
  .call(&fetch_specifications)
44
+ .map(&ShopifyCli::TransformDataStructure.new(symbolize_keys: true, underscore_keys: true))
45
+ .then(&method(:select_cli_extensions))
40
46
  .then(&Tasks::ConfigureFeatures)
41
47
  .then(&method(:ensure_legacy_compatibility))
42
48
  .then(&method(:build_specifications))
@@ -64,7 +70,8 @@ module Extension
64
70
 
65
71
  def ensure_legacy_compatibility(specification_attribute_sets)
66
72
  specification_attribute_sets.each do |attributes|
67
- next unless attributes.fetch(:identifier) == "product_subscription"
73
+ next unless attributes.fetch(:identifier) == "subscription_management"
74
+ attributes[:identifier] = "product_subscription"
68
75
  attributes[:graphql_identifier] = "SUBSCRIPTION_MANAGEMENT"
69
76
  end
70
77
  end
@@ -72,6 +79,10 @@ module Extension
72
79
  def build_specifications(specification_attribute_sets)
73
80
  specification_attribute_sets.map { |attributes| Models::Specification.new(**attributes) }
74
81
  end
82
+
83
+ def select_cli_extensions(specification_attribute_sets)
84
+ specification_attribute_sets.select { |attributes| attributes.dig(:options, :management_experience) == "cli" }
85
+ end
75
86
  end
76
87
  end
77
88
  end
@@ -24,7 +24,7 @@ module Extension
24
24
  end
25
25
 
26
26
  def extract_surface_area(argo_configuration)
27
- argo_configuration.fetch(:surface_area) do
27
+ argo_configuration.fetch(:surface) do
28
28
  raise UnspecifiedSurfaceArea, "Argo configuration does not specify surface area"
29
29
  end
30
30
  end
@@ -3,35 +3,15 @@ module Extension
3
3
  class FetchSpecifications
4
4
  include ShopifyCli::MethodObject
5
5
 
6
- def call
7
- [
8
- product_subscription_specification,
9
- checkout_post_purchase_specification,
10
- ]
11
- end
12
-
13
- private
6
+ property :context
7
+ property :api_key
14
8
 
15
- def product_subscription_specification
16
- {
17
- identifier: "product_subscription",
18
- features: {
19
- argo: {
20
- surface_area: "admin",
21
- },
22
- },
23
- }
24
- end
25
-
26
- def checkout_post_purchase_specification
27
- {
28
- identifier: "checkout_post_purchase",
29
- features: {
30
- argo: {
31
- surface_area: "checkout",
32
- },
33
- },
34
- }
9
+ def call
10
+ response = ShopifyCli::PartnersAPI
11
+ .query(context, "fetch_specifications", api_key: api_key)
12
+ .dig("data", "extensionSpecifications")
13
+ context.abort(context.message("tasks.errors.parse_error")) if response.nil?
14
+ response
35
15
  end
36
16
  end
37
17
  end
@@ -8,8 +8,8 @@ module Node
8
8
 
9
9
  def ask
10
10
  self.title ||= CLI::UI::Prompt.ask(ctx.message("node.forms.create.app_name"))
11
+ self.name = format_name
11
12
  self.type = ask_type
12
- self.name = self.title.downcase.split(" ").join("_")
13
13
  res = ShopifyCli::Tasks::SelectOrgAndShop.call(ctx, organization_id: organization_id, shop_domain: shop_domain)
14
14
  self.organization_id = res[:organization_id]
15
15
  self.shop_domain = res[:shop_domain]
@@ -17,6 +17,15 @@ module Node
17
17
 
18
18
  private
19
19
 
20
+ def format_name
21
+ name = title.downcase.split(" ").join("_")
22
+
23
+ if name.include?("shopify")
24
+ ctx.abort(ctx.message("node.forms.create.error.invalid_app_name"))
25
+ end
26
+ name
27
+ end
28
+
20
29
  def ask_type
21
30
  if type.nil?
22
31
  return CLI::UI::Prompt.ask(ctx.message("node.forms.create.app_type.select")) do |handler|
@@ -202,6 +202,7 @@ module Node
202
202
  forms: {
203
203
  create: {
204
204
  error: {
205
+ invalid_app_name: "App name cannot contain 'Shopify'",
205
206
  invalid_app_type: "Invalid app type %s",
206
207
  },
207
208
  app_name: "App name",
@@ -20,8 +20,8 @@ module Rails
20
20
 
21
21
  def ask
22
22
  self.title ||= CLI::UI::Prompt.ask(ctx.message("rails.forms.create.app_name"))
23
+ self.name = format_name
23
24
  self.type = ask_type
24
- self.name = self.title.downcase.split(" ").join("_")
25
25
  res = ShopifyCli::Tasks::SelectOrgAndShop.call(ctx, organization_id: organization_id, shop_domain: shop_domain)
26
26
  self.organization_id = res[:organization_id]
27
27
  self.shop_domain = res[:shop_domain]
@@ -30,6 +30,16 @@ module Rails
30
30
 
31
31
  private
32
32
 
33
+ def format_name
34
+ name = title.downcase.split(" ").join("_")
35
+
36
+ if name.include?("shopify")
37
+ ctx.abort(ctx.message("rails.forms.create.error.invalid_app_name"))
38
+ end
39
+
40
+ name
41
+ end
42
+
33
43
  def ask_type
34
44
  if type.nil?
35
45
  return CLI::UI::Prompt.ask(ctx.message("rails.forms.create.app_type.select")) do |handler|
@@ -257,6 +257,7 @@ module Rails
257
257
  forms: {
258
258
  create: {
259
259
  error: {
260
+ invalid_app_name: "App name cannot contain 'Shopify'",
260
261
  invalid_app_type: "Invalid app type %s",
261
262
  invalid_db_type: "Invalid database type %s",
262
263
  },
@@ -27,3 +27,16 @@ tax_filter:
27
27
  package: "@shopify/extension-point-as-tax-filter"
28
28
  sdk-version: "^9.0.0"
29
29
  toolchain-version: "^5.0.0"
30
+ payment_methods:
31
+ domain: 'checkout'
32
+ assemblyscript:
33
+ package: "@shopify/scripts-checkout-apis"
34
+ toolchain-version: "^5.0.0"
35
+ sdk-version: "^9.0.0"
36
+ shipping_methods:
37
+ domain: 'checkout'
38
+ assemblyscript:
39
+ package: "@shopify/scripts-checkout-apis"
40
+ sdk-version: "^9.0.0"
41
+ toolchain-version: "^5.0.0"
42
+
@@ -27,11 +27,6 @@ module Script
27
27
  private
28
28
 
29
29
  DEFAULT_CONFIG_UI_FILENAME = "config-ui.yml"
30
- DEFAULT_CONFIG = {
31
- "version" => 1,
32
- "type" => "single",
33
- "fields" => [],
34
- }
35
30
 
36
31
  def setup_project(ctx:, language:, script_name:, extension_point:, description:, no_config_ui:)
37
32
  ScriptProject.create(ctx, script_name)
@@ -48,7 +43,7 @@ module Script
48
43
  identifiers.merge!(config_ui_file: DEFAULT_CONFIG_UI_FILENAME)
49
44
  Infrastructure::ConfigUiRepository
50
45
  .new(ctx: ctx)
51
- .create_config_ui(DEFAULT_CONFIG_UI_FILENAME, YAML.dump(DEFAULT_CONFIG))
46
+ .create_config_ui(DEFAULT_CONFIG_UI_FILENAME, default_config_ui_content(script_name))
52
47
  end
53
48
 
54
49
  ScriptProject.write(
@@ -72,6 +67,15 @@ module Script
72
67
  spinner.update_title(ctx.message("script.create.created"))
73
68
  end
74
69
  end
70
+
71
+ def default_config_ui_content(title)
72
+ YAML.dump({
73
+ "version" => 1,
74
+ "type" => "single",
75
+ "title" => title,
76
+ "fields" => [],
77
+ })
78
+ end
75
79
  end
76
80
  end
77
81
  end
@@ -4,17 +4,22 @@ module Script
4
4
  module Layers
5
5
  module Domain
6
6
  class ExtensionPoint
7
- attr_reader :type, :deprecated, :sdks
7
+ attr_reader :type, :deprecated, :sdks, :domain
8
8
 
9
9
  def initialize(type, config)
10
10
  @type = type
11
11
  @deprecated = config["deprecated"] || false
12
+ @domain = config["domain"] || nil
12
13
  @sdks = ExtensionPointSDKs.new(config)
13
14
  end
14
15
 
15
16
  def deprecated?
16
17
  @deprecated
17
18
  end
19
+
20
+ def dasherize_type
21
+ @type.gsub("_", "-")
22
+ end
18
23
  end
19
24
 
20
25
  class ExtensionPointSDKs
@@ -11,7 +11,10 @@ module Script
11
11
  property! :path_to_project, accepts: String
12
12
 
13
13
  BOOTSTRAP = "npx --no-install shopify-scripts-toolchain-as bootstrap --from %{extension_point} --dest %{base}"
14
+ BUILD = "shopify-scripts-toolchain-as build --src src/shopify_main.ts " \
15
+ "--binary build/%{script_name}.wasm --metadata build/metadata.json"
14
16
  MIN_NODE_VERSION = "14.5.0"
17
+ ASC_ARGS = "-- --lib node_modules --optimize --use Date="
15
18
 
16
19
  def setup_dependencies
17
20
  write_npmrc
@@ -19,8 +22,7 @@ module Script
19
22
  end
20
23
 
21
24
  def bootstrap
22
- type = extension_point.type.gsub("_", "-")
23
- out, status = ctx.capture2e(format(BOOTSTRAP, extension_point: type, base: path_to_project))
25
+ out, status = ctx.capture2e(bootstap_command)
24
26
  raise Domain::Errors::ServiceFailureError, out unless status.success?
25
27
  end
26
28
 
@@ -55,7 +57,7 @@ module Script
55
57
  },
56
58
  "scripts": {
57
59
  "test": "asp --summary --verbose",
58
- "build": "shopify-scripts-toolchain-as build --src src/shopify_main.ts --binary build/#{script_name}.wasm --metadata build/metadata.json -- --lib node_modules --optimize --use Date="
60
+ "build": "#{build_command}"
59
61
  },
60
62
  "engines": {
61
63
  "node": ">=#{MIN_NODE_VERSION}"
@@ -64,6 +66,30 @@ module Script
64
66
  HERE
65
67
  ctx.write("package.json", package_json)
66
68
  end
69
+
70
+ def bootstap_command
71
+ type = extension_point.dasherize_type
72
+ base_command = format(BOOTSTRAP, extension_point: type, base: path_to_project)
73
+ domain = extension_point.domain
74
+
75
+ if domain.nil?
76
+ base_command
77
+ else
78
+ "#{base_command} --domain #{domain}"
79
+ end
80
+ end
81
+
82
+ def build_command
83
+ type = extension_point.dasherize_type
84
+ base_command = format(BUILD, script_name: script_name)
85
+ domain = extension_point.domain
86
+
87
+ if domain.nil?
88
+ "#{base_command} #{ASC_ARGS}"
89
+ else
90
+ "#{base_command} --domain #{domain} --ep #{type} #{ASC_ARGS}"
91
+ end
92
+ end
67
93
  end
68
94
  end
69
95
  end
@@ -33,9 +33,7 @@ module Script
33
33
 
34
34
  def dependencies_installed?
35
35
  # Assuming if node_modules folder exist at root of script folder, all deps are installed
36
- return false unless ctx.dir_exist?("node_modules")
37
- check_if_ep_dependencies_up_to_date!
38
- true
36
+ ctx.dir_exist?("node_modules")
39
37
  end
40
38
 
41
39
  def metadata
@@ -91,39 +89,6 @@ module Script
91
89
 
92
90
  contents
93
91
  end
94
-
95
- def check_if_ep_dependencies_up_to_date!
96
- return true if ENV["SHOPIFY_CLI_SCRIPTS_IGNORE_OUTDATED"]
97
-
98
- # ignore exit code since it will not be 0 unless every package is up to date which they probably won't be
99
- out, _ = ctx.capture2e("npm", "outdated", "--json", "--depth", "0")
100
- parsed_outdated_check = JSON.parse(out)
101
- outdated_ep_packages = parsed_outdated_check
102
- .select { |package_name, _| package_name.start_with?("@shopify/extension-point-as-") }
103
- .select { |_, version_info| !package_is_up_to_date?(version_info) }
104
- .keys
105
- raise Errors::PackagesOutdatedError.new(outdated_ep_packages),
106
- "NPM packages out of date: #{outdated_ep_packages.join(", ")}" unless outdated_ep_packages.empty?
107
- end
108
-
109
- def package_is_up_to_date?(version_info)
110
- require "semantic/semantic"
111
- current_version = version_info["current"]
112
- latest_version = version_info["latest"]
113
-
114
- # making an assumption that the script developer knows what they're doing if they're not referencing a
115
- # semver version
116
- begin
117
- current_version = ::Semantic::Version.new(current_version)
118
- latest_version = ::Semantic::Version.new(latest_version)
119
- rescue ArgumentError
120
- return true
121
- end
122
-
123
- return false if current_version.major < latest_version.major
124
- return false if latest_version.major == 0 && current_version.minor < latest_version.minor
125
- true
126
- end
127
92
  end
128
93
  end
129
94
  end
@@ -60,15 +60,6 @@ module Script
60
60
  class ShopScriptConflictError < ScriptProjectError; end
61
61
  class ShopScriptUndefinedError < ScriptProjectError; end
62
62
  class TaskRunnerNotFoundError < ScriptProjectError; end
63
-
64
- class PackagesOutdatedError < ScriptProjectError
65
- attr_reader :outdated_packages
66
- def initialize(outdated_packages)
67
- super("EP packages are outdated and need to be updated: #{outdated_packages.join(", ")}")
68
- @outdated_packages = outdated_packages
69
- end
70
- end
71
-
72
63
  class BuildScriptNotFoundError < ScriptProjectError; end
73
64
  class InvalidBuildScriptError < ScriptProjectError; end
74
65
 
@@ -26,7 +26,7 @@ module Script
26
26
  extensionPointName: extension_point_type.upcase,
27
27
  title: script_name,
28
28
  description: description,
29
- configUi: config_ui.content,
29
+ configUi: config_ui&.content,
30
30
  sourceCode: Base64.encode64(script_content),
31
31
  language: compiled_type,
32
32
  force: force,
@@ -42,11 +42,11 @@ module Script
42
42
  if user_errors.any? { |e| e["tag"] == "already_exists_error" }
43
43
  raise Errors::ScriptRepushError, api_key
44
44
  elsif (e = user_errors.any? { |err| err["tag"] == "config_ui_syntax_error" })
45
- raise Errors::ConfigUiSyntaxError, config_ui.filename
45
+ raise Errors::ConfigUiSyntaxError, config_ui&.filename
46
46
  elsif (e = user_errors.find { |err| err["tag"] == "config_ui_missing_keys_error" })
47
- raise Errors::ConfigUiMissingKeysError.new(config_ui.filename, e["message"])
47
+ raise Errors::ConfigUiMissingKeysError.new(config_ui&.filename, e["message"])
48
48
  elsif (e = user_errors.find { |err| err["tag"] == "config_ui_fields_missing_keys_error" })
49
- raise Errors::ConfigUiFieldsMissingKeysError.new(config_ui.filename, e["message"])
49
+ raise Errors::ConfigUiFieldsMissingKeysError.new(config_ui&.filename, e["message"])
50
50
  else
51
51
  raise Errors::ScriptServiceUserError.new(query_name, user_errors.to_s)
52
52
  end
@@ -122,9 +122,6 @@ module Script
122
122
 
123
123
  shop_script_undefined_cause: "Script is already turned off in store.",
124
124
 
125
- packages_outdated_cause: "These npm packages are out of date: %s.",
126
- packages_outdated_help: "To update them, run {{cyan:npm install --save-dev %s}}.",
127
-
128
125
  invalid_build_script: "The root package.json contains an invalid build command that " \
129
126
  "is needed to compile your script to WebAssembly.",
130
127
  build_script_not_found: "The root package.json is missing the build command that " \
@@ -220,17 +220,6 @@ module Script
220
220
  {
221
221
  cause_of_error: ShopifyCli::Context.message("script.error.shop_script_undefined_cause"),
222
222
  }
223
- when Layers::Infrastructure::Errors::PackagesOutdatedError
224
- {
225
- cause_of_error: ShopifyCli::Context.message(
226
- "script.error.packages_outdated_cause",
227
- e.outdated_packages.join(", ")
228
- ),
229
- help_suggestion: ShopifyCli::Context.message(
230
- "script.error.packages_outdated_help",
231
- e.outdated_packages.collect { |package| "#{package}@latest" }.join(" ")
232
- ),
233
- }
234
223
  when Layers::Infrastructure::Errors::BuildScriptNotFoundError
235
224
  {
236
225
  cause_of_error: ShopifyCli::Context.message("script.error.build_script_not_found"),
@@ -5,7 +5,7 @@ module ShopifyCli
5
5
  class EnsureDevStore < ShopifyCli::Task
6
6
  def call(ctx)
7
7
  @ctx = ctx
8
- return ctx.puts(ctx.message(
8
+ return ctx.abort(ctx.message(
9
9
  "core.tasks.ensure_dev_store.could_not_verify_store", project.env.shop
10
10
  )) if shop.nil?
11
11
  return if shop["transferDisabled"] == true
@@ -68,7 +68,7 @@ module ShopifyCli
68
68
  def underscore_key(key)
69
69
  return key unless underscore_keys? && key.respond_to?(:to_str)
70
70
 
71
- key.to_str.dup.yield_self do |k|
71
+ key.to_str.dup.tap do |k|
72
72
  k.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
73
73
  k.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
74
74
  k.tr!("-", "_")
@@ -1,3 +1,3 @@
1
1
  module ShopifyCli
2
- VERSION = "1.7.1"
2
+ VERSION = "1.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-16 00:00:00.000000000 Z
11
+ date: 2021-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -126,6 +126,7 @@ files:
126
126
  - lib/graphql/create_product.graphql
127
127
  - lib/graphql/extension_create.graphql
128
128
  - lib/graphql/extension_update_draft.graphql
129
+ - lib/graphql/fetch_specifications.graphql
129
130
  - lib/graphql/find_organization.graphql
130
131
  - lib/graphql/get_app_by_api_key.graphql
131
132
  - lib/graphql/get_app_urls.graphql