shopify-cli 2.13.0 → 2.14.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +5 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +1 -1
  4. data/CHANGELOG.md +18 -0
  5. data/Gemfile.lock +6 -6
  6. data/Rakefile +16 -0
  7. data/ext/javy/hashes/javy-arm-macos-v0.2.1.gz.sha256 +1 -0
  8. data/ext/javy/hashes/javy-x86_64-linux-v0.2.1.gz.sha256 +1 -0
  9. data/ext/javy/hashes/javy-x86_64-macos-v0.2.1.gz.sha256 +1 -0
  10. data/ext/javy/hashes/javy-x86_64-windows-v0.2.1.gz.sha256 +1 -0
  11. data/ext/javy/version +1 -1
  12. data/lib/project_types/extension/models/npm_package.rb +19 -1
  13. data/lib/project_types/extension/models/server_config/development_renderer.rb +4 -3
  14. data/lib/project_types/script/cli.rb +0 -4
  15. data/lib/project_types/script/config/extension_points.yml +0 -6
  16. data/lib/project_types/script/layers/application/build_script.rb +3 -18
  17. data/lib/project_types/script/layers/application/push_script.rb +12 -10
  18. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +0 -1
  19. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +0 -1
  20. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +2 -10
  21. data/lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb +1 -1
  22. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -23
  23. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +1 -1
  24. data/lib/project_types/script/messages/messages.rb +2 -2
  25. data/lib/project_types/theme/commands/package.rb +1 -0
  26. data/lib/project_types/theme/messages/messages.rb +2 -0
  27. data/lib/shopify_cli/commands/app/deploy.rb +0 -1
  28. data/lib/shopify_cli/context.rb +2 -2
  29. data/lib/shopify_cli/core/entry_point.rb +1 -1
  30. data/lib/shopify_cli/core/monorail.rb +14 -6
  31. data/lib/shopify_cli/exception_reporter.rb +2 -0
  32. data/lib/shopify_cli/packager.rb +1 -1
  33. data/lib/shopify_cli/result.rb +14 -0
  34. data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +5 -5
  35. data/lib/shopify_cli/theme/dev_server/watcher.rb +10 -2
  36. data/lib/shopify_cli/theme/development_theme.rb +2 -5
  37. data/lib/shopify_cli/theme/syncer.rb +20 -25
  38. data/lib/shopify_cli/theme/theme.rb +16 -27
  39. data/lib/shopify_cli/theme/theme_admin_api.rb +71 -0
  40. data/lib/shopify_cli/transform_data_structure.rb +3 -2
  41. data/lib/shopify_cli/version.rb +1 -1
  42. data/shipit.yml +3 -0
  43. data/shopify-cli.gemspec +9 -2
  44. metadata +12 -8
  45. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +0 -36
  46. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +0 -109
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e54fd77e2aa3b1721ea02cd7cad4a84afdae67a3c73510e6ee8b01e44bfc5949
4
- data.tar.gz: a92380f94b7a33cea4eae04d2d528ef09a51d161a5b77a900a294e7176ee89e9
3
+ metadata.gz: be8f00a6bb6d3e7059a63e77ff74327d9e11474cc34b156ec54da33080119e11
4
+ data.tar.gz: ed986614e2b2c0b9b9ca70a175c2133a3130643f3678bbf17148556be4f39f86
5
5
  SHA512:
6
- metadata.gz: 3a55cc0e5a57ab4a842411667dfca871140ef324d17c537157e3913cce383c84ae70ebd26cbf8f14a020b94283c9d6264ab71af5f55c37255fbe7966ee8f46f5
7
- data.tar.gz: 24328c051c6795d7c4778fdaea861cc77d3337a886126074bce4ae3073b635b6bcd878457e8cad4399c5982b0be5d168a3f6f3c86c5e3bbbe7b7b2ce192e4d58
6
+ metadata.gz: cc1c384e33b5bc316e38ab1ab58b978ab56e811309c82746f9218fc8de2cd4d57b243414f324421baff1abdc69829d952840e2c2bd94049963858ca3700c5600
7
+ data.tar.gz: d065d5a10be15c0f79c800798fb0302e9b2519b7b22fea5879ae321297e8bd0859d8b21756b40ae8abe78387e1e3e62b600d0e796a5848545b1c8e5c37af4cd2
data/.github/CODEOWNERS CHANGED
@@ -3,3 +3,8 @@
3
3
 
4
4
  /lib/project_types/script/ @shopify/scripts-platform
5
5
  /test/project_types/script/ @shopify/scripts-platform
6
+
7
+ /lib/project_types/theme/ @shopify/theme-platform-dev-experience
8
+ /lib/shopify_cli/theme/ @shopify/theme-platform-dev-experience
9
+ /test/project_types/theme/ @shopify/theme-platform-dev-experience
10
+ /test/shopify-cli/theme/ @shopify/theme-platform-dev-experience
@@ -40,4 +40,4 @@ Fixes #0000 <!-- link to issue if one exists -->
40
40
  - [ ] I've added a CHANGELOG entry for this PR (if the change is public-facing)
41
41
  - [ ] I've considered possible cross-platform impacts (Mac, Linux, Windows).
42
42
  - [ ] I've left the version number as is (we'll handle incrementing this when releasing).
