shopify-cli 2.5.0 → 2.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +25 -0
  4. data/Dockerfile +0 -2
  5. data/Gemfile.lock +22 -16
  6. data/README.md +1 -1
  7. data/Rakefile +7 -16
  8. data/bin/console +11 -0
  9. data/bin/shopify +16 -3
  10. data/dev.yml +3 -0
  11. data/ext/shopify-cli/extconf.rb +1 -0
  12. data/lib/project_types/extension/cli.rb +2 -0
  13. data/lib/project_types/extension/commands/build.rb +2 -1
  14. data/lib/project_types/extension/features/argo.rb +1 -1
  15. data/lib/project_types/extension/features/argo_serve.rb +1 -0
  16. data/lib/project_types/extension/models/development_server.rb +4 -0
  17. data/lib/project_types/extension/models/development_server_requirements.rb +1 -2
  18. data/lib/project_types/extension/models/specification_handlers/default.rb +4 -0
  19. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
  20. data/lib/project_types/extension/tasks/find_npm_packages.rb +2 -2
  21. data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
  22. data/lib/project_types/extension/tasks/run_extension_command.rb +26 -10
  23. data/lib/project_types/node/commands/serve.rb +9 -1
  24. data/lib/project_types/node/messages/messages.rb +3 -0
  25. data/lib/project_types/script/cli.rb +4 -3
  26. data/lib/project_types/script/commands/create.rb +2 -0
  27. data/lib/project_types/script/config/extension_points.yml +30 -29
  28. data/lib/project_types/script/layers/application/create_script.rb +32 -12
  29. data/lib/project_types/script/layers/application/extension_points.rb +3 -3
  30. data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
  31. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +4 -2
  32. data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +1 -1
  33. data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
  34. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
  35. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
  36. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
  37. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
  38. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
  39. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +1 -1
  40. data/lib/project_types/script/messages/messages.rb +4 -0
  41. data/lib/project_types/script/ui/error_handler.rb +8 -0
  42. data/lib/shopify_cli/api.rb +4 -0
  43. data/lib/shopify_cli/command/app_sub_command.rb +16 -0
  44. data/lib/shopify_cli/constants.rb +33 -5
  45. data/lib/shopify_cli/core/executor.rb +5 -1
  46. data/lib/shopify_cli/environment.rb +35 -4
  47. data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
  48. data/lib/shopify_cli/exception_reporter.rb +55 -0
  49. data/lib/shopify_cli/git.rb +30 -0
  50. data/lib/shopify_cli/messages/messages.rb +27 -1
  51. data/lib/shopify_cli/method_object.rb +11 -4
  52. data/lib/shopify_cli/migrator/migration.rb +27 -0
  53. data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
  54. data/lib/shopify_cli/migrator.rb +48 -0
  55. data/lib/shopify_cli/version.rb +1 -1
  56. data/lib/shopify_cli.rb +11 -3
  57. data/shopify-cli.gemspec +9 -1
  58. data/utilities/docker.rb +47 -0
  59. data/utilities/utilities.rb +5 -0
  60. metadata +31 -6
  61. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
  62. data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +0 -60
@@ -7,7 +7,7 @@ module Script
7
7
  module Application
8
8
  class CreateScript
9
9
  class << self
10
- def call(ctx:, language:, script_name:, extension_point_type:, no_config_ui:)
10
+ def call(ctx:, language:, sparse_checkout_branch:, script_name:, extension_point_type:, no_config_ui:)
11
11
  raise Infrastructure::Errors::ScriptProjectAlreadyExistsError, script_name if ctx.dir_exist?(script_name)
12
12
 
13
13
  in_new_directory_context(ctx, script_name) do
@@ -18,10 +18,24 @@ module Script
18
18
  extension_point_type: extension_point_type,
19
19
  language: language
20
20
  )
