shopify-cli 1.10.0 → 1.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  3. data/.github/workflows/release.yml +2 -4
  4. data/CHANGELOG.md +31 -1
  5. data/Gemfile.lock +1 -1
  6. data/lib/project_types/extension/cli.rb +6 -2
  7. data/lib/project_types/extension/commands/serve.rb +69 -1
  8. data/lib/project_types/extension/commands/tunnel.rb +3 -1
  9. data/lib/project_types/extension/extension_project.rb +1 -0
  10. data/lib/project_types/extension/features/argo.rb +15 -24
  11. data/lib/project_types/extension/features/argo_runtime.rb +91 -0
  12. data/lib/project_types/extension/features/argo_serve.rb +35 -27
  13. data/lib/project_types/extension/features/argo_serve_options.rb +42 -0
  14. data/lib/project_types/extension/messages/messages.rb +3 -0
  15. data/lib/project_types/extension/models/npm_package.rb +14 -0
  16. data/lib/project_types/extension/models/specification.rb +1 -0
  17. data/lib/project_types/extension/models/specification_handlers/checkout_argo_extension.rb +18 -0
  18. data/lib/project_types/extension/models/specification_handlers/default.rb +33 -3
  19. data/lib/project_types/extension/tasks/choose_next_available_port.rb +36 -0
  20. data/lib/project_types/extension/tasks/configure_features.rb +2 -0
  21. data/lib/project_types/extension/tasks/find_npm_packages.rb +106 -0
  22. data/lib/project_types/script/cli.rb +14 -13
  23. data/lib/project_types/script/commands/push.rb +8 -3
  24. data/lib/project_types/script/config/extension_points.yml +0 -3
  25. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +9 -3
  26. data/lib/project_types/script/layers/application/create_script.rb +6 -5
  27. data/lib/project_types/script/layers/application/push_script.rb +2 -1
  28. data/lib/project_types/script/layers/domain/errors.rb +6 -13
  29. data/lib/project_types/script/layers/domain/push_package.rb +4 -8
  30. data/lib/project_types/script/layers/domain/script_json.rb +32 -0
  31. data/lib/project_types/script/layers/domain/script_project.rb +1 -1
  32. data/lib/project_types/script/layers/infrastructure/command_runner.rb +19 -0
  33. data/lib/project_types/script/layers/infrastructure/errors.rb +25 -20
  34. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +105 -0
  35. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +103 -0
  36. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +26 -0
  37. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +73 -0
  38. data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +60 -0
  39. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +21 -0
  40. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +6 -8
  41. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +44 -59
  42. data/lib/project_types/script/layers/infrastructure/script_service.rb +21 -15
  43. data/lib/project_types/script/messages/messages.rb +28 -22
  44. data/lib/project_types/script/tasks/ensure_env.rb +32 -3
  45. data/lib/project_types/script/ui/error_handler.rb +37 -36
  46. data/lib/shopify-cli/admin_api.rb +7 -4
  47. data/lib/shopify-cli/context.rb +13 -0
  48. data/lib/shopify-cli/messages/messages.rb +48 -43
  49. data/lib/shopify-cli/method_object.rb +4 -4
  50. data/lib/shopify-cli/oauth.rb +7 -1
  51. data/lib/shopify-cli/partners_api.rb +7 -4
  52. data/lib/shopify-cli/partners_api/organizations.rb +3 -3
  53. data/lib/shopify-cli/resources/env_file.rb +1 -1
  54. data/lib/shopify-cli/shopifolk.rb +1 -1
  55. data/lib/shopify-cli/tasks/select_org_and_shop.rb +6 -4
  56. data/lib/shopify-cli/tunnel.rb +22 -1
  57. data/lib/shopify-cli/version.rb +1 -1
  58. metadata +17 -11
  59. data/lib/project_types/extension/features/argo_renderer_package.rb +0 -47
  60. data/lib/project_types/script/layers/domain/config_ui.rb +0 -16
  61. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +0 -100
  62. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +0 -95
  63. data/lib/project_types/script/layers/infrastructure/project_creator.rb +0 -24
  64. data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +0 -72
  65. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +0 -59
  66. data/lib/project_types/script/layers/infrastructure/task_runner.rb +0 -19
