shopify-cli 2.5.0 → 2.6.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +11 -0
  4. data/Dockerfile +0 -2
  5. data/Gemfile.lock +22 -16
  6. data/Rakefile +7 -16
  7. data/bin/console +11 -0
  8. data/bin/shopify +15 -3
  9. data/dev.yml +3 -0
  10. data/ext/shopify-cli/extconf.rb +2 -0
  11. data/lib/project_types/extension/cli.rb +2 -0
  12. data/lib/project_types/extension/commands/build.rb +2 -1
  13. data/lib/project_types/extension/features/argo.rb +1 -1
  14. data/lib/project_types/extension/features/argo_serve.rb +1 -0
  15. data/lib/project_types/extension/models/development_server.rb +4 -0
  16. data/lib/project_types/extension/models/development_server_requirements.rb +1 -2
  17. data/lib/project_types/extension/models/specification_handlers/default.rb +4 -0
  18. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
  19. data/lib/project_types/extension/tasks/find_npm_packages.rb +2 -2
  20. data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
  21. data/lib/project_types/extension/tasks/run_extension_command.rb +26 -10
  22. data/lib/project_types/node/commands/serve.rb +9 -1
  23. data/lib/project_types/node/messages/messages.rb +3 -0
  24. data/lib/project_types/script/cli.rb +4 -3
  25. data/lib/project_types/script/commands/create.rb +2 -0
  26. data/lib/project_types/script/config/extension_points.yml +30 -29
  27. data/lib/project_types/script/layers/application/create_script.rb +32 -12
  28. data/lib/project_types/script/layers/application/extension_points.rb +3 -3
  29. data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
  30. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +4 -2
  31. data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +1 -1
  32. data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
  33. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
  34. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
  35. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
  36. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
  37. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
  38. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +1 -1
  39. data/lib/project_types/script/messages/messages.rb +4 -0
  40. data/lib/project_types/script/ui/error_handler.rb +8 -0
  41. data/lib/shopify_cli/command/app_sub_command.rb +16 -0
  42. data/lib/shopify_cli/constants.rb +33 -5
  43. data/lib/shopify_cli/core/executor.rb +5 -1
  44. data/lib/shopify_cli/environment.rb +35 -4
  45. data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
  46. data/lib/shopify_cli/exception_reporter.rb +55 -0
  47. data/lib/shopify_cli/git.rb +30 -0
  48. data/lib/shopify_cli/messages/messages.rb +27 -1
  49. data/lib/shopify_cli/method_object.rb +11 -4
  50. data/lib/shopify_cli/migrator/migration.rb +27 -0
  51. data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
  52. data/lib/shopify_cli/migrator.rb +48 -0
  53. data/lib/shopify_cli/version.rb +1 -1
  54. data/lib/shopify_cli.rb +11 -3
  55. data/shopify-cli.gemspec +9 -1
  56. data/utilities/docker.rb +47 -0
  57. data/utilities/utilities.rb +5 -0
  58. metadata +31 -6
  59. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
  60. 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"),
@@ -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