21
- project_creator = Infrastructure::Languages::ProjectCreator
22
- .for(ctx, language, extension_point, script_name, project.id)
21
+
22
+ # remove the need to pass the whole extension-point object to the infra layer
23
+ sparse_checkout_repo = extension_point.libraries.for(language).repo
24
+ type = extension_point.dasherize_type
25
+ domain = extension_point.domain
26
+
27
+ project_creator = Infrastructure::Languages::ProjectCreator.for(
28
+ ctx: ctx,
29
+ language: language,
30
+ type: type,
31
+ project_name: script_name,
32
+ path_to_project: project.id,
33
+ sparse_checkout_repo: sparse_checkout_repo,
34
+ sparse_checkout_branch: sparse_checkout_branch,
35
+ sparse_checkout_set_path: "#{domain}/#{language}/#{type}/default"
36
+ )
37
+
23
38
  install_dependencies(ctx, language, script_name, project_creator)
24
- bootstrap(ctx, project_creator)
25
39
  script_project_repo.update_or_create_script_json(title: script_name, configuration_ui: !no_config_ui)
26
40
  project
27
41
  end
@@ -31,15 +45,21 @@ module Script
31
45
 
32
46
  def install_dependencies(ctx, language, script_name, project_creator)
33
47
  task_runner = Infrastructure::Languages::TaskRunner.for(ctx, language, script_name)
34
- project_creator.setup_dependencies
35
- ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
36
- end
37
-
38
- def bootstrap(ctx, project_creator)
39
- UI::StrictSpinner.spin(ctx.message("script.create.creating")) do |spinner|
40
- project_creator.bootstrap
41
- spinner.update_title(ctx.message("script.create.created"))
48
+ CLI::UI::Frame.open(ctx.message(
49
+ "core.git.pulling_from_to",
50
+ project_creator.sparse_checkout_repo,
51
+ script_name,
52
+ )) do
53
+ UI::StrictSpinner.spin(ctx.message(
54
+ "core.git.pulling",
55
+ project_creator.sparse_checkout_repo,
56
+ script_name,
57
+ )) do |spinner|
58
+ project_creator.setup_dependencies
59
+ spinner.update_title(ctx.message("core.git.pulled", script_name))
60
+ end
42
61
  end
62
+ ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
43
63
  end
44
64
 
45
65
  def in_new_directory_context(ctx, directory)
@@ -27,9 +27,9 @@ module Script
27
27
  end
28
28
 
29
29
  def self.languages(type:)
30
- get(type: type).sdks.all.map do |sdk|
31
- next nil if sdk.beta? && !ShopifyCLI::Feature.enabled?(:scripts_beta_languages)
32
- sdk.class.language
30
+ get(type: type).libraries.all.map do |library|
31
+ next nil if library.beta? && !ShopifyCLI::Feature.enabled?(:scripts_beta_languages)
32
+ library.language
33
33
  end.compact
34
34
  end
35
35
 
@@ -4,14 +4,14 @@ module Script
4
4
  module Layers
5
5
  module Domain
6
6
  class ExtensionPoint
7
- attr_reader :type, :beta, :deprecated, :sdks, :domain
7
+ attr_reader :type, :beta, :deprecated, :libraries, :domain
8
8
 
9
9
  def initialize(type, config)
10
10
  @type = type
11
11
  @beta = config["beta"] || false
12
12
  @deprecated = config["deprecated"] || false
13
13
  @domain = config["domain"] || nil
14
- @sdks = ExtensionPointSDKs.new(config)
14
+ @libraries = ExtensionPointLibraries.new(config["libraries"])
15
15
  end
16
16
 
17
17
  def beta?
@@ -26,39 +26,31 @@ module Script
26
26
  @type.gsub("_", "-")
27
27
  end
28
28
 
29
- class ExtensionPointSDKs
29
+ class ExtensionPointLibraries
30
30
  def initialize(config)
31
31
  @config = config
32
32
  end
33
33
 
34
34
  def all
35
- [assemblyscript, rust].compact
35
+ @all ||= @config.map do |language, libray_config|
36
+ ExtensionPointLibrary.new(language, libray_config)
37
+ end
36
38
  end
37
39
 
38
- def assemblyscript
39
- @assemblyscript ||= new_sdk(ExtensionPointAssemblyScriptSDK)
40
- end
41
-
42
- def rust
43
- @rust ||= new_sdk(ExtensionPointRustSDK)
44
- end
45
-
46
- private
47
-
48
- def new_sdk(klass)
49
- config = @config[klass.language]
50
- return nil if config.nil?
51
- klass.new(config)
40
+ def for(language)
41
+ all.find { |ep| ep.language == language }
52
42
  end
