shopify-cli 2.7.0 → 2.7.4

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +2 -2
  3. data/.github/workflows/shopify.yml +1 -1
  4. data/.gitignore +2 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +46 -0
  7. data/Codespace.dockerfile +2 -2
  8. data/Gemfile.lock +4 -4
  9. data/Rakefile +27 -0
  10. data/Tests.dockerfile +2 -2
  11. data/dev.yml +3 -3
  12. data/ext/javy/hashes/javy-arm-macos-v0.1.0.gz.sha256 +1 -0
  13. data/ext/javy/hashes/javy-x86_64-linux-v0.1.0.gz.sha256 +1 -0
  14. data/ext/javy/hashes/javy-x86_64-macos-v0.1.0.gz.sha256 +1 -0
  15. data/ext/javy/hashes/javy-x86_64-windows-v0.1.0.gz.sha256 +1 -0
  16. data/ext/javy/javy.rb +204 -0
  17. data/ext/javy/version +1 -0
  18. data/lib/graphql/get_extension_registrations.graphql +27 -0
  19. data/lib/project_types/extension/cli.rb +27 -2
  20. data/lib/project_types/extension/commands/build.rb +10 -14
  21. data/lib/project_types/extension/commands/create.rb +3 -6
  22. data/lib/project_types/extension/commands/push.rb +36 -8
  23. data/lib/project_types/extension/extension_project.rb +1 -1
  24. data/lib/project_types/extension/features/argo_serve.rb +6 -5
  25. data/lib/project_types/extension/forms/questions/ask_registration.rb +6 -2
  26. data/lib/project_types/extension/loaders/project.rb +29 -0
  27. data/lib/project_types/extension/loaders/specification_handler.rb +22 -0
  28. data/lib/project_types/extension/messages/messages.rb +4 -2
  29. data/lib/project_types/extension/models/app.rb +1 -1
  30. data/lib/project_types/extension/models/development_server.rb +2 -2
  31. data/lib/project_types/extension/models/specification_handlers/default.rb +4 -0
  32. data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
  33. data/lib/project_types/extension/tasks/execute_commands/base.rb +13 -0
  34. data/lib/project_types/extension/tasks/execute_commands/build.rb +29 -0
  35. data/lib/project_types/extension/tasks/execute_commands/create.rb +33 -0
  36. data/lib/project_types/extension/tasks/execute_commands/serve.rb +35 -0
  37. data/lib/project_types/extension/tasks/merge_server_config.rb +33 -22
  38. data/lib/project_types/rails/commands/create.rb +2 -4
  39. data/lib/project_types/script/cli.rb +9 -1
  40. data/lib/project_types/script/commands/connect.rb +19 -0
  41. data/lib/project_types/script/commands/create.rb +1 -3
  42. data/lib/project_types/script/commands/javy.rb +29 -0
  43. data/lib/project_types/script/commands/push.rb +2 -1
  44. data/lib/project_types/script/config/extension_points.yml +12 -30
  45. data/lib/project_types/script/forms/ask_app.rb +32 -0
  46. data/lib/project_types/script/forms/ask_org.rb +30 -0
  47. data/lib/project_types/script/forms/ask_script_uuid.rb +22 -0
  48. data/lib/project_types/script/forms/run_against_shopify_org.rb +14 -0
  49. data/lib/project_types/script/graphql/app_script_set.graphql +2 -2
  50. data/lib/project_types/script/layers/application/build_script.rb +0 -1
  51. data/lib/project_types/script/layers/application/connect_app.rb +79 -0
  52. data/lib/project_types/script/layers/application/create_script.rb +17 -17
  53. data/lib/project_types/script/layers/application/push_script.rb +1 -1
  54. data/lib/project_types/script/layers/domain/errors.rb +1 -4
  55. data/lib/project_types/script/layers/domain/push_package.rb +3 -3
  56. data/lib/project_types/script/layers/domain/{script_json.rb → script_config.rb} +2 -2
  57. data/lib/project_types/script/layers/domain/script_project.rb +5 -1
  58. data/lib/project_types/script/layers/infrastructure/errors.rb +36 -7
  59. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +0 -4
  60. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +0 -4
  61. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +2 -2
  62. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +125 -27
  63. data/lib/project_types/script/layers/infrastructure/script_service.rb +11 -11
  64. data/lib/project_types/script/messages/messages.rb +32 -4
  65. data/lib/project_types/script/ui/error_handler.rb +31 -21
  66. data/lib/project_types/theme/commands/pull.rb +3 -0
  67. data/lib/project_types/theme/commands/push.rb +7 -1
  68. data/lib/project_types/theme/commands/serve.rb +1 -1
  69. data/lib/project_types/theme/messages/messages.rb +35 -1
  70. data/lib/project_types/theme/ui/sync_progress_bar.rb +2 -2
  71. data/lib/shopify_cli/command/project_command.rb +20 -7
  72. data/lib/shopify_cli/command.rb +6 -0
  73. data/lib/shopify_cli/commands/app/create/node.rb +1 -3
  74. data/lib/shopify_cli/commands/app/create/rails.rb +1 -3
  75. data/lib/shopify_cli/constants.rb +7 -0
  76. data/lib/shopify_cli/context.rb +11 -1
  77. data/lib/shopify_cli/environment.rb +4 -0
  78. data/lib/shopify_cli/form.rb +2 -0
  79. data/lib/shopify_cli/git.rb +2 -0
  80. data/lib/shopify_cli/identity_auth.rb +18 -0
  81. data/lib/shopify_cli/messages/messages.rb +9 -2
  82. data/lib/shopify_cli/partners_api/app_extensions/job.rb +36 -0
  83. data/lib/shopify_cli/partners_api/app_extensions.rb +46 -0
  84. data/lib/shopify_cli/partners_api/organizations.rb +2 -5
  85. data/lib/shopify_cli/partners_api.rb +2 -8
  86. data/lib/shopify_cli/project.rb +8 -7
  87. data/lib/shopify_cli/resources/env_file.rb +13 -5
  88. data/lib/shopify_cli/services/app/create/node_service.rb +2 -0
  89. data/lib/shopify_cli/services/app/create/php_service.rb +1 -1
  90. data/lib/shopify_cli/services/app/create/rails_service.rb +3 -1
  91. data/lib/shopify_cli/services/app/serve/node_service.rb +1 -1
  92. data/lib/shopify_cli/services/app/serve/rails_service.rb +1 -1
  93. data/lib/shopify_cli/tasks/ensure_authenticated.rb +9 -3
  94. data/lib/shopify_cli/theme/dev_server/cdn_fonts.rb +73 -0
  95. data/lib/shopify_cli/theme/dev_server/hot-reload.js +38 -9
  96. data/lib/shopify_cli/theme/dev_server/proxy/template_param_builder.rb +84 -0
  97. data/lib/shopify_cli/theme/dev_server/proxy.rb +9 -15
  98. data/lib/shopify_cli/theme/dev_server.rb +32 -19
  99. data/lib/shopify_cli/theme/syncer/error_reporter.rb +45 -0
  100. data/lib/shopify_cli/theme/syncer/operation.rb +56 -0
  101. data/lib/shopify_cli/theme/syncer/standard_reporter.rb +32 -0
  102. data/lib/shopify_cli/theme/syncer.rb +40 -39
  103. data/lib/shopify_cli/theme/theme.rb +31 -19
  104. data/lib/shopify_cli/thread_pool/job.rb +27 -0
  105. data/lib/shopify_cli/thread_pool.rb +37 -0
  106. data/lib/shopify_cli/tunnel.rb +26 -22
  107. data/lib/shopify_cli/version.rb +1 -1
  108. data/shopify-cli.gemspec +1 -1
  109. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +3 -1
  110. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +1 -1
  111. metadata +34 -8
  112. data/lib/graphql/all_orgs_with_extensions.graphql +0 -37
  113. data/lib/project_types/extension/tasks/run_extension_command.rb +0 -82
  114. data/lib/project_types/script/tasks/ensure_env.rb +0 -106