@@ -8,7 +8,8 @@ module Script
8
8
  def call(ctx:, force:)
9
9
  script_project_repo = Infrastructure::ScriptProjectRepository.new(ctx: ctx)
10
10
  script_project = script_project_repo.get
11
- task_runner = Infrastructure::TaskRunner.for(ctx, script_project.language, script_project.script_name)
11
+ task_runner = Infrastructure::Languages::TaskRunner
12
+ .for(ctx, script_project.language, script_project.script_name)
12
13
 
13
14
  ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
14
15
  BuildScript.call(ctx: ctx, task_runner: task_runner, script_project: script_project)
@@ -14,21 +14,16 @@ module Script
14
14
  end
15
15
  end
16
16
 
17
- class InvalidConfigUiDefinitionError < ScriptProjectError
18
- attr_reader :filename
19
- def initialize(filename)
17
+ class MissingScriptJsonFieldError < ScriptProjectError
18
+ attr_reader :field
19
+ def initialize(field)
20
20
  super()
21
- @filename = filename
21
+ @field = field
22
22
  end
23
23
  end
24
24
 
25
- class MissingSpecifiedConfigUiDefinitionError < ScriptProjectError
26
- attr_reader :filename
27
- def initialize(filename)
28
- super()
29
- @filename = filename
30
- end
31
- end
25
+ class InvalidScriptJsonDefinitionError < ScriptProjectError; end
26
+ class NoScriptJsonFile < ScriptProjectError; end
32
27
 
33
28
  class ScriptNotFoundError < ScriptProjectError
34
29
  attr_reader :script_name, :extension_point_type
@@ -39,8 +34,6 @@ module Script
39
34
  end
40
35
  end
41
36
 
42
- class ServiceFailureError < ScriptProjectError; end
43
-
44
37
  class MetadataNotFoundError < ScriptProjectError; end
45
38
 
46
39
  class MetadataValidationError < ScriptProjectError; end
@@ -7,8 +7,7 @@ module Script
7
7
  attr_reader :id,
8
8
  :uuid,
9
9
  :extension_point_type,
10
- :script_name,
11
- :config_ui,
10
+ :script_json,
12
11
  :script_content,
13
12
  :compiled_type,
14
13
  :metadata
@@ -17,33 +16,30 @@ module Script
17
16
  id:,
18
17
  uuid:,
19
18
  extension_point_type:,
20
- script_name:,
21
19
  script_content:,
22
20
  compiled_type:,
23
21
  metadata:,
24
- config_ui:
22
+ script_json:
25
23
  )
26
24
  @id = id
27
25
  @uuid = uuid
28
26
  @extension_point_type = extension_point_type
29
- @script_name = script_name
30
27
  @script_content = script_content
31
28
  @compiled_type = compiled_type
32
29
  @metadata = metadata
33
- @config_ui = config_ui
30
+ @script_json = script_json
34
31
  end
35
32
 
36
33
  def push(script_service, api_key, force)
37
34
  script_service.push(
38
35
  uuid: @uuid,
39
36
  extension_point_type: @extension_point_type,
40
- script_name: @script_name,
41
37
  script_content: @script_content,
42
38
  compiled_type: @compiled_type,
43
39
  api_key: api_key,
44
40
  force: force,
45
41
  metadata: @metadata,
46
- config_ui: @config_ui,
42
+ script_json: @script_json,
47
43
  )
48
44
  end