53
43
  end
54
44
 
55
- class ExtensionPointSDK
56
- attr_reader :version, :beta, :package
45
+ class ExtensionPointLibrary
46
+ attr_reader :language, :version, :beta, :package, :repo
57
47
 
58
- def initialize(config)
48
+ def initialize(language, config)
49
+ @language = language
59
50
  @beta = config["beta"] || false
60
51
  @package = config["package"]
61
52
  @version = config["package-version"]
53
+ @repo = config["repo"]
62
54
  end
63
55
 
64
56
  def beta?
@@ -68,30 +60,6 @@ module Script
68
60
  def versioned?
69
61
  @version
70
62
  end
71
-
72
- def self.language
73
- raise NotImplementedError
74
- end
75
- end
76
-
77
- class ExtensionPointAssemblyScriptSDK < ExtensionPointSDK
78
- attr_reader :sdk_version, :toolchain_version
79
-
80
- def initialize(config)
81
- super
82
- @sdk_version = config["sdk-version"]
83
- @toolchain_version = config["toolchain-version"]
84
- end
85
-
86
- def self.language
87
- "assemblyscript"
88
- end
89
- end
90
-
91
- class ExtensionPointRustSDK < ExtensionPointSDK
92
- def self.language
93
- "rust"
94
- end
95
63
  end
96
64
  end
97
65
  end
@@ -12,8 +12,10 @@ module Script
12
12
  proxy_response = ShimAPI.query(@ctx, query_name, api_key: @api_key, variables: variables.to_json)
13
13
  raise_if_graphql_failed(proxy_response)
14
14
 
15
- response = proxy_response["data"]["scriptServiceProxy"]
16
- JSON.parse(response) if response
15
+ response = proxy_response.dig("data", "scriptServiceProxy")
16
+ raise Errors::InvalidResponseError unless response
17
+
18
+ JSON.parse(response)
17
19
  end
18
20
 
19
21
  private
@@ -22,7 +22,7 @@ module Script
22
22
  private
23
23
 
24
24
  def script_service_url
25
- if ::ShopifyCLI::Environment.use_spin_partners_instance?
25
+ if ::ShopifyCLI::Environment.use_spin?
26
26
  "https://script-service.#{::ShopifyCLI::Environment.spin_url}"
27
27
  else
28
28
  LOCAL_INSTANCE_URL
@@ -43,6 +43,7 @@ module Script
43
43
  class DependencyInstallError < ScriptProjectError; end
44
44
  class DeprecatedEPError < ScriptProjectError; end
45
45
  class EmptyResponseError < ScriptProjectError; end
46
+ class InvalidResponseError < ScriptProjectError; end
46
47
  class ForbiddenError < ScriptProjectError; end
47
48
  class InvalidContextError < ScriptProjectError; end
48
49
 
@@ -94,7 +95,11 @@ module Script
94
95
  end
95
96
  end
96
97
 
98
+ class InvalidProjectError < ScriptProjectError; end
99
+
97
100
  class ScriptUploadError < ScriptProjectError; end
101
+ class ProjectConfigNotFoundError < ScriptProjectError; end
102
+ class InvalidProjectConfigError < ScriptProjectError; end
98
103
  end
99
104
  end
100
105
  end
@@ -4,99 +4,19 @@ module Script
4
4
  module Layers
5
5
  module Infrastructure
6
6
  module Languages
7
- class AssemblyScriptProjectCreator
8
- include SmartProperties
9
- property! :ctx, accepts: ShopifyCLI::Context
10
- property! :extension_point, accepts: Domain::ExtensionPoint
11
- property! :script_name, accepts: String
12
- property! :path_to_project, accepts: String
7
+ class AssemblyScriptProjectCreator < ProjectCreator
8
+ MIN_NODE_VERSION = "14.5.0" # kept because task_runner uses this
9
+ NPM_SET_REGISTRY_COMMAND = "npm --userconfig ./.npmrc config set @shopify:registry https://registry.npmjs.com"
10
+ NPM_SET_ENGINE_STRICT_COMMAND = "npm --userconfig ./.npmrc config set engine-strict true"
13
11
 