@@ -6,7 +6,7 @@ mutation AppScriptSet(
6
6
  $force: Boolean,
7
7
  $schemaMajorVersion: String,
8
8
  $schemaMinorVersion: String,
9
- $scriptJsonVersion: String!,
9
+ $scriptConfigVersion: String!,
10
10
  $configurationUi: Boolean!,
11
11
  $configurationDefinition: String!,
12
12
  $moduleUploadUrl: String!,
@@ -20,7 +20,7 @@ mutation AppScriptSet(
20
20
  force: $force
21
21
  schemaMajorVersion: $schemaMajorVersion
22
22
  schemaMinorVersion: $schemaMinorVersion,
23
- scriptJsonVersion: $scriptJsonVersion,
23
+ scriptConfigVersion: $scriptConfigVersion,
24
24
  configurationUi: $configurationUi,
25
25
  configurationDefinition: $configurationDefinition,
26
26
  moduleUploadUrl: $moduleUploadUrl,
@@ -23,7 +23,6 @@ module Script
23
23
  ctx.puts("\n{{red:#{e.message}}}")
24
24
  end
25
25
  errors = [
26
- Infrastructure::Errors::InvalidBuildScriptError,
27
26
  Infrastructure::Errors::BuildScriptNotFoundError,
28
27
  Infrastructure::Errors::WebAssemblyBinaryNotFoundError,
29
28
  ]
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shopify_cli"
4
+
5
+ module Script
6
+ module Layers
7
+ module Application
8
+ class ConnectApp
9
+ class << self
10
+ def call(ctx:, force: false, strict: false)
11
+ script_project_repo = Layers::Infrastructure::ScriptProjectRepository.new(ctx: ctx)
12
+ script_project = script_project_repo.get
13
+
14
+ return false if script_project.env_valid? && !force
15
+
16
+ if ShopifyCLI::Shopifolk.check && Forms::RunAgainstShopifyOrg.ask(ctx, nil, nil).response
17
+ ShopifyCLI::Shopifolk.act_as_shopify_organization
18
+ end
19
+
20
+ org =
21
+ if partner_proxy_bypass
22
+ stubbed_org
23
+ else
24
+ orgs = ShopifyCLI::PartnersAPI::Organizations.fetch_with_app(ctx)
25
+ Forms::AskOrg.ask(ctx, orgs, nil).org
26
+ end
27
+
28
+ app = Forms::AskApp.ask(
29
+ ctx,
30
+ {
31
+ apps: org["apps"],
32
+ acting_as_shopify_organization: ShopifyCLI::Shopifolk.acting_as_shopify_organization?,
33
+ },
34
+ nil
35
+ ).app
36
+
37
+ script_service = Layers::Infrastructure::ServiceLocator.script_service(ctx: ctx, api_key: app["apiKey"])
38
+ extension_point_type = script_project.extension_point_type
39
+ scripts = script_service.get_app_scripts(extension_point_type: extension_point_type)
40
+
41
+ uuid = Forms::AskScriptUuid.ask(ctx, scripts, nil)&.uuid
42
+
43
+ if strict && uuid.nil?
44
+ ctx.abort(ctx.message("script.connect.missing_script"))
45
+ end
46
+
47
+ script_project_repo.create_env(
48
+ api_key: app["apiKey"],
49
+ secret: app["apiSecretKeys"].first["secret"],
50
+ uuid: uuid
51
+ )
52
+ ctx.done(ctx.message("script.connect.connected", app["title"]))
53
+
54
+ true
55
+ end
56
+
57
+ private
58
+
59
+ def partner_proxy_bypass
60
+ !ENV["BYPASS_PARTNERS_PROXY"].nil?
61
+ end
62
+
63
+ def stubbed_org
64
+ {
65
+ "apps" => [
66
+ {
67
+ "appType" => "custom",
68
+ "apiKey" => "stubbed-api-key",
69
+ "apiSecretKeys" => [{ "secret" => "stubbed-api-secret" }],
70
+ "title" => "Fake App (Not connected to Partners)",
71
+ },
72
+ ],
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -8,11 +8,14 @@ module Script
8
8
  class CreateScript
9
9
  class << self
10
10
  def call(ctx:, language:, sparse_checkout_branch:, script_name:, extension_point_type:)
11
- raise Infrastructure::Errors::ScriptProjectAlreadyExistsError, script_name if ctx.dir_exist?(script_name)
11
+ script_project_repo = Infrastructure::ScriptProjectRepository.new(
12
+ ctx: ctx,
13
+ directory: script_name,
14
+ initial_directory: ctx.root
15
+ )
12
16
 
13
- in_new_directory_context(ctx, script_name) do
17
+ in_new_directory_context(script_project_repo) do
14
18
  extension_point = ExtensionPoints.get(type: extension_point_type)
15
- script_project_repo = Infrastructure::ScriptProjectRepository.new(ctx: ctx)
16
19
  project = script_project_repo.create(
17
20
  script_name: script_name,
18
21
  extension_point_type: extension_point_type,
@@ -36,7 +39,7 @@ module Script
36
39
  )
37
40
 
38
41
  install_dependencies(ctx, language, script_name, project_creator)
39
- script_project_repo.update_or_create_script_json(title: script_name)
42
+ script_project_repo.update_script_config(title: script_name)
40
43
  project
41
44
  end
42
45
  end
@@ -62,19 +65,16 @@ module Script
62
65
  ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
63
66
  end
64
67
 
65
- def in_new_directory_context(ctx, directory)
66
- initial_directory = ctx.root
67
- begin
68
- ctx.mkdir_p(directory)
69
- ctx.chdir(directory)
70
- yield
71
- rescue
72
- ctx.chdir(initial_directory)
73
- ctx.rm_r(directory)
74
- raise
75
- ensure
76
- ctx.chdir(initial_directory)
77
- end
68
+ def in_new_directory_context(script_project_repo)
69
+ script_project_repo.create_project_directory
70
+ yield
71
+ rescue Infrastructure::Errors::ScriptProjectAlreadyExistsError
72
+ raise
73
+ rescue
74
+ script_project_repo.delete_project_directory
75
+ raise
76
+ ensure
77
+ script_project_repo.change_to_initial_directory
78
78
  end
79
79
  end
80
80
  end
@@ -43,7 +43,7 @@ module Script
43
43
  extension_point_type: package.extension_point_type,
44
44
  force: force,
45
45
  metadata: package.metadata,
46
- script_json: package.script_json,
46
+ script_config: package.script_config,
47
47
  module_upload_url: module_upload_url,
48
48
  library: package.library,
49
49
  )
@@ -14,7 +14,7 @@ module Script
14
14
  end
15
15
  end
16
16
 
17
- class MissingScriptJsonFieldError < ScriptProjectError
17
+ class MissingScriptConfigFieldError < ScriptProjectError
18
18
  attr_reader :field
19
19
  def initialize(field)
20
20
  super()
@@ -22,9 +22,6 @@ module Script
22
22
  end
23
23
  end
24
24
 
25
- class InvalidScriptJsonDefinitionError < ScriptProjectError; end
26
- class NoScriptJsonFile < ScriptProjectError; end
27
-
28
25
  class ScriptNotFoundError < ScriptProjectError
29
26
  attr_reader :script_name, :extension_point_type
30
27
  def initialize(extension_point_type, script_name)
@@ -7,7 +7,7 @@ module Script
7
7
  attr_reader :id,
8
8
  :uuid,
9
9
  :extension_point_type,
10
- :script_json,
10
+ :script_config,
11
11
  :script_content,
12
12
  :compiled_type,
13
13
  :metadata,
@@ -20,7 +20,7 @@ module Script
20
20
  script_content:,
21
21
  compiled_type: nil,
22
22
  metadata:,
23
- script_json:,
23
+ script_config:,
24
24
  library:
25
25
  )
26
26
  @id = id
@@ -29,7 +29,7 @@ module Script
29
29
  @script_content = script_content
30
30
  @compiled_type = compiled_type
31
31
  @metadata = metadata
32
- @script_json = script_json
32
+ @script_config = script_config
33
33
  @library = library
34
34
  end
35
35
  end
@@ -3,7 +3,7 @@
3
3
  module Script
4
4
  module Layers
5
5
  module Domain
6
- class ScriptJson
6
+ class ScriptConfig
7
7
  attr_reader :content, :version, :title, :description, :configuration_ui, :configuration
8
8
 
9
9
  REQUIRED_FIELDS = %w(version title)
@@ -23,7 +23,7 @@ module Script
23
23
 
24
24
  def validate_content!(content)
25
25
  REQUIRED_FIELDS.each do |field|
26
- raise Errors::MissingScriptJsonFieldError, field if content[field].nil?
26
+ raise Errors::MissingScriptConfigFieldError, field if content[field].nil?
27
27
  end
28
28
  end
29
29
  end
@@ -15,7 +15,7 @@ module Script
15
15
  property! :script_name, accepts: String
16
16
  property! :language, accepts: String
17
17
 
18
- property :script_json, accepts: ScriptJson
18
+ property :script_config, accepts: ScriptConfig
19
19
 
20
20
  def initialize(*)
21
21
  super
@@ -43,6 +43,10 @@ module Script
43
43
  !raw_uuid.nil?
44
44
  end
45
45
 
46
+ def env_valid?
47
+ api_key && api_secret && uuid_defined?
48
+ end
49
+
46
50
  private
47
51
 
48
52
  def raw_uuid
@@ -5,9 +5,9 @@ module Script
5
5
  module Infrastructure
6
6
  module Errors
7
7
  class BuildError < ScriptProjectError; end
8
- class ScriptJsonSyntaxError < ScriptProjectError; end
8
+ class ScriptConfigSyntaxError < ScriptProjectError; end
9
9
 
10
- class ScriptJsonMissingKeysError < ScriptProjectError
10
+ class ScriptConfigMissingKeysError < ScriptProjectError
11
11
  attr_reader :missing_keys
12
12
  def initialize(missing_keys)
13
13
  super()
@@ -15,7 +15,7 @@ module Script
15
15
  end
16
16
  end
17
17
 
18
- class ScriptJsonInvalidValueError < ScriptProjectError
18
+ class ScriptConfigInvalidValueError < ScriptProjectError
19
19
  attr_reader :valid_input_modes
20
20
  def initialize(valid_input_modes)
21
21
  super()
@@ -23,7 +23,7 @@ module Script
23
23
  end
24
24
  end
25
25
 
26
- class ScriptJsonFieldsMissingKeysError < ScriptProjectError
26
+ class ScriptConfigFieldsMissingKeysError < ScriptProjectError
27
27
  attr_reader :missing_keys
28
28
  def initialize(missing_keys)
29
29
  super()
@@ -31,7 +31,7 @@ module Script
31
31
  end
32
32
  end
33
33
 
34
- class ScriptJsonFieldsInvalidValueError < ScriptProjectError
34
+ class ScriptConfigFieldsInvalidValueError < ScriptProjectError
35
35
  attr_reader :valid_types
36
36
  def initialize(valid_types)
37
37
  super()
@@ -39,6 +39,29 @@ module Script
39
39
  end
40
40
  end
41
41
 
42
+ class InvalidScriptConfigYmlDefinitionError < ScriptProjectError; end
43
+
44
+ class InvalidScriptJsonDefinitionError < ScriptProjectError; end
45
+
46
+ class MissingScriptConfigYmlFieldError < ScriptProjectError
47
+ attr_reader :field
48
+ def initialize(field)
49
+ super()
50
+ @field = field
51
+ end
52
+ end
53
+
54
+ class MissingScriptJsonFieldError < ScriptProjectError
55
+ attr_reader :field
56
+ def initialize(field)
57
+ super()
58
+ @field = field
59
+ end
60
+ end
61
+
62
+ class NoScriptConfigYmlFileError < ScriptProjectError; end
63
+ class NoScriptConfigFileError < ScriptProjectError; end
64
+
42
65
  class APILibraryNotFoundError < ScriptProjectError
43
66
  attr_reader :library_name
44
67
  def initialize(library_name)
@@ -56,8 +79,15 @@ module Script
56
79
  end
57
80
  end
58
81
 
82
+ class DeprecatedEPError < ScriptProjectError
83
+ attr_reader(:extension_point)
84
+ def initialize(extension_point)
85
+ super()
86
+ @extension_point = extension_point
87
+ end
88
+ end
89
+
59
90
  class DependencyInstallError < ScriptProjectError; end
60
- class DeprecatedEPError < ScriptProjectError; end
61
91
  class EmptyResponseError < ScriptProjectError; end
62
92
  class InvalidResponseError < ScriptProjectError; end
63
93
  class ForbiddenError < ScriptProjectError; end
@@ -102,7 +132,6 @@ module Script
102
132
  class ScriptProjectAlreadyExistsError < ScriptProjectError; end
103
133
  class TaskRunnerNotFoundError < ScriptProjectError; end
104
134
  class BuildScriptNotFoundError < ScriptProjectError; end
105
- class InvalidBuildScriptError < ScriptProjectError; end
106
135
 
107
136
  class WebAssemblyBinaryNotFoundError < ScriptProjectError
108
137
  def initialize
@@ -98,10 +98,6 @@ module Script
98
98
 
99
99
  raise Errors::BuildScriptNotFoundError,
100
100
  "Build script not found" if build_script.nil?
101
-
102
- unless build_script.start_with?("shopify-scripts")
103
- raise Errors::InvalidBuildScriptError, "Invalid build script"
104
- end
105
101
  end
106
102
 
107
103
  def bytecode
@@ -100,10 +100,6 @@ module Script
100
100
 
101
101
  raise Errors::BuildScriptNotFoundError,
102
102
  "Build script not found" if build_script.nil?
103
-
104
- unless build_script.start_with?("javy")
105
- raise Errors::InvalidBuildScriptError, "Invalid build script"
106
- end
107
103
  end
108
104
 
109
105
  def bytecode
@@ -18,7 +18,7 @@ module Script
18
18
  script_content: script_content,
19
19
  compiled_type: compiled_type,
20
20
  metadata: metadata,
21
- script_json: script_project.script_json,
21
+ script_config: script_project.script_config,
22
22
  library: library
23
23
  )