43
- - [ ] I've included any post-release steps in the section above.
43
+ - [ ] I've included any post-release steps in the section above (if needed).
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@ From version 2.6.0, the sections in this file adhere to the [keep a changelog](h
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## Version 2.14.0
6
+
7
+ ### Changed
8
+ * [#2126](https://github.com/Shopify/shopify-cli/pull/2126): Use javy version 0.2.1
9
+
10
+ ### Added
11
+ * [#2103](https://github.com/Shopify/shopify-cli/pull/2103): Improve `shopify theme package` to include the `release-notes.md` file
12
+
13
+ ### Fixed
14
+ * [#2112](https://github.com/Shopify/shopify-cli/pull/2112): Fix intermittent error ("can't add a new key into hash during iteration") in the `theme push` command
15
+ * [#2088](https://github.com/Shopify/shopify-cli/pull/2088): Update theme-check to 1.10.1
16
+ * [#2130](https://github.com/Shopify/shopify-cli/pull/2130): Fix Homebrew installation.
17
+ * [#2133](https://github.com/Shopify/shopify-cli/pull/2133): Fix ignore file handling in DevServer::Watcher.
18
+
5
19
  ## Version 2.13.0
6
20
 
7
21
  ### Added
@@ -11,6 +25,10 @@ From version 2.6.0, the sections in this file adhere to the [keep a changelog](h
11
25
  ### Fixed
12
26
  * [#2092](https://github.com/Shopify/shopify-cli/pull/2092): Fix `RootHelper` parse logic to support options with an equal (e.g.: `option=value`)
13
27
  * [#2089](https://github.com/Shopify/shopify-cli/pull/2089): Use javy version 0.2.0
28
+ * [#2114](https://github.com/Shopify/shopify-cli/pull/2114): Fix `theme` command error messaging with `ThemeAdminAPI` wrapper
29
+
30
+ ### Removed
31
+ * [#2102](https://github.com/Shopify/shopify-cli/pull/2102): Remove AssemblyScript as a supported script language.
14
32
 
15
33
  ## Version 2.12.0
16
34
  ### Added
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify-cli (2.13.0)
4
+ shopify-cli (2.14.0)
5
5
  bugsnag (~> 6.22)
6
6
  listen (~> 3.7.0)
7
- theme-check (~> 1.9.0)
7
+ theme-check (~> 1.10.1)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
@@ -81,7 +81,7 @@ GEM
81
81
  mini_portile2 (~> 2.8.0)
82
82
  racc (~> 1.4)
83
83
  parallel (1.21.0)
84
- parser (3.1.0.0)
84
+ parser (3.1.1.0)
85
85
  ast (~> 2.4.1)
86
86
  pry (0.13.1)
87
87
  coderay (~> 1.1)
@@ -119,7 +119,7 @@ GEM
119
119
  ruby-progressbar (1.11.0)
120
120
  sys-uname (1.2.2)
121
121
  ffi (~> 1.1)
122
- theme-check (1.9.0)
122
+ theme-check (1.10.1)
123
123
  liquid (>= 5.1.0)
124
124
  nokogiri (>= 1.12)
125
125
  parser (~> 3)
@@ -134,7 +134,7 @@ PLATFORMS
134
134
  ruby
135
135
 
136
136
  DEPENDENCIES
137
- bundler (~> 2.2.2)
137
+ bundler (~> 2.3.8)
138
138
  byebug
139
139
  colorize (~> 0.8.1)
140
140
  cucumber (~> 7.0)
@@ -155,4 +155,4 @@ DEPENDENCIES
155
155
  webmock
156
156
 
157
157
  BUNDLED WITH
158
- 2.2.29
158
+ 2.3.8
data/Rakefile CHANGED
@@ -2,6 +2,8 @@ ENV["SHOPIFY_CLI_TEST"] = "1"
2
2
 
3
3
  require_relative "bin/load_shopify"
4
4
  require_relative "utilities/utilities"
5
+ require_relative "lib/shopify_cli/constants"
6
+ require_relative "lib/shopify_cli/version"
5
7
  require "rake/testtask"
6
8
  require "rubocop/rake_task"
7
9
  require "bundler/gem_tasks"
@@ -33,6 +35,20 @@ task :console do
33
35
  exec("irb", "-r", "./bin/load_shopify.rb", "-r", "byebug")
34
36
  end
35
37
 
38
+ desc("Notifies a new version to Bugsnag")
39
+ task :notify_version_to_bugsnag do
40
+ # This task runs at deployment time to notify
41
+ # Bugsnag about new versions. Because the deployment
42
+ # environment has Node, we can run the Bugsnag CLI
43
+ # through npx.
44
+ system(
45
+ { "npm_config_yes" => "true" },
46
+ "npx", "-q", "bugsnag-build-reporter",
47
+ "-k", ShopifyCLI::Constants::Bugsnag::API_KEY,
48
+ "-v", ShopifyCLI::VERSION
49
+ ) || abort
50
+ end
51
+
36
52
  namespace :rdoc do
37
53
  repo = "https://github.com/Shopify/shopify-cli.wiki.git"
38
54
  intermediate = "markdown_intermediate"
@@ -0,0 +1 @@
1
+ 80576fe617d6e093a72bc826f041207ddc57605381f0db6451ba27310e57e830
@@ -0,0 +1 @@
1
+ 6b7b6f6745594c2e8efcaf948c0ef367911446101d2b8a7c8138ce2aca868cbd
@@ -0,0 +1 @@
1
+ 4010c2d154f1ef7ebf1f8c49621a0742ab75c60fd77746a5fa175878d07f16ef
@@ -0,0 +1 @@
1
+ c12418f7b3e4edead87ade1f44bd7280626a92d8d1238d7f8eb91b1122f20f20
data/ext/javy/version CHANGED
@@ -1 +1 @@
1
- v0.2.0
1
+ v0.2.1
@@ -2,9 +2,27 @@ require "semantic/semantic"
2
2
 
3
3
  module Extension
4
4
  module Models
5
- NpmPackage = Struct.new(:name, :version, keyword_init: true) do
5
+ class NpmPackage
6
+ include SmartProperties
6
7
  include Comparable
7
8
 
9
+ property :name
10
+ property :version
11
+ property :scripts, accepts: Hash
12
+ property :dependencies, accepts: Hash
13
+ property :dev_dependencies, accepts: Hash
14
+
15
+ def initialize(**config)
16
+ super(**config.select { |property_name, _| self.class.properties.key?(property_name) })
17
+ end
18
+
19
+ def self.parse(io)
20
+ ShopifyCLI::Result.call { JSON.parse(io.read) }
21
+ .then(&ShopifyCLI::TransformDataStructure.new(underscore_keys: true, symbolize_keys: true, shallow: true))
22
+ .then { |specification| new(**specification) }
23
+ .unwrap { |error| raise "Failed to parse NPM package specification: #{error}" }
24
+ end
25
+
8
26
  def <=>(other)
9
27
  return nil unless name == other.name
10
28
  Semantic::Version.new(version) <=> Semantic::Version.new(other.version)
@@ -13,15 +13,16 @@ module Extension
13
13
  ]
14
14
 
15
15
  property! :name, accepts: VALID_RENDERERS
16
+ property! :version, accepts: String, default: "latest"
16
17
 
17
18
  def self.find(type)
18
19
  case type.downcase
19
20
  when "product_subscription"
20
- new(name: "@shopify/admin-ui-extensions")
21
+ new(name: "@shopify/admin-ui-extensions", version: "^1.0.1")
21
22
  when "checkout_ui_extension"
22
- new(name: "@shopify/checkout-ui-extensions")
23
+ new(name: "@shopify/checkout-ui-extensions", version: "^0.14.0")
23
24
  when "checkout_post_purchase"
24
- new(name: "@shopify/post-purchase-ui-extensions")
25
+ new(name: "@shopify/post-purchase-ui-extensions", version: "^0.13.2")
25
26
  end
26
27
  end
27
28
  end
@@ -64,10 +64,6 @@ module Script
64
64
  autoload :ServiceLocator, Project.project_filepath("layers/infrastructure/service_locator")
65
65
 
66
66
  module Languages
67
- autoload :AssemblyScriptProjectCreator,
68
- Project.project_filepath("layers/infrastructure/languages/assemblyscript_project_creator")
69
- autoload :AssemblyScriptTaskRunner,
70
- Project.project_filepath("layers/infrastructure/languages/assemblyscript_task_runner")
71
67
  autoload :ProjectCreator, Project.project_filepath("layers/infrastructure/languages/project_creator")
72
68
  autoload :TaskRunner, Project.project_filepath("layers/infrastructure/languages/task_runner")
73
69
  autoload :TypeScriptProjectCreator,
@@ -1,9 +1,6 @@
1
1
  payment_methods:
2
2
  domain: 'checkout'
3
3
  libraries:
4
- assemblyscript:
5
- repo: "https://github.com/Shopify/scripts-apis-examples"
6
- package: "@shopify/scripts-checkout-apis"
7
4
  typescript:
8
5
  beta: true
9
6
  package: "@shopify/scripts-checkout-apis"
@@ -13,9 +10,6 @@ payment_methods:
13
10
  shipping_methods:
14
11
  domain: 'checkout'
15
12
  libraries:
16
- assemblyscript:
17
- repo: "https://github.com/Shopify/scripts-apis-examples"
18
- package: "@shopify/scripts-checkout-apis"
19
13
  typescript:
20
14
  beta: true
21
15
  package: "@shopify/scripts-checkout-apis"
@@ -5,31 +5,16 @@ module Script
5
5
  module Application
6
6
  class BuildScript
7
7
  class << self
8
- def call(ctx:, task_runner:, script_project:, library:)
8
+ def call(ctx:, task_runner:)
9
9
  CLI::UI::Frame.open(ctx.message("script.application.building")) do
10
10
  UI::StrictSpinner.spin(ctx.message("script.application.building_script")) do |spinner|
11
- script_content = task_runner.build
12
- metadata_file_location = task_runner.metadata_file_location
13
- metadata = Infrastructure::MetadataRepository.new(ctx: ctx).get_metadata(metadata_file_location)
14
-
15
- Infrastructure::PushPackageRepository.new(ctx: ctx).create_push_package(
16
- script_project: script_project,
17
- script_content: script_content,
18
- metadata: metadata,
19
- library: library,
20
- )
11
+ task_runner.build
21
12
  spinner.update_title(ctx.message("script.application.built"))
22
13
  end
23
- rescue StandardError => e
14
+ rescue Infrastructure::Errors::BuildError => e
24
15
  CLI::UI::Frame.with_frame_color_override(:red) do
25
16
  ctx.puts("\n{{red:#{e.message}}}")
26
17
  end
27
- errors = [
28
- Infrastructure::Errors::BuildScriptNotFoundError,
29
- Infrastructure::Errors::WebAssemblyBinaryNotFoundError,
30
- ]
31
-
32
- raise Infrastructure::Errors::BuildError unless errors.any? { |err| e.is_a?(err) }
33
18
  raise
34
19
  end
35
20
  end
@@ -21,30 +21,32 @@ module Script
21
21
  api: script_project.extension_point_type
22
22
  ) if library.nil? && (script_project.language != "wasm")
23
23
 
24
- library_name = library&.package
25
- library_data = {
26
- language: script_project.language,
27
- version: task_runner.library_version(library_name),
28
- } if library_name
29
-
30
24
  ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
31
- BuildScript.call(ctx: ctx, task_runner: task_runner, script_project: script_project, library: library_data)
32
-
33
- metadata_file_location = task_runner.metadata_file_location
34
- metadata = Infrastructure::MetadataRepository.new(ctx: ctx).get_metadata(metadata_file_location)
25
+ BuildScript.call(ctx: ctx, task_runner: task_runner)
35
26
 
36
27
  CLI::UI::Frame.open(ctx.message("script.application.pushing")) do
37
28
  UI::PrintingSpinner.spin(ctx, ctx.message("script.application.pushing_script")) do |p_ctx, spinner|
29
+ library_name = library&.package
30
+ library_data = {
31
+ language: script_project.language,
32
+ version: task_runner.library_version(library_name),
33
+ } if library_name
34
+
35
+ metadata_file_location = task_runner.metadata_file_location
36
+ metadata = Infrastructure::MetadataRepository.new(ctx: ctx).get_metadata(metadata_file_location)
37
+
38
38
  package = Infrastructure::PushPackageRepository.new(ctx: p_ctx).get_push_package(
39
39
  script_project: script_project,
40
40
  metadata: metadata,
41
41
  library: library_data,
42
42
  )
43
+
43
44
  script_service = Infrastructure::ServiceLocator.script_service(
44
45
  ctx: p_ctx,
45
46
  api_key: script_project.api_key
46
47
  )
47
48
  module_upload_url = Infrastructure::ScriptUploader.new(script_service).upload(package.script_content)
49
+
48
50
  uuid = script_service.set_app_script(
49
51
  uuid: package.uuid,
50
52
  extension_point_type: package.extension_point_type,
@@ -26,7 +26,6 @@ module Script
26
26
  )
27
27
 
28
28
  project_creators = {
29
- "assemblyscript" => AssemblyScriptProjectCreator,
30
29
  "typescript" => TypeScriptProjectCreator,
31
30
  "wasm" => WasmProjectCreator,
32
31
  }
@@ -9,7 +9,6 @@ module Script
9
9
 
10
10
  def self.for(ctx, language)
11
11
  task_runners = {
12
- "assemblyscript" => AssemblyScriptTaskRunner,
13
12
  "typescript" => TypeScriptTaskRunner,
14
13
  "wasm" => WasmTaskRunner,
15
14
  }
@@ -18,7 +18,8 @@ module Script
18
18
 
19
19
  def build
20
20
  compile
21
- bytecode
21
+ rescue Errors::SystemCallFailureError => e
22
+ raise Errors::BuildError, e.out
22
23
  end
23
24
 
24
25
  def install_dependencies
@@ -95,15 +96,6 @@ module Script
95
96
  raise Errors::BuildScriptNotFoundError,
96
97
  "Build script not found" if build_script.nil?
97
98
  end
98
-
99
- def bytecode
100
- raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(BYTECODE_FILE)
101
-
102
- contents = ctx.binread(BYTECODE_FILE)
103
- ctx.rm(BYTECODE_FILE)
104
-
105
- contents
106
- end
107
99
  end
108
100
  end
109
101
  end
@@ -5,7 +5,7 @@ module Script
5
5
  module Infrastructure
6
6
  module Languages
7
7
  class WasmTaskRunner < TaskRunner
8
- BYTECODE_FILE = "script.wasm"
8
+ BYTECODE_FILE = "build/index.wasm"
9
9
 
10
10
  def dependencies_installed?
11
11
  true
@@ -7,23 +7,6 @@ module Script
7
7
  include SmartProperties
8
8
  property! :ctx, accepts: ShopifyCLI::Context
9
9
 
10
- def create_push_package(script_project:, script_content:, metadata:, library:)
11
- build_file_path = file_path(script_project.id)
12
- write_to_path(build_file_path, script_content)
13
-
14
- Domain::PushPackage.new(
15
- id: build_file_path,
16
- uuid: script_project.uuid,
17
- extension_point_type: script_project.extension_point_type,
18
- title: script_project.title,
19
- description: script_project.description,
20
- script_content: script_content,
21
- metadata: metadata,
22
- script_config: script_project.script_config,
23
- library: library
24
- )
25
- end
26
-
27
10
  def get_push_package(script_project:, metadata:, library:)
28
11
  build_file_path = file_path(script_project.id)
29
12
  raise Domain::Errors::PushPackageNotFoundError unless ctx.file_exist?(build_file_path)
@@ -44,13 +27,8 @@ module Script
44
27
 
45
28
  private
46
29
 
47
- def write_to_path(path, content)
48
- ctx.mkdir_p(File.dirname(path))
49
- ctx.binwrite(path, content)
50
- end
51
-
52
30
  def file_path(path_to_script)
53
- "#{path_to_script}/build/script.wasm"
31
+ "#{path_to_script}/build/index.wasm"
54
32
  end
55
33
  end
56
34
  end
@@ -136,7 +136,7 @@ module Script
136
136
  end
137
137
 
138
138
  def default_language
139
- "assemblyscript"
139
+ "wasm"
140
140
  end
141
141
 
142
142
  def validate_metadata!(extension_point_type, language)
@@ -135,8 +135,8 @@ module Script
135
135
  "\nbuild: npx 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=",
136
136
 
137
137
  web_assembly_binary_not_found: "Wasm binary not found.",
138
- web_assembly_binary_not_found_suggestion: "Check that there is a valid Wasm binary in the root directory" \
139
- "Your Wasm binary should match the script name: <script_name>.wasm",
138
+ web_assembly_binary_not_found_suggestion: "Check that a valid Wasm binary is present. " \
139
+ "The Wasm binary's filepath must be 'build/index.wasm'.",
140
140
 
141
141
  project_config_not_found: "Internal error - Script can't be created because the project's config file is missing from the repository.",
142
142
 
@@ -15,6 +15,7 @@ module Theme
15
15
  sections
16
16
  snippets
17
17
  templates
18
+ release-notes.md
18
19
  ]
19
20
 
20
21
  def call(args, _name)
@@ -7,6 +7,8 @@ module Theme
7
7
  Suite of commands for developing Shopify themes. See {{command:%1$s theme <command> --help}} for usage of each command.
8
8
  Usage: {{command:%1$s theme [ %2$s ]}}
9
9
  HELP
10
+ ensure_user_error: "You are not authorized to edit themes on %s.",
11
+ ensure_user_try_this: "Make sure you are a user of that store, and allowed to edit themes.",
10
12
 
11
13
  init: {
12
14
  help: <<~HELP,
@@ -2,7 +2,6 @@ module ShopifyCLI
2
2
  module Commands
3
3
  class App
4
4
  class Deploy < ShopifyCLI::Command::AppSubCommand
5
- subcommand :Heroku, "heroku", "shopify_cli/commands/app/deploy/heroku"
6
5
  prerequisite_task :ensure_git_dependency
7
6
 
8
7
  recommend_default_ruby_range
@@ -103,7 +103,7 @@ module ShopifyCLI
103
103
  # any command run by the context.
104
104
  attr_accessor :env
105
105
 
106
- def initialize(root: Dir.pwd, env: ($original_env || ENV).clone) # :nodoc:
106
+ def initialize(root: Dir.pwd, env: ($original_env || ENV).to_h) # :nodoc:
107
107
  self.root = root
108
108
  self.env = env
109
109
  end
@@ -164,7 +164,7 @@ module ShopifyCLI
164
164
 
165
165
  # will return true while tests are running, either locally or on CI
166
166
  def testing?
167
- ci? || ENV["TEST"]
167
+ ci? || ENV["SHOPIFY_CLI_TEST"]
168
168
  end
169
169
 
170
170
  ##
@@ -5,7 +5,7 @@ module ShopifyCLI
5
5
  module EntryPoint
6
6
  class << self
7
7
  def call(args, ctx = Context.new)
8
- if ctx.development?
8
+ if ctx.development? && !ctx.testing?
9
9
  ctx.warn(
10
10
  ctx.message("core.warning.development_version", File.join(ShopifyCLI::ROOT, "bin", ShopifyCLI::TOOL_NAME))
11
11
  )
@@ -17,11 +17,7 @@ module ShopifyCLI
17
17
 
18
18
  def log(name, args, &block) # rubocop:disable Lint/UnusedMethodArgument
19
19
  command, command_name = Commands::Registry.lookup_command(name)
20
- final_command = [command_name]
21
- if command
22
- subcommand, subcommand_name = command.subcommand_registry.lookup_command(args.first)
23
- final_command << subcommand_name if subcommand
24
- end
20
+ full_command = self.full_command(command, args, resolved_command: [command_name])
25
21
 
26
22
  start_time = now_in_milliseconds
27
23
  err = nil
@@ -35,9 +31,21 @@ module ShopifyCLI
35
31
  # If there's an error, we don't prompt from here and we let the exception
36
32
  # reporter do that.
37
33
  if report?(prompt: err.nil?)
38
- send_event(start_time, final_command, args - final_command, err&.message)
34
+ send_event(start_time, full_command, args - full_command, err&.message)
35
+ end
36
+ end
37
+ end
38
+
39
+ def full_command(command, args, resolved_command:)
40
+ resolved_command = resolved_command.dup
41
+ if command
42
+ subcommand, subcommand_name = command.subcommand_registry.lookup_command(args.first)
43
+ resolved_command << subcommand_name if subcommand
44
+ if subcommand&.subcommand_registry
45
+ resolved_command = full_command(subcommand, args.drop(1), resolved_command: resolved_command)
39
46
  end
40
47
  end
48
+ resolved_command
41
49
  end
42
50
 
43
51
  private
@@ -46,6 +46,8 @@ module ShopifyCLI
46
46
  Bugsnag.notify(error) do |event|
47
47
  event.add_metadata(:device, metadata)
48
48
  end
49
+ rescue
50
+ nil
49
51
  end
50
52
 
51
53
  def self.report?(context:)
@@ -81,7 +81,7 @@ module ShopifyCLI
81
81
  puts "Grabbing sha256 checksum from Rubygems.org"
82
82
  require "digest/sha2"
83
83
  require "open-uri"
84
- gem_checksum = open("https://rubygems.org/downloads/shopify-cli-#{ShopifyCLI::VERSION}.gem") do |io|
84
+ gem_checksum = URI.open("https://rubygems.org/downloads/shopify-cli-#{ShopifyCLI::VERSION}.gem") do |io|
85
85
  Digest::SHA256.new.hexdigest(io.read)
86
86
  end
87
87
 
@@ -181,6 +181,13 @@ module ShopifyCLI
181
181
  self
182
182
  end
183
183
 
184
+ ##
185
+ # returns the value this success represents
186
+ #
187
+ def unwrap!
188
+ value
189
+ end
190
+
184
191
  ##
185
192
  # returns the success value and ignores the fallback value that was either
186
193
  # provided as a method argument or by passing a block. However, the caller
@@ -339,6 +346,13 @@ module ShopifyCLI
339
346
  raise ArgumentError, "expected either a fallback value or a block" unless (args.length == 1) ^ block
340
347
  block ? block.call(@error) : args.pop
341
348
  end
349
+
350
+ ##
351
+ # raises the error this failure represents
352
+ #
353
+ def unwrap!
354
+ raise error
355
+ end
342
356
  end
343
357
 
344
358
  ##
@@ -28,6 +28,10 @@ module ShopifyCLI
28
28
 
29
29
  private
30
30
 
31
+ def api_client
32
+ @api_client ||= ThemeAdminAPI.new(@ctx, @theme.shop)
33
+ end
34
+
31
35
  def updated_file?(body, file)
32
36
  remote_checksum = body.dig("asset", "checksum")
33
37
  local_checksum = file.checksum
@@ -45,12 +49,8 @@ module ShopifyCLI
45
49
  end
46
50
 
47
51
  def fetch_asset(file)
48
- ShopifyCLI::AdminAPI.rest_request(
49
- @ctx,
50
- shop: @theme.shop,
52
+ api_client.get(
51
53
  path: "themes/#{@theme.id}/assets.json",
52
- method: "GET",
53
- api_version: "unstable",
54
54
  query: URI.encode_www_form("asset[key]" => file.relative_path.to_s),
55
55
  )
56
56
  rescue ShopifyCLI::API::APIRequestNotFoundError
@@ -45,13 +45,21 @@ module ShopifyCLI
45
45
  def filter_theme_files(files)
46
46
  files
47
47
  .select { |file| @theme.theme_file?(file) }
48
- .reject { |file| @ignore_filter&.ignore?(file) }
48
+ .map { |file| @theme[file] }
49
+ .reject { |file| ignore_file?(file) }
49
50
  end
50
51
 
51
52
  def filter_remote_files(files)
52
53
  files
53
54
  .select { |file| @syncer.remote_file?(file) }
54
- .reject { |file| @ignore_filter&.ignore?(file) }
55
+ .map { |file| @theme[file] }
56
+ .reject { |file| ignore_file?(file) }
57
+ end
58
+
59
+ private
60
+
61
+ def ignore_file?(file)
62
+ @ignore_filter&.ignore?(file.relative_path.to_s)
55
63
  end
56
64
  end
57
65
  end
@@ -45,11 +45,8 @@ module ShopifyCLI
45
45
  def exists?
46
46
  return false unless id
47
47
 
48
- ShopifyCLI::AdminAPI.rest_request(
49
- @ctx,
50
- shop: shop,
51
- path: "themes/#{id}.json",
52
- api_version: "unstable",
48
+ api_client.get(
49
+ path: "themes/#{id}.json"
53
50
  )
54
51
  rescue ShopifyCLI::API::APIRequestNotFoundError
55
52
  false
@@ -7,15 +7,15 @@ require "forwardable"
7
7
  require_relative "syncer/error_reporter"
8
8
  require_relative "syncer/standard_reporter"
9
9
  require_relative "syncer/operation"
10
+ require_relative "theme_admin_api"
10
11
 
11
12
  module ShopifyCLI
12
13
  module Theme
13
14
  class Syncer
14
15
  extend Forwardable
15
16
 
16
- API_VERSION = "unstable"
17
-
18
17
  attr_reader :checksums
18
+ attr_reader :checksums_mutex
19
19
  attr_accessor :include_filter
20
20
  attr_accessor :ignore_filter
21
21
 
@@ -39,6 +39,9 @@ module ShopifyCLI
39
39
  # Mutex used to pause all threads when backing-off when hitting API rate limits
40
40
  @backoff_mutex = Mutex.new
41
41
 
42
+ # Mutex used to coordinate changes in the checksums (shared accross all threads)
43
+ @checksums_mutex = Mutex.new
44
+
42
45
  # Latest theme assets checksums. Updated on each upload.
43
46
  @checksums = {}
44
47
 
@@ -46,6 +49,10 @@ module ShopifyCLI
46
49
  @error_checksums = []
47
50
  end
48
51
 
52
+ def api_client
53
+ @api_client ||= ThemeAdminAPI.new(@ctx, @theme.shop)
54
+ end
55
+
49
56
  def lock_io!
50
57
  @reporters.each(&:disable!)
51
58
  end
@@ -96,11 +103,8 @@ module ShopifyCLI
96
103
  end
97
104
 
98
105
  def fetch_checksums!
99
- _status, response = ShopifyCLI::AdminAPI.rest_request(
100
- @ctx,
101
- shop: @theme.shop,
102
- path: "themes/#{@theme.id}/assets.json",
103
- api_version: API_VERSION,
106
+ _status, response = api_client.get(
107
+ path: "themes/#{@theme.id}/assets.json"
104
108
  )
105
109
  update_checksums(response)
106
110
  end
@@ -239,12 +243,8 @@ module ShopifyCLI
239
243
  asset[:attachment] = Base64.encode64(file.read)
240
244
  end
241
245
 
242
- _status, body, response = ShopifyCLI::AdminAPI.rest_request(
243
- @ctx,
244
- shop: @theme.shop,
246
+ _status, body, response = api_client.put(
245
247
  path: "themes/#{@theme.id}/assets.json",
246
- method: "PUT",
247
- api_version: API_VERSION,
248
248
  body: JSON.generate(asset: asset)
249
249
  )
250
250
 
@@ -272,16 +272,12 @@ module ShopifyCLI
272
272
  end
273
273
 
274
274
  def ignored_by_include_filter?(path)
275
- include_filter && !include_filter.match?(path)
275
+ !!include_filter && !include_filter.match?(path)
276
276
  end
277
277
 
278
278
  def get(file)
279
- _status, body, response = ShopifyCLI::AdminAPI.rest_request(
280
- @ctx,
281
- shop: @theme.shop,
279
+ _status, body, response = api_client.get(
282
280
  path: "themes/#{@theme.id}/assets.json",
283
- method: "GET",
284
- api_version: API_VERSION,
285
281
  query: URI.encode_www_form("asset[key]" => file.relative_path.to_s),
286
282
  )
287
283
 
@@ -298,12 +294,8 @@ module ShopifyCLI
298
294
  end
299
295
 
300
296
  def delete(file)
301
- _status, _body, response = ShopifyCLI::AdminAPI.rest_request(
302
- @ctx,
303
- shop: @theme.shop,
297
+ _status, _body, response = api_client.delete(
304
298
  path: "themes/#{@theme.id}/assets.json",
305
- method: "DELETE",
306
- api_version: API_VERSION,
307
299
  body: JSON.generate(asset: {
308
300
  key: file.relative_path.to_s,
309
301
  })
@@ -314,14 +306,17 @@ module ShopifyCLI
314
306
 
315
307
  def update_checksums(api_response)
316
308
  api_response.values.flatten.each do |asset|
317
- if asset["key"]
309
+ next unless asset["key"]
310
+ checksums_mutex.synchronize do
318
311
  @checksums[asset["key"]] = asset["checksum"]
319
312
  end
320
313
  end
321
314
  # Generate .liquid asset files are reported twice in checksum:
322
315
  # once of generated, once for .liquid. We only keep the .liquid, that's the one we have
323
316
  # on disk.
324
- @checksums.reject! { |key, _| @checksums.key?("#{key}.liquid") }
317
+ checksums_mutex.synchronize do
318
+ @checksums.reject! { |key, _| @checksums.key?("#{key}.liquid") }
319
+ end
325
320
  end
326
321
 
327
322
  def file_has_changed?(file)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative "file"
3
+ require_relative "theme_admin_api"
3
4
 
4
5
  require "pathname"
5
6
  require "time"
@@ -59,7 +60,7 @@ module ShopifyCLI
59
60
  end
60
61
 
61
62
  def shop
62
- AdminAPI.get_shop_or_abort(@ctx)
63
+ api_client.get_shop_or_abort
63
64
  end
64
65
 
65
66
  def editor_url
@@ -101,9 +102,7 @@ module ShopifyCLI
101
102
  def create
102
103
  raise InvalidThemeRole, "Can't create live theme. Use publish." if live?
103
104
 
104
- _status, body = ShopifyCLI::AdminAPI.rest_request(
105
- @ctx,
106
- shop: shop,
105
+ _status, body = api_client.post(
107
106
  path: "themes.json",
108
107
  body: JSON.generate({
109
108
  theme: {
@@ -111,31 +110,21 @@ module ShopifyCLI
111
110
  role: role,
112
111
  },
113
112
  }),
114
- method: "POST",
115
- api_version: "unstable",
116
113
  )
117
114
 
118
115
  @id = body["theme"]["id"]
119
116
  end
120
117
 
121
118
  def delete
122
- AdminAPI.rest_request(
123
- @ctx,
124
- shop: shop,
125
- method: "DELETE",
126
- path: "themes/#{id}.json",
127
- api_version: "unstable",
119
+ api_client.delete(
120
+ path: "themes/#{id}.json"
128
121
  )
129
122
  end
130
123
 
131
124
  def publish
132
125
  return if live?
133
- AdminAPI.rest_request(
134
- @ctx,
135
- shop: shop,
136
- method: "PUT",
126
+ api_client.put(
137
127
  path: "themes/#{id}.json",
138
- api_version: "unstable",
139
128
  body: JSON.generate(theme: {
140
129
  role: "main",
141
130
  })
@@ -205,23 +194,23 @@ module ShopifyCLI
205
194
  end
206
195
 
207
196
  def fetch_themes(ctx)
208
- AdminAPI.rest_request(
209
- ctx,
210
- shop: AdminAPI.get_shop_or_abort(ctx),
211
- path: "themes.json",
212
- api_version: "unstable",
197
+ api_client = ThemeAdminAPI.new(ctx)
198
+
199
+ api_client.get(
200
+ path: "themes.json"
213
201
  )
214
202
  end
215
203
  end
216
204
 
217
205
  private
218
206
 
207
+ def api_client
208
+ @api_client ||= ThemeAdminAPI.new(@ctx)
209
+ end
210
+
219
211
  def load_info_from_api
220
- _status, body = AdminAPI.rest_request(
221
- @ctx,
222
- shop: shop,
223
- path: "themes/#{id}.json",
224
- api_version: "unstable",
212
+ _status, body = api_client.get(
213
+ path: "themes/#{id}.json"
225
214
  )
226
215
 
227
216
  @name = body.dig("theme", "name")
@@ -0,0 +1,71 @@
1
+ module ShopifyCLI
2
+ module Theme
3
+ class ThemeAdminAPI
4
+ API_VERSION = "unstable"
5
+
6
+ attr_reader :shop
7
+
8
+ def initialize(ctx, shop = nil)
9
+ @ctx = ctx
10
+ @shop = shop || get_shop_or_abort
11
+ end
12
+
13
+ def get(path:, **args)
14
+ rest_request(
15
+ method: "GET",
16
+ path: path,
17
+ **args
18
+ )
19
+ end
20
+
21
+ def put(path:, **args)
22
+ rest_request(
23
+ method: "PUT",
24
+ path: path,
25
+ **args
26
+ )
27
+ end
28
+
29
+ def post(path:, **args)
30
+ rest_request(
31
+ method: "POST",
32
+ path: path,
33
+ **args
34
+ )
35
+ end
36
+
37
+ def delete(path:, **args)
38
+ rest_request(
39
+ method: "DELETE",
40
+ path: path,
41
+ **args
42
+ )
43
+ end
44
+
45
+ def get_shop_or_abort # rubocop:disable Naming/AccessorMethodName
46
+ ShopifyCLI::AdminAPI.get_shop_or_abort(@ctx)
47
+ end
48
+
49
+ private
50
+
51
+ def rest_request(**args)
52
+ ShopifyCLI::AdminAPI.rest_request(
53
+ @ctx,
54
+ shop: @shop,
55
+ api_version: API_VERSION,
56
+ **args.compact
57
+ )
58
+ rescue ShopifyCLI::API::APIRequestForbiddenError,
59
+ ShopifyCLI::API::APIRequestUnauthorizedError
60
+ handle_permissions_error
61
+ end
62
+
63
+ def handle_permissions_error
64
+ ensure_user_error = @ctx.message("theme.ensure_user_error", get_shop_or_abort)
65
+ ensure_user_try_this = @ctx.message("theme.ensure_user_try_this")
66
+
67
+ @ctx.abort(ensure_user_error, ensure_user_try_this)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -40,6 +40,7 @@ module ShopifyCLI
40
40
 
41
41
  property! :underscore_keys, accepts: [true, false], default: false, reader: :underscore_keys?
42
42
  property! :symbolize_keys, accepts: [true, false], default: false, reader: :symbolize_keys?
43
+ property! :shallow, accepts: [true, false], default: false, reader: :shallow?
43
44
  property! :associative_array_container,
44
45
  accepts: ->(c) { c.respond_to?(:new) && c.method_defined?(:[]=) },
45
46
  default: -> { Hash }
@@ -47,10 +48,10 @@ module ShopifyCLI
47
48
  def call(object)
48
49
  case object
49
50
  when Array
50
- object.map(&self).map(&:value)
51
+ shallow? ? object.dup : object.map(&self).map(&:value)
51
52
  when Hash
52
53
  object.each.with_object(associative_array_container.new) do |(key, value), result|
53
- result[transform_key(key)] = call(value).value
54
+ result[transform_key(key)] = shallow? ? value : call(value).value
54
55
  end
55
56
  else
56
57
  ShopifyCLI::Result.success(object)
@@ -1,3 +1,3 @@
1
1
  module ShopifyCLI
2
- VERSION = "2.13.0"
2
+ VERSION = "2.14.0"
3
3
  end
data/shipit.yml ADDED
@@ -0,0 +1,3 @@
1
+ deploy:
2
+ post:
3
+ - bundle exec rake notify_version_to_bugsnag
data/shopify-cli.gemspec CHANGED
@@ -35,11 +35,18 @@ Gem::Specification.new do |spec|
35
35
  spec.require_paths = ["lib", "vendor"]
36
36
  spec.executables << "shopify"
37
37
 
38
- spec.add_development_dependency("bundler", "~> 2.2.2")
38
+ spec.add_development_dependency("bundler", "~> 2.3.8")
39
39
  spec.add_development_dependency("rake", "~> 12.3", ">= 12.3.3")
40
40
  spec.add_development_dependency("minitest", "~> 5.0")
41
41
 
42
42
  spec.add_dependency("bugsnag", "~> 6.22")
43
43
  spec.add_dependency("listen", "~> 3.7.0")
44
- spec.add_dependency("theme-check", "~> 1.9.0")
44
+
45
+ # We prefer being more strict here with the version range to have a more deterministic build.
46
+ # The added benefit is that, if the user upgrades the CLI, and we have "~> 1.10.1" version range,
47
+ # they will get a theme-check update.
48
+ # Whereas if we were to have "~> 1.9", that version would still be satisfied and thus not upgraded.
49
+ # Both shopify-cli and theme-check gems are owned and developed by Shopify.
50
+ # These gems are currently being actively developed and it's easiest to update them together.
51
+ spec.add_dependency("theme-check", "~> 1.10.1")
45
52
  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: 2.13.0
4
+ version: 2.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-02 00:00:00.000000000 Z
11
+ date: 2022-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.2.2
19
+ version: 2.3.8
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.2.2
26
+ version: 2.3.8
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 1.9.0
95
+ version: 1.10.1
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: 1.9.0
102
+ version: 1.10.1
103
103
  description: |
104
104
  Shopify CLI helps you build Shopify apps faster. It quickly scaffolds Node.js
105
105
  and Ruby on Rails embedded apps. It also automates many common tasks in the
@@ -155,12 +155,16 @@ files:
155
155
  - docs/users/migrate-from-themekit.md
156
156
  - ext/javy/hashes/javy-arm-macos-v0.1.0.gz.sha256
157
157
  - ext/javy/hashes/javy-arm-macos-v0.2.0.gz.sha256
158
+ - ext/javy/hashes/javy-arm-macos-v0.2.1.gz.sha256
158
159
  - ext/javy/hashes/javy-x86_64-linux-v0.1.0.gz.sha256
159
160
  - ext/javy/hashes/javy-x86_64-linux-v0.2.0.gz.sha256
161
+ - ext/javy/hashes/javy-x86_64-linux-v0.2.1.gz.sha256
160
162
  - ext/javy/hashes/javy-x86_64-macos-v0.1.0.gz.sha256
161
163
  - ext/javy/hashes/javy-x86_64-macos-v0.2.0.gz.sha256
164
+ - ext/javy/hashes/javy-x86_64-macos-v0.2.1.gz.sha256
162
165
  - ext/javy/hashes/javy-x86_64-windows-v0.1.0.gz.sha256
163
166
  - ext/javy/hashes/javy-x86_64-windows-v0.2.0.gz.sha256
167
+ - ext/javy/hashes/javy-x86_64-windows-v0.2.1.gz.sha256
164
168
  - ext/javy/javy.rb
165
169
  - ext/javy/version
166
170
  - ext/shopify-extensions/extconf.rb
@@ -317,8 +321,6 @@ files:
317
321
  - lib/project_types/script/layers/infrastructure/command_runner.rb
318
322
  - lib/project_types/script/layers/infrastructure/errors.rb
319
323
  - lib/project_types/script/layers/infrastructure/extension_point_repository.rb
320
- - lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb
321
- - lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb
322
324
  - lib/project_types/script/layers/infrastructure/languages/project_creator.rb
323
325
  - lib/project_types/script/layers/infrastructure/languages/task_runner.rb
324
326
  - lib/project_types/script/layers/infrastructure/languages/tool_version_checker.rb
@@ -502,12 +504,14 @@ files:
502
504
  - lib/shopify_cli/theme/syncer/operation.rb
503
505
  - lib/shopify_cli/theme/syncer/standard_reporter.rb
504
506
  - lib/shopify_cli/theme/theme.rb
507
+ - lib/shopify_cli/theme/theme_admin_api.rb
505
508
  - lib/shopify_cli/thread_pool.rb
506
509
  - lib/shopify_cli/thread_pool/job.rb
507
510
  - lib/shopify_cli/transform_data_structure.rb
508
511
  - lib/shopify_cli/tunnel.rb
509
512
  - lib/shopify_cli/utilities.rb
510
513
  - lib/shopify_cli/version.rb
514
+ - shipit.yml
511
515
  - shopify-cli.gemspec
512
516
  - shopify-dev
513
517
  - utilities/constants.rb
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Script
4
- module Layers
5
- module Infrastructure
6
- module Languages
7
- class AssemblyScriptProjectCreator < ProjectCreator
8
- def setup_dependencies
9
- task_runner = Infrastructure::Languages::AssemblyScriptTaskRunner.new(ctx)
10
- task_runner.set_npm_config
11
- super
12
-
13
- update_package_json_name
14
- end
15
-
16
- private
17
-
18
- def update_package_json_name
19
- file_content = ctx.read("package.json")
20
- hash = file_content_to_hash(file_content)
21
- hash["name"] = project_name
22
- ctx.write("package.json", hash_to_file_content(hash))
23
- end
24
-
25
- def file_content_to_hash(content)
26
- JSON.parse(content)
27
- end
28
-
29
- def hash_to_file_content(hash)
30
- JSON.pretty_generate(hash)
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Script
4
- module Layers
5
- module Infrastructure
6
- module Languages
7
- class AssemblyScriptTaskRunner < TaskRunner
8
- NODE_MIN_VERSION = "14.15.0"
9
- NPM_MIN_VERSION = "5.2.0"
10
-
11
- BYTECODE_FILE = "build/script.wasm"
12
- METADATA_FILE = "build/metadata.json"
13
- SCRIPT_SDK_BUILD = "npm run build"
14
- NPM_SET_REGISTRY_COMMAND = "npm --userconfig ./.npmrc config set @shopify:registry https://registry.npmjs.com"
15
- NPM_SET_ENGINE_STRICT_COMMAND = "npm --userconfig ./.npmrc config set engine-strict true"
16
- NPM_INSTALL_COMMAND = "npm install --no-audit --no-optional --legacy-peer-deps --loglevel error"
17
-
18
- def build
19
- compile
20
- bytecode
21
- end
22
-
23
- def install_dependencies
24
- run_cmd_with_env_check(NPM_INSTALL_COMMAND)
25
-
26
- rescue Errors::SystemCallFailureError => e
27
- raise Errors::DependencyInstallError, e.out
28
- end
29
-
30
- def dependencies_installed?
31
- # Assuming if node_modules folder exist at root of script folder, all deps are installed
32
- ctx.dir_exist?("node_modules")
33
- end
34
-
35
- def metadata_file_location
36
- METADATA_FILE
37
- end
38
-
39
- def library_version(library_name)
40
- output = JSON.parse(run_cmd_with_env_check("npm -s list --json"))
41
- library_version_from_npm_list(output, library_name)
42
- rescue Errors::SystemCallFailureError => error
43
- library_version_from_npm_list_error_output(error, library_name)
44
- end
45
-
46
- def set_npm_config
47
- run_cmd_with_env_check(NPM_SET_REGISTRY_COMMAND)
48
- run_cmd_with_env_check(NPM_SET_ENGINE_STRICT_COMMAND)
49
- end
50
-
51
- private
52
-
53
- def ensure_environment
54
- return if defined?(@environment_checked)
55
- @environment_checked = true
56
-
57
- ToolVersionChecker.check_node(minimum_version: NODE_MIN_VERSION)
58
- ToolVersionChecker.check_npm(minimum_version: NPM_MIN_VERSION)
59
- end
60
-
61
- def run_cmd_with_env_check(cmd)
62
- ensure_environment
63
- CommandRunner.new(ctx: ctx).call(cmd)
64
- end
65
-
66
- def library_version_from_npm_list_error_output(error, library_name)
67
- # npm list can return a failure status code, even when returning the correct data.
68
- # This causes the CommandRunner to throw a SystemCallFailure error that contains the data.
69
- # In here, we check that the output contains `npm list`'s structure and extract the version.
70
- output = JSON.parse(error.out)
71
- raise error unless output.key?("dependencies")
72
-
73
- library_version_from_npm_list(output, library_name)
74
- rescue JSON::ParserError
75
- raise error
76
- end
77
-
78
- def library_version_from_npm_list(output, library_name)
79
- output.dig("dependencies", library_name, "version").tap do |version|
80
- raise Errors::APILibraryNotFoundError, library_name unless version
81
- end
82
- end
83
-
84
- def compile
85
- check_compilation_dependencies!
86
- run_cmd_with_env_check(SCRIPT_SDK_BUILD)
87
- end
88
-
89
- def check_compilation_dependencies!
90
- pkg = JSON.parse(File.read("package.json"))
91
- build_script = pkg.dig("scripts", "build")
92
-
93
- raise Errors::BuildScriptNotFoundError,
94
- "Build script not found" if build_script.nil?
95
- end
96
-
97
- def bytecode
98
- raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(BYTECODE_FILE)
99
-
100
- contents = ctx.binread(BYTECODE_FILE)
101
- ctx.rm(BYTECODE_FILE)
102
-
103
- contents
104
- end
105
- end
106
- end
107
- end
108
- end
109
- end