14
- BOOTSTRAP = "npx --no-install shopify-scripts-toolchain-as bootstrap --from %{extension_point} --dest %{base}"
15
- BUILD = "shopify-scripts-toolchain-as build --src src/shopify_main.ts " \
16
- "--binary build/script.wasm --metadata build/metadata.json"
17
- MIN_NODE_VERSION = "14.5.0"
18
- ASC_ARGS = "-- --lib node_modules --optimize --use Date="
19
-
20
- def setup_dependencies
21
- write_npmrc
22
- write_package_json
23
- end
24
-
25
- def bootstrap
26
- command_runner.call(bootstap_command)
27
- end
28
-
29
- private
30
-
31
- def command_runner
32
- @command_runner ||= CommandRunner.new(ctx: ctx)
33
- end
34
-
35
- def write_npmrc
36
- command_runner.call("npm --userconfig ./.npmrc config set @shopify:registry https://registry.npmjs.com")
37
- command_runner.call("npm --userconfig ./.npmrc config set engine-strict true")
38
- end
39
-
40
- def extension_point_version
41
- return extension_point.sdks.assemblyscript.version if extension_point.sdks.assemblyscript.versioned?
42
-
43
- out = command_runner.call("npm -s show #{extension_point.sdks.assemblyscript.package} version --json")
44
- "^#{JSON.parse(out)}"
12
+ def self.config_file
13
+ "package.json"
45
14
  end
46
15
 
47
- def write_package_json
48
- package_json = {
49
- name: script_name,
50
- version: "1.0.0",
51
- devDependencies: dev_dependencies,
52
- scripts: {
53
- test: "asp --summary --verbose",
54
- build: build_command,
55
- },
56
- engines: {
57
- node: ">=#{MIN_NODE_VERSION}",
58
- },
59
- }
60
-
61
- ctx.write("package.json", JSON.pretty_generate(package_json))
62
- end
63
-
64
- def bootstap_command
65
- type = extension_point.dasherize_type
66
- base_command = format(BOOTSTRAP, extension_point: type, base: path_to_project)
67
- domain = extension_point.domain
68
-
69
- if domain.nil?
70
- base_command
71
- else
72
- "#{base_command} --domain #{domain}"
73
- end
74
- end
75
-
76
- def build_command
77
- type = extension_point.dasherize_type
78
- domain = extension_point.domain
79
-
80
- if domain.nil?
81
- "#{BUILD} #{ASC_ARGS}"
82
- else
83
- "#{BUILD} --domain #{domain} --ep #{type} #{ASC_ARGS}"
84
- end
85
- end
86
-
87
- def dev_dependencies
88
- dependencies = {
89
- "@as-pect/cli": "^6.0.0",
90
- "assemblyscript": "^0.18.13",
91
- "@shopify/scripts-toolchain-as": extension_point.sdks.assemblyscript.toolchain_version,
92
- "#{extension_point.sdks.assemblyscript.package}": extension_point_version,
93
- }
94
-
95
- if extension_point.sdks.assemblyscript.sdk_version
96
- dependencies["@shopify/scripts-sdk-as"] = extension_point.sdks.assemblyscript.sdk_version
97
- end
98
-
99
- dependencies
16
+ def setup_dependencies
17
+ super
18
+ command_runner.call(NPM_SET_REGISTRY_COMMAND)
19
+ command_runner.call(NPM_SET_ENGINE_STRICT_COMMAND)
100
20
  end
101
21
  end
102
22
  end
@@ -5,20 +5,85 @@ module Script
5
5
  module Infrastructure
6
6
  module Languages
7
7
  class ProjectCreator