24
24
  end
@@ -34,7 +34,7 @@ module Script
34
34
  extension_point_type: script_project.extension_point_type,
35
35
  script_content: script_content,
36
36
  metadata: metadata,
37
- script_json: script_project.script_json,
37
+ script_config: script_project.script_config,
38
38
  library: library
39
39
  )
40
40
  end
@@ -6,10 +6,26 @@ module Script
6
6
  class ScriptProjectRepository
7
7
  include SmartProperties
8
8
  property! :ctx, accepts: ShopifyCLI::Context
9
+ property :directory, accepts: String
10
+ property :initial_directory, accepts: String
9
11
 
10
- SCRIPT_JSON_FILENAME = "script.json"
11
12
  MUTABLE_ENV_VALUES = %i(uuid)
12
13
 
14
+ def create_project_directory
15
+ raise Infrastructure::Errors::ScriptProjectAlreadyExistsError, directory if ctx.dir_exist?(directory)
16
+ ctx.mkdir_p(directory)
17
+ change_directory(directory: directory)
18
+ end
19
+
20
+ def delete_project_directory
21
+ change_to_initial_directory
22
+ ctx.rm_r(directory)
23
+ end
24
+
25
+ def change_to_initial_directory
26
+ change_directory(directory: initial_directory)
27
+ end
28
+
13
29
  def create(script_name:, extension_point_type:, language:)