49
45
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Domain
6
+ class ScriptJson
7
+ attr_reader :content, :version, :title, :description, :configuration_ui, :configuration
8
+
9
+ REQUIRED_FIELDS = %w(version title)
10
+
11
+ def initialize(content:)
12
+ validate_content!(content)
13
+
14
+ @content = content
15
+ @version = @content["version"].to_s
16
+ @title = @content["title"]
17
+ @description = @content["description"]
18
+ @configuration_ui = @content["configurationUi"]
19
+ @configuration = @content["configuration"]
20
+ end
21
+
22
+ private
23
+
24
+ def validate_content!(content)
25
+ REQUIRED_FIELDS.each do |field|
26
+ raise Errors::MissingScriptJsonFieldError, field if content[field].nil?
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -15,7 +15,7 @@ module Script
15
15
  property! :script_name, accepts: String
16
16
  property! :language, accepts: String
17
17
 
18
- property :config_ui, accepts: ConfigUi
18
+ property :script_json, accepts: ScriptJson
19
19
 
20
20
  def initialize(*)
21
21
  super
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ class CommandRunner
7
+ include SmartProperties
8
+
9
+ property! :ctx, accepts: ShopifyCli::Context
10
+
11
+ def call(cmd)
12
+ out, status = ctx.capture2e(cmd)
13
+ raise Errors::SystemCallFailureError.new(out: out.chomp, cmd: cmd) unless status.success?
14
+ out
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -6,40 +6,36 @@ module Script
6
6
  module Errors
7
7
  class AppNotInstalledError < ScriptProjectError; end
8
8
  class BuildError < ScriptProjectError; end
9
- class ConfigUiSyntaxError < ScriptProjectError; end
9
+ class ScriptJsonSyntaxError < ScriptProjectError; end
10
10
 
11
- class ConfigUiMissingKeysError < ScriptProjectError
12
- attr_reader :filename, :missing_keys
13
- def initialize(filename, missing_keys)
11
+ class ScriptJsonMissingKeysError < ScriptProjectError
12
+ attr_reader :missing_keys
13
+ def initialize(missing_keys)
14
14
  super()
15
- @filename = filename
16
15
  @missing_keys = missing_keys
17
16
  end
18
17
  end
19
18
 
20
- class ConfigUiInvalidInputModeError < ScriptProjectError
21
- attr_reader :filename, :valid_input_modes
22
- def initialize(filename, valid_input_modes)
19
+ class ScriptJsonInvalidValueError < ScriptProjectError
20
+ attr_reader :valid_input_modes
21
+ def initialize(valid_input_modes)
23
22
  super()
24
- @filename = filename
25
23
  @valid_input_modes = valid_input_modes
26
24
  end
27
25
  end
28
26
 
29
- class ConfigUiFieldsMissingKeysError < ScriptProjectError
30
- attr_reader :filename, :missing_keys
31
- def initialize(filename, missing_keys)
27
+ class ScriptJsonFieldsMissingKeysError < ScriptProjectError
28
+ attr_reader :missing_keys
29
+ def initialize(missing_keys)
32
30
  super()
33
- @filename = filename
34
31
  @missing_keys = missing_keys
35
32
  end
36
33
  end
37
34
 
38
- class ConfigUiFieldsInvalidTypeError < ScriptProjectError
39
- attr_reader :filename, :valid_types
40
- def initialize(filename, valid_types)
35
+ class ScriptJsonFieldsInvalidValueError < ScriptProjectError
36
+ attr_reader :valid_types
37
+ def initialize(valid_types)
41
38
  super()
42
- @filename = filename
43
39
  @valid_types = valid_types
44
40
  end
45
41
  end
@@ -69,11 +65,20 @@ module Script
69
65
 
70
66
  class ProjectCreatorNotFoundError < ScriptProjectError; end
71
67
 
68
+ class SystemCallFailureError < ScriptProjectError
69
+ attr_reader :out, :cmd
70
+ def initialize(out:, cmd:)
71
+ super(out)
72
+ @out = out
73
+ @cmd = cmd
74
+ end
75
+ end
76
+
72
77
  class ScriptRepushError < ScriptProjectError