8
- PROJECT_CREATORS = {
9
- "assemblyscript" => AssemblyScriptProjectCreator,
10
- "rust" => RustProjectCreator,
11
- }
12
-
13
- def self.for(ctx, language, extension_point, script_name, path_to_project)
14
- raise Errors::ProjectCreatorNotFoundError unless PROJECT_CREATORS[language]
15
- PROJECT_CREATORS[language].new(
8
+ include SmartProperties
9
+ property! :ctx, accepts: ShopifyCLI::Context
10
+ property! :type, accepts: String
11
+ property! :project_name, accepts: String
12
+ property! :path_to_project, accepts: String
13
+ property! :sparse_checkout_repo, accepts: String
14
+ property! :sparse_checkout_branch, accepts: String
15
+ property! :sparse_checkout_set_path, accepts: String
16
+
17
+ def self.for(
18
+ ctx:,
19
+ language:,
20
+ type:,
21
+ project_name:,
22
+ path_to_project:,
23
+ sparse_checkout_repo:,
24
+ sparse_checkout_branch:,
25
+ sparse_checkout_set_path:
26
+ )
27
+
28
+ project_creators = {
29
+ "assemblyscript" => AssemblyScriptProjectCreator,
30
+ "typescript" => TypeScriptProjectCreator,
31
+ }
32
+
33
+ raise Errors::ProjectCreatorNotFoundError unless project_creators[language]
34
+ project_creators[language].new(
16
35
  ctx: ctx,
17
- extension_point: extension_point,
18
- script_name: script_name,
19
- path_to_project: path_to_project
36
+ type: type,
37
+ project_name: project_name,
38
+ path_to_project: path_to_project,
39
+ sparse_checkout_repo: sparse_checkout_repo,
40
+ sparse_checkout_branch: sparse_checkout_branch,
41
+ sparse_checkout_set_path: sparse_checkout_set_path
42
+ )
43
+ end
44
+
45
+ def self.config_file
46
+ raise NotImplementedError
47
+ end
48
+
49
+ # the sparse checkout process is common to all script types
50
+ def setup_dependencies
51
+ setup_sparse_checkout
52
+ clean
53
+ update_project_name(File.join(path_to_project, self.class.config_file))
54
+ end
55
+
56
+ private
57
+
58
+ def setup_sparse_checkout
59
+ ShopifyCLI::Git.sparse_checkout(
60
+ sparse_checkout_repo,
61
+ sparse_checkout_set_path,
62
+ sparse_checkout_branch,
63
+ ctx
20
64
  )
21
65
  end
66
+
67
+ def clean
68
+ source = File.join(path_to_project, sparse_checkout_set_path, ".")
69
+ FileUtils.cp_r(source, path_to_project)
70
+ ctx.rm_rf(sparse_checkout_set_path.split("/")[0])
71
+ ctx.rm_rf(".git")
72
+ end
73
+
74
+ def update_project_name(config_file)
75
+ raise Errors::ProjectConfigNotFoundError unless File.exist?(config_file)
76
+ upstream_name = "#{type.gsub("_", "-")}-default"
77
+ contents = File.read(config_file)
78
+
79
+ raise Errors::InvalidProjectConfigError unless contents.include?(upstream_name)
80
+ new_contents = contents.gsub(upstream_name, project_name)
81
+ File.write(config_file, new_contents)
82
+ end
83
+
84
+ def command_runner
85
+ @command_runner ||= CommandRunner.new(ctx: ctx)
86
+ end
22
87
  end
23
88
  end
24
89
  end
@@ -7,7 +7,7 @@ module Script
7
7
  class TaskRunner
8
8
  TASK_RUNNERS = {
9
9
  "assemblyscript" => AssemblyScriptTaskRunner,
10
- "rust" => RustTaskRunner,
10
+ "typescript" => TypeScriptTaskRunner,
11
11
  }
12
12
 
13
13
  def self.for(ctx, language, script_name)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ module Languages
7
+ class TypeScriptProjectCreator < ProjectCreator
8
+ MIN_NODE_VERSION = "14.15.0"
9
+ NPM_SET_REGISTRY_COMMAND = "npm --userconfig ./.npmrc config set @shopify:registry https://registry.npmjs.com"
10
+ NPM_SET_ENGINE_STRICT_COMMAND = "npm --userconfig ./.npmrc config set engine-strict true"
11
+
12
+ def self.config_file
13
+ "package.json"
14
+ end
15
+
16
+ def setup_dependencies
17
+ super
18
+ command_runner.call(NPM_SET_REGISTRY_COMMAND)
19
+ command_runner.call(NPM_SET_ENGINE_STRICT_COMMAND)
20
+
21
+ if ctx.file_exist?("yarn.lock")
22
+ ctx.rm("yarn.lock")
23
+ end
24
+
25
+ if ctx.file_exist?("package-lock.json")
26
+ ctx.rm("package-lock.json")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ module Languages
7
+ class TypeScriptTaskRunner
8
+ BYTECODE_FILE = "build/%{name}.wasm"
9
+ METADATA_FILE = "build/metadata.json"
10
+ SCRIPT_SDK_BUILD = "npm run build"
11
+ GEN_METADATA = "npm run gen-metadata"
12
+
13
+ attr_reader :ctx, :script_name
14
+
15
+ def initialize(ctx, script_name)
16
+ @ctx = ctx
17
+ @script_name = script_name
18
+ end
19
+
20
+ def build
21
+ compile
22
+ bytecode
23
+ end
24
+
25
+ def compiled_type
26
+ "wasm"
27
+ end
28
+
29
+ def install_dependencies
30
+ check_node_version!
31
+
32
+ output, status = ctx.capture2e("npm install --no-audit --no-optional --legacy-peer-deps --loglevel error")
33
+ raise Errors::DependencyInstallError, output unless status.success?
34
+ end
35
+
36
+ def dependencies_installed?
37
+ # Assuming if node_modules folder exist at root of script folder, all deps are installed
38
+ ctx.dir_exist?("node_modules")
39
+ end
40
+
41
+ def metadata
42
+ unless @ctx.file_exist?(METADATA_FILE)
43
+ msg = @ctx.message("script.error.metadata_not_found_cause", METADATA_FILE)
44
+ raise Domain::Errors::MetadataNotFoundError, msg
45
+ end
46
+
47
+ raw_contents = File.read(METADATA_FILE)
48
+ Domain::Metadata.create_from_json(@ctx, raw_contents)
49
+ end
50
+
51
+ private
52
+
53
+ def check_node_version!
54
+ output, status = @ctx.capture2e("node", "--version")
55
+ raise Errors::DependencyInstallError, output unless status.success?
56
+
57
+ require "semantic/semantic"
58
+ version = ::Semantic::Version.new(output[1..-1])
59
+ unless version >= ::Semantic::Version.new(TypeScriptProjectCreator::MIN_NODE_VERSION)
60
+ raise Errors::DependencyInstallError,
61
+ "Node version must be >= v#{TypeScriptProjectCreator::MIN_NODE_VERSION}. "\
62
+ "Current version: #{output.strip}."
63
+ end
64
+ end
65
+
66
+ def compile
67
+ check_compilation_dependencies!
68
+ CommandRunner.new(ctx: ctx).call(SCRIPT_SDK_BUILD)
69
+ CommandRunner.new(ctx: ctx).call(GEN_METADATA)
70
+ end
71
+
72
+ def check_compilation_dependencies!
73
+ pkg = JSON.parse(File.read("package.json"))
74
+ build_script = pkg.dig("scripts", "build")
75
+
76
+ raise Errors::BuildScriptNotFoundError,
77
+ "Build script not found" if build_script.nil?
78
+
79
+ unless build_script.start_with?("javy")
80
+ raise Errors::InvalidBuildScriptError, "Invalid build script"
81
+ end
82
+ end
83
+
84
+ def bytecode
85
+ legacy_filename = format(BYTECODE_FILE, name: script_name)
86
+ filename = format(BYTECODE_FILE, name: "index")
87
+
88
+ bytecode_file = if ctx.file_exist?(filename)
89
+ filename
90
+ elsif ctx.file_exist?(legacy_filename)
91
+ legacy_filename
92
+ else
93
+ raise Errors::WebAssemblyBinaryNotFoundError
94
+ end
95
+
96
+ contents = ctx.binread(bytecode_file)
97
+ ctx.rm(bytecode_file)
98
+
99
+ contents
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -129,7 +129,7 @@ module Script
129
129
  end
130
130
 
131
131
  def default_language
132
- Domain::ExtensionPoint::ExtensionPointAssemblyScriptSDK.language
132
+ "assemblyscript"
133
133
  end
134
134
 
135
135
  def validate_metadata!(extension_point_type, language)
@@ -142,6 +142,10 @@ module Script
142
142
  "Check that your build npm script outputs the generated binary to the root of the directory." \
143
143
  "Generated binary should match the script name: <script_name>.wasm",
144
144
 
145
+ project_config_not_found: "Internal error - Script can't be created because the project's config file is missing from the repository.",
146
+
147
+ invalid_project_config: "Internal error - Script can't be created because the project's config file is invalid in the repository.",
148
+
145
149
  script_upload_cause: "Fail to upload script.",
146
150
  script_upload_help: "Try again.",
147
151
  },