14
30
  validate_metadata!(extension_point_type, language)
15
31
 
@@ -40,7 +56,7 @@ module Script
40
56
  script_name: script_name,
41
57
  extension_point_type: extension_point_type,
42
58
  language: language,
43
- script_json: ScriptJsonRepository.new(ctx: ctx).get
59
+ script_config: script_config_repository.get!
44
60
  )
45
61
  end
46
62
 
@@ -58,7 +74,7 @@ module Script
58
74
  script_name: script_name,
59
75
  extension_point_type: extension_point_type,
60
76
  language: language,
61
- script_json: ScriptJsonRepository.new(ctx: ctx).get,
77
+ script_config: script_config_repository.get!,
62
78
  )
63
79
  end
64
80
 
@@ -77,14 +93,12 @@ module Script
77
93
  script_name: script_name,
78
94
  extension_point_type: extension_point_type,
79
95
  language: language,
80
- script_json: ScriptJsonRepository.new(ctx: ctx).get,
96
+ script_config: script_config_repository.get!,
81
97
  )
82
98
  end
83
99
 
84
- def update_or_create_script_json(title:)
85
- script_json = ScriptJsonRepository
86
- .new(ctx: ctx)
87
- .update_or_create(title: title)
100
+ def update_script_config(title:)
101
+ script_config = script_config_repository.update!(title: title)
88
102
 