73
- attr_reader :api_key
74
- def initialize(api_key)
78
+ attr_reader :uuid
79
+ def initialize(uuid)
75
80
  super()
76
- @api_key = api_key
81
+ @uuid = uuid
77
82
  end
78
83
  end
79
84
 
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
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
13
+
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 show #{extension_point.sdks.assemblyscript.package} version --json")
44
+ "^#{JSON.parse(out)}"
45
+ end
46
+
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
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ module Languages
7
+ class AssemblyScriptTaskRunner
8
+ BYTECODE_FILE = "build/%{name}.wasm"
9
+ METADATA_FILE = "build/metadata.json"
10
+ SCRIPT_SDK_BUILD = "npm run build"
11
+
12
+ attr_reader :ctx, :script_name
13
+
14
+ def initialize(ctx, script_name)
15
+ @ctx = ctx
16
+ @script_name = script_name
17
+ end
18
+
19
+ def build
20
+ compile
21
+ bytecode
22
+ end
23
+
24
+ def compiled_type
25
+ "wasm"
26
+ end
27
+
28
+ def install_dependencies
29
+ check_node_version!
30
+
31
+ output, status = ctx.capture2e("npm install --no-audit --no-optional --legacy-peer-deps --loglevel error")
32
+ raise Errors::DependencyInstallError, output unless status.success?
33
+ end
34
+
35
+ def dependencies_installed?
36
+ # Assuming if node_modules folder exist at root of script folder, all deps are installed
37
+ ctx.dir_exist?("node_modules")
38
+ end
39
+
40
+ def metadata
41
+ unless @ctx.file_exist?(METADATA_FILE)
42
+ msg = @ctx.message("script.error.metadata_not_found_cause", METADATA_FILE)
43
+ raise Domain::Errors::MetadataNotFoundError, msg
44
+ end
45
+
46
+ raw_contents = File.read(METADATA_FILE)
47
+ Domain::Metadata.create_from_json(@ctx, raw_contents)
48
+ end
49
+
50
+ private
51
+
52
+ def check_node_version!
53
+ output, status = @ctx.capture2e("node", "--version")
54
+ raise Errors::DependencyInstallError, output unless status.success?
55
+
56
+ require "semantic/semantic"
57
+ version = ::Semantic::Version.new(output[1..-1])
58
+ unless version >= ::Semantic::Version.new(AssemblyScriptProjectCreator::MIN_NODE_VERSION)
59
+ raise Errors::DependencyInstallError,
60
+ "Node version must be >= v#{AssemblyScriptProjectCreator::MIN_NODE_VERSION}. "\
61
+ "Current version: #{output.strip}."
62
+ end
63
+ end
64
+
65
+ def compile
66
+ check_compilation_dependencies!
67
+ CommandRunner.new(ctx: ctx).call(SCRIPT_SDK_BUILD)
68
+ end
69
+
70
+ def check_compilation_dependencies!
71
+ pkg = JSON.parse(File.read("package.json"))
72
+ build_script = pkg.dig("scripts", "build")
73
+
74
+ raise Errors::BuildScriptNotFoundError,
75
+ "Build script not found" if build_script.nil?
76
+
77
+ unless build_script.start_with?("shopify-scripts")
78
+ raise Errors::InvalidBuildScriptError, "Invalid build script"
79
+ end
80
+ end
81
+
82
+ def bytecode
83
+ legacy_filename = format(BYTECODE_FILE, name: script_name)
84
+ filename = format(BYTECODE_FILE, name: "script")
85
+
86
+ bytecode_file = if ctx.file_exist?(filename)
87
+ filename
88
+ elsif ctx.file_exist?(legacy_filename)
89
+ legacy_filename
90
+ else
91
+ raise Errors::WebAssemblyBinaryNotFoundError
92
+ end
93
+
94
+ contents = ctx.binread(bytecode_file)
95
+ ctx.rm(bytecode_file)
96
+
97
+ contents
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end