@@ -237,6 +237,14 @@ module Script
237
237
  cause_of_error: ShopifyCLI::Context.message("script.error.web_assembly_binary_not_found"),
238
238
  help_suggestion: ShopifyCLI::Context.message("script.error.web_assembly_binary_not_found_suggestion"),
239
239
  }
240
+ when Layers::Infrastructure::Errors::ProjectConfigNotFoundError
241
+ {
242
+ cause_of_error: ShopifyCLI::Context.message("script.error.project_config_not_found"),
243
+ }
244
+ when Layers::Infrastructure::Errors::InvalidProjectConfigError
245
+ {
246
+ cause_of_error: ShopifyCLI::Context.message("script.error.invalid_project_config"),
247
+ }
240
248
  when Layers::Infrastructure::Errors::ScriptUploadError
241
249
  {
242
250
  cause_of_error: ShopifyCLI::Context.message("script.error.script_upload_cause"),
@@ -1,4 +1,5 @@
1
1
  require "shopify_cli"
2
+ require "securerandom"
2
3
 
3
4
  module ShopifyCLI
4
5
  class API
@@ -54,6 +55,7 @@ module ShopifyCLI
54
55
  # we delay this require so as to avoid a performance hit on starting the CLI
55
56
  require "shopify_cli/http_request"
56
57
  headers = default_headers.merge(headers)
58
+ ctx.debug("#{method} #{uri} with X-Request-Id: #{headers["X-Request-Id"]}")
57
59
  response = if method == "POST"
58
60
  HttpRequest.post(uri, body, headers)
59
61
  elsif method == "PUT"
@@ -82,6 +84,7 @@ module ShopifyCLI
82
84
  raise APIRequestUnexpectedError.new("#{response.code}\n#{response.body}", response: response)
83
85
  end
84
86
  rescue Errno::ETIMEDOUT, Timeout::Error
87
+ ctx.debug("timeout in #{method} #{uri} with X-Request-Id: #{headers["X-Request-Id"]}")
85
88
  raise APIRequestTimeoutError.new("Timeout")
86
89
  end.retry_after(APIRequestRetriableError, retries: 3) do |e|
87
90
  sleep(1) if e.is_a?(APIRequestThrottledError)
@@ -109,6 +112,7 @@ module ShopifyCLI
109
112
  "User-Agent" => "Shopify CLI; v=#{ShopifyCLI::VERSION}",
110
113
  "Sec-CH-UA" => "Shopify CLI; v=#{ShopifyCLI::VERSION} sha=#{ShopifyCLI.sha}",
111
114
  "Sec-CH-UA-PLATFORM" => ctx.os.to_s,
115
+ "X-Request-Id" => SecureRandom.uuid,
112
116
  }.tap do |headers|
113
117
  headers["X-Shopify-Cli-Employee"] = "1" if Shopifolk.acting_as_shopify_organization?
114
118
  end.merge(auth_headers(token))
@@ -0,0 +1,16 @@
1
+ module ShopifyCLI
2
+ class Command
3
+ class AppSubCommand < SubCommand
4
+ class << self
5
+ def call_help(*)
6
+ output = help
7
+ if respond_to?(:extended_help)
8
+ output += "\n"
9
+ output += extended_help
10
+ end
11
+ @ctx.puts(output)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end