89
103
  Domain::ScriptProject.new(
90
104
  id: ctx.root,
@@ -92,12 +106,16 @@ module Script
92
106
  script_name: script_name,
93
107
  extension_point_type: extension_point_type,
94
108
  language: language,
95
- script_json: script_json,
109
+ script_config: script_config,
96
110
  )
97
111
  end
98
112
 
99
113
  private
100
114
 
115
+ def change_directory(directory:)
116
+ ctx.chdir(directory)
117
+ end
118
+
101
119
  def capture_io(&block)
102
120
  CLI::UI::StdoutRouter::Capture.new(&block).run
103
121
  end
@@ -140,40 +158,120 @@ module Script
140
158
  end
141
159
  end
142
160
 
143
- class ScriptJsonRepository
161
+ def script_config_repository
162
+ @script_config_repository ||= begin
163
+ supported_repos = [
164
+ ScriptConfigYmlRepository.new(ctx: ctx),
165
+ ScriptJsonRepository.new(ctx: ctx),
166
+ ]
167
+ repo = supported_repos.find(&:active?)
168
+ raise Infrastructure::Errors::NoScriptConfigYmlFileError if repo.nil?
169
+ repo
170
+ end
171
+ end
172
+
173
+ class ScriptConfigRepository
144
174
  include SmartProperties
