shopify-cli 2.7.0 → 2.7.4

Sign up to get free protection for your applications and to get access to all the features.
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