145
175
  property! :ctx, accepts: ShopifyCLI::Context
146
176
 
147
- def get
148
- current_script_json || raise(Domain::Errors::NoScriptJsonFile)
177
+ def active?
178
+ ctx.file_exist?(filename)
179
+ end
180
+
181
+ def get!
182
+ raise Infrastructure::Errors::NoScriptConfigFileError unless active?
183
+
184
+ content = ctx.read(filename)
185
+ hash = file_content_to_hash(content)
186
+
187
+ from_h(hash)
188
+ end
189
+
190
+ def update!(title:)
191
+ hash = get!.content
192
+ update_hash(hash: hash, title: title)
193
+
194
+ ctx.write(filename, hash_to_file_content(hash))
195
+
196
+ from_h(hash)
197
+ end
198
+
199
+ private
200
+
201
+ def update_hash(hash:, title:)
202
+ hash["version"] ||= "2"
203
+ hash["title"] = title
204
+ end
205
+
206
+ def from_h(hash)
207
+ Domain::ScriptConfig.new(content: hash)
208
+ rescue Domain::Errors::MissingScriptConfigFieldError => e
209
+ raise missing_field_error, e.field
149
210
  end
150
211
 
151
- def update_or_create(title:)
152
- json = current_script_json&.content || {}
153
- json["version"] ||= "1"
154
- json["title"] = title
212
+ # to be implemented by subclasses
213
+ def filename
214
+ raise NotImplementedError
215
+ end
155
216
 
156
- ctx.write(SCRIPT_JSON_FILENAME, JSON.pretty_generate(json))
217
+ def file_content_to_hash(file_content)
218
+ raise NotImplementedError
219
+ end
157
220
 
158
- Domain::ScriptJson.new(content: json)
221
+ def hash_to_file_content(hash)
222
+ raise NotImplementedError
159
223
  end
160
224
 
225
+ def missing_field_error
226
+ raise NotImplementedError
227
+ end
228
+ end
229
+
230
+ class ScriptConfigYmlRepository < ScriptConfigRepository
161
231
  private
162
232
 
163
- def current_script_json
164
- return nil unless ctx.file_exist?(SCRIPT_JSON_FILENAME)
233
+ def filename
234
+ "script.config.yml"
235
+ end
236
+
237
+ def file_content_to_hash(file_content)
238
+ begin
239
+ hash = YAML.load(file_content)
240
+ rescue Psych::SyntaxError
241
+ raise Errors::InvalidScriptConfigYmlDefinitionError
242
+ end
243
+ raise Errors::InvalidScriptConfigYmlDefinitionError unless hash.is_a?(Hash)
244
+ hash
245
+ end
246
+
247
+ def hash_to_file_content(hash)
248
+ YAML.dump(hash)
249
+ end
165
250
 
166
- content = ctx.read(SCRIPT_JSON_FILENAME)
167
- raise Domain::Errors::InvalidScriptJsonDefinitionError unless valid_script_json?(content)
251
+ def missing_field_error
252
+ Errors::MissingScriptConfigYmlFieldError
253
+ end
254
+ end
168
255
 
169
- Domain::ScriptJson.new(content: JSON.parse(content))
256
+ class ScriptJsonRepository < ScriptConfigRepository
257
+ private
258
+
259
+ def filename
260
+ "script.json"
170
261
  end
171
262
 
172
- def valid_script_json?(content)
173
- JSON.parse(content)
174
- true
263
+ def file_content_to_hash(file_content)
264
+ JSON.parse(file_content)
175
265
  rescue JSON::ParserError
176
- false
266
+ raise Errors::InvalidScriptJsonDefinitionError
267
+ end
268
+
269
+ def hash_to_file_content(hash)
270
+ JSON.pretty_generate(hash)
271
+ end
272
+
273
+ def missing_field_error
274
+ Errors::MissingScriptJsonFieldError
177
275
  end
178
276
  end
179
277
  end
@@ -17,7 +17,7 @@ module Script
17
17
  extension_point_type:,
18
18
  force: false,
19
19
  metadata:,
20
- script_json:,
20
+ script_config:,
21
21
  module_upload_url:,
22
22
  library:
23
23
  )
@@ -25,14 +25,14 @@ module Script
25
25
  variables = {
26
26
  uuid: uuid,
27
27
  extensionPointName: extension_point_type.upcase,
28
- title: script_json.title,
29
- description: script_json.description,
28
+ title: script_config.title,
29
+ description: script_config.description,
30
30
  force: force,
31
31
  schemaMajorVersion: metadata.schema_major_version.to_s, # API expects string value
32
32
  schemaMinorVersion: metadata.schema_minor_version.to_s, # API expects string value
33
- scriptJsonVersion: script_json.version,
34
- configurationUi: script_json.configuration_ui,
35
- configurationDefinition: script_json.configuration&.to_json,
33
+ scriptConfigVersion: script_config.version,
34
+ configurationUi: script_config.configuration_ui,
35
+ configurationDefinition: script_config.configuration&.to_json,
36
36
  moduleUploadUrl: module_upload_url,
37
37
  library: {
38
38
  language: library[:language],
@@ -47,19 +47,19 @@ module Script
47
47
  if user_errors.any? { |e| e["tag"] == "already_exists_error" }
48
48
  raise Errors::ScriptRepushError, uuid
49
49
  elsif (e = user_errors.any? { |err| err["tag"] == "configuration_definition_syntax_error" })
50
- raise Errors::ScriptJsonSyntaxError
50
+ raise Errors::ScriptConfigSyntaxError
51
51
  elsif (e = user_errors.find { |err| err["tag"] == "configuration_definition_missing_keys_error" })
52
- raise Errors::ScriptJsonMissingKeysError, e["message"]
52
+ raise Errors::ScriptConfigMissingKeysError, e["message"]
53
53
  elsif (e = user_errors.find { |err| err["tag"] == "configuration_definition_invalid_value_error" })
54
- raise Errors::ScriptJsonInvalidValueError, e["message"]
54
+ raise Errors::ScriptConfigInvalidValueError, e["message"]
55
55
  elsif (e = user_errors.find do |err|
56
56
  err["tag"] == "configuration_definition_schema_field_missing_keys_error"
57
57
  end)
58
- raise Errors::ScriptJsonFieldsMissingKeysError, e["message"]
58
+ raise Errors::ScriptConfigFieldsMissingKeysError, e["message"]
59
59
  elsif (e = user_errors.find do |err|
60
60
  err["tag"] == "configuration_definition_schema_field_invalid_value_error"
61
61
  end)
62
- raise Errors::ScriptJsonFieldsInvalidValueError, e["message"]
62
+ raise Errors::ScriptConfigFieldsInvalidValueError, e["message"]
63
63
  elsif user_errors.find { |err| %w(not_use_msgpack_error schema_version_argument_error).include?(err["tag"]) }
64
64
  raise Domain::Errors::MetadataValidationError
65
65
  else