shopify-cli 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +15 -2
  3. data/CHANGELOG.md +4 -1
  4. data/Gemfile.lock +3 -3
  5. data/dev.yml +3 -0
  6. data/lib/graphql/extension_create.graphql +17 -2
  7. data/lib/project_types/extension/cli.rb +2 -0
  8. data/lib/project_types/extension/commands/extension_command.rb +4 -4
  9. data/lib/project_types/extension/commands/push.rb +2 -2
  10. data/lib/project_types/extension/commands/register.rb +4 -3
  11. data/lib/project_types/extension/commands/serve.rb +1 -35
  12. data/lib/project_types/extension/extension_project.rb +15 -4
  13. data/lib/project_types/extension/extension_project_keys.rb +2 -1
  14. data/lib/project_types/extension/features/argo.rb +6 -0
  15. data/lib/project_types/extension/features/argo_renderer_package.rb +32 -0
  16. data/lib/project_types/extension/features/argo_serve.rb +69 -0
  17. data/lib/project_types/extension/messages/message_loading.rb +3 -1
  18. data/lib/project_types/extension/models/registration.rb +1 -0
  19. data/lib/project_types/extension/models/specification.rb +2 -0
  20. data/lib/project_types/extension/models/specification_handlers/default.rb +8 -0
  21. data/lib/project_types/extension/tasks/configure_features.rb +2 -0
  22. data/lib/project_types/extension/tasks/converters/registration_converter.rb +2 -0
  23. data/lib/project_types/node/commands/generate.rb +0 -22
  24. data/lib/project_types/script/cli.rb +2 -8
  25. data/lib/project_types/script/commands/create.rb +0 -7
  26. data/lib/project_types/script/commands/push.rb +2 -2
  27. data/lib/project_types/script/config/extension_points.yml +2 -0
  28. data/lib/project_types/script/errors.rb +0 -19
  29. data/lib/project_types/script/forms/create.rb +3 -14
  30. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +0 -3
  31. data/lib/project_types/script/graphql/script_service_proxy.graphql +1 -2
  32. data/lib/project_types/script/layers/application/build_script.rb +1 -2
  33. data/lib/project_types/script/layers/application/create_script.rb +30 -51
  34. data/lib/project_types/script/layers/application/extension_points.rb +3 -2
  35. data/lib/project_types/script/layers/application/push_script.rb +2 -4
  36. data/lib/project_types/script/layers/domain/extension_point.rb +56 -46
  37. data/lib/project_types/script/layers/domain/metadata.rb +18 -25
  38. data/lib/project_types/script/layers/domain/push_package.rb +0 -4
  39. data/lib/project_types/script/layers/domain/script_project.rb +34 -0
  40. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +6 -2
  41. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +4 -4
  42. data/lib/project_types/script/layers/infrastructure/errors.rb +12 -10
  43. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +10 -12
  44. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +1 -1
  45. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +145 -0
  46. data/lib/project_types/script/layers/infrastructure/script_service.rb +9 -72
  47. data/lib/project_types/script/messages/messages.rb +0 -47
  48. data/lib/project_types/script/ui/error_handler.rb +7 -24
  49. data/lib/shopify-cli/context.rb +28 -0
  50. data/lib/shopify-cli/version.rb +1 -1
  51. metadata +6 -10
  52. data/lib/project_types/script/commands/disable.rb +0 -25
  53. data/lib/project_types/script/commands/enable.rb +0 -80
  54. data/lib/project_types/script/graphql/shop_script_delete.graphql +0 -14
  55. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +0 -28
  56. data/lib/project_types/script/layers/application/disable_script.rb +0 -21
  57. data/lib/project_types/script/layers/application/enable_script.rb +0 -23
  58. data/lib/project_types/script/layers/infrastructure/config_ui_repository.rb +0 -46
  59. data/lib/project_types/script/script_project.rb +0 -64
@@ -6,19 +6,17 @@ module Script
6
6
  class PushScript
7
7
  class << self
8
8
  def call(ctx:, force:)
9
- script_project = ScriptProject.current
9
+ script_project = Infrastructure::ScriptProjectRepository.new(ctx: ctx).get
10
10
  task_runner = Infrastructure::TaskRunner.for(ctx, script_project.language, script_project.script_name)
11
- config_ui = Infrastructure::ConfigUiRepository.new(ctx: ctx).get_config_ui(script_project.config_ui_file)
12
11
 
13
12
  ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
14
- BuildScript.call(ctx: ctx, task_runner: task_runner, script_project: script_project, config_ui: config_ui)
13
+ BuildScript.call(ctx: ctx, task_runner: task_runner, script_project: script_project)
15
14
 
16
15
  UI::PrintingSpinner.spin(ctx, ctx.message("script.application.pushing")) do |p_ctx, spinner|
17
16
  package = Infrastructure::PushPackageRepository.new(ctx: p_ctx).get_push_package(
18
17
  script_project: script_project,
19
18
  compiled_type: task_runner.compiled_type,
20
19
  metadata: task_runner.metadata,
21
- config_ui: config_ui,
22
20
  )
23
21
  package.push(Infrastructure::ScriptService.new(ctx: p_ctx), script_project.api_key, force)
24
22
  spinner.update_title(p_ctx.message("script.application.pushed"))
@@ -4,15 +4,20 @@ module Script
4
4
  module Layers
5
5
  module Domain
6
6
  class ExtensionPoint
7
- attr_reader :type, :deprecated, :sdks, :domain
7
+ attr_reader :type, :beta, :deprecated, :sdks, :domain
8
8
 
9
9
  def initialize(type, config)
10
10
  @type = type
11
+ @beta = config["beta"] || false
11
12
  @deprecated = config["deprecated"] || false
12
13
  @domain = config["domain"] || nil
13
14
  @sdks = ExtensionPointSDKs.new(config)
14
15
  end
15
16
 
17
+ def beta?
18
+ @beta
19
+ end
20
+
16
21
  def deprecated?
17
22
  @deprecated
18
23
  end
@@ -20,68 +25,73 @@ module Script
20
25
  def dasherize_type
21
26
  @type.gsub("_", "-")
22
27
  end
23
- end
24
28
 
25
- class ExtensionPointSDKs
26
- def initialize(config)
27
- @config = config
28
- end
29
+ class ExtensionPointSDKs
30
+ def initialize(config)
31
+ @config = config
32
+ end
29
33
 
30
- def all
31
- [assemblyscript, rust].compact
32
- end
34
+ def all
35
+ [assemblyscript, rust].compact
36
+ end
33
37
 
34
- def assemblyscript
35
- @assemblyscript ||= new_sdk(ExtensionPointAssemblyScriptSDK)
36
- end
38
+ def assemblyscript
39
+ @assemblyscript ||= new_sdk(ExtensionPointAssemblyScriptSDK)
40
+ end
37
41
 
38
- def rust
39
- @rust ||= new_sdk(ExtensionPointRustSDK)
40
- end
42
+ def rust
43
+ @rust ||= new_sdk(ExtensionPointRustSDK)
44
+ end
41
45
 
42
- private
46
+ private
43
47
 
44
- def new_sdk(klass)
45
- config = @config[klass.language]
46
- return nil if config.nil?
47
- klass.new(config)
48
+ def new_sdk(klass)
49
+ config = @config[klass.language]
50
+ return nil if config.nil?
51
+ klass.new(config)
52
+ end
48
53
  end
49
- end
50
54
 
51
- class ExtensionPointSDK
52
- attr_reader :beta, :package
55
+ class ExtensionPointSDK
56
+ attr_reader :version, :beta, :package
53
57
 
54
- def initialize(config)
55
- @beta = config["beta"] || false
56
- @package = config["package"]
57
- end
58
+ def initialize(config)
59
+ @beta = config["beta"] || false
60
+ @package = config["package"]
61
+ @version = config["package-version"]
62
+ end
58
63
 
59
- def beta?
60
- @beta
61
- end
64
+ def beta?
65
+ @beta
66
+ end
67
+
68
+ def versioned?
69
+ @version
70
+ end
62
71
 
63
- def self.language
64
- raise NotImplementedError
72
+ def self.language
73
+ raise NotImplementedError
74
+ end
65
75
  end
66
- end
67
76
 
68
- class ExtensionPointAssemblyScriptSDK < ExtensionPointSDK
69
- attr_reader :sdk_version, :toolchain_version
77
+ class ExtensionPointAssemblyScriptSDK < ExtensionPointSDK
78
+ attr_reader :sdk_version, :toolchain_version
70
79
 
71
- def initialize(config)
72
- super
73
- @sdk_version = config["sdk-version"]
74
- @toolchain_version = config["toolchain-version"]
75
- end
80
+ def initialize(config)
81
+ super
82
+ @sdk_version = config["sdk-version"]
83
+ @toolchain_version = config["toolchain-version"]
84
+ end
76
85
 
77
- def self.language
78
- "assemblyscript"
86
+ def self.language
87
+ "assemblyscript"
88
+ end
79
89
  end
80
- end
81
90
 
82
- class ExtensionPointRustSDK < ExtensionPointSDK
83
- def self.language
84
- "rust"
91
+ class ExtensionPointRustSDK < ExtensionPointSDK
92
+ def self.language
93
+ "rust"
94
+ end
85
95
  end
86
96
  end
87
97
  end
@@ -14,39 +14,32 @@ module Script
14
14
 
15
15
  class << self
16
16
  def create_from_json(ctx, metadata_json)
17
+ err_tag = nil
17
18
  metadata_hash = JSON.parse(metadata_json)
18
- schema_versions = metadata_hash["schemaVersions"]
19
- if schema_versions.nil?
20
- err_msg = "script.error.metadata_schema_versions_missing"
21
- raise ::Script::Layers::Domain::Errors::MetadataValidationError, ctx.message(err_msg)
22
- end
23
- # Scripts may be attached to more than one EP in the future but not right now
24
- unless schema_versions.count == 1
25
- err_msg = "script.error.metadata_schema_versions_single_key"
26
- raise ::Script::Layers::Domain::Errors::MetadataValidationError, ctx.message(err_msg)
27
- end
28
19
 
29
- _, version = schema_versions.first
20
+ use_msgpack = !!metadata_hash.dig("flags", "use_msgpack")
21
+ schema_versions = metadata_hash["schemaVersions"] || {}
22
+
23
+ version = schema_versions.values.first || {}
30
24
  schema_major_version = version["major"]
31
25
  schema_minor_version = version["minor"]
32
- if schema_major_version.nil?
33
- err_msg = "script.error.metadata_schema_versions_missing_major"
34
- raise ::Script::Layers::Domain::Errors::MetadataValidationError, ctx.message(err_msg)
35
- end
36
26
 
37
- if schema_minor_version.nil?
38
- err_msg = "script.error.metadata_schema_versions_missing_minor"
39
- raise ::Script::Layers::Domain::Errors::MetadataValidationError, ctx.message(err_msg)
27
+ if schema_versions.empty?
28
+ err_tag = "script.error.metadata_schema_versions_missing"
29
+ elsif schema_versions.count != 1
30
+ # Scripts may be attached to more than one EP in the future but not right now
31
+ err_tag = "script.error.metadata_schema_versions_single_key"
32
+ elsif schema_major_version.nil?
33
+ err_tag = "script.error.metadata_schema_versions_missing_major"
34
+ elsif schema_minor_version.nil?
35
+ err_tag = "script.error.metadata_schema_versions_missing_minor"
40
36
  end
41
37
 
42
- use_msgpack = !!metadata_hash.dig("flags", "use_msgpack")
43
-
44
38
  Metadata.new(schema_major_version, schema_minor_version, use_msgpack)
45
- rescue ::Script::Layers::Domain::Errors::MetadataValidationError
46
- raise
47
- rescue
48
- err_msg = "script.error.metadata_validation_cause"
49
- raise ::Script::Layers::Domain::Errors::MetadataValidationError, ctx.message(err_msg)
39
+ rescue JSON::ParserError
40
+ err_tag = "script.error.metadata_validation_cause"
41
+ ensure
42
+ raise Errors::MetadataValidationError, ctx.message(err_tag) if err_tag
50
43
  end
51
44
  end
52
45
  end
@@ -7,7 +7,6 @@ module Script
7
7
  attr_reader :id,
8
8
  :extension_point_type,
9
9
  :script_name,
10
- :description,
11
10
  :config_ui,
12
11
  :script_content,
13
12
  :compiled_type,
@@ -17,7 +16,6 @@ module Script
17
16
  id:,
18
17
  extension_point_type:,
19
18
  script_name:,
20
- description:,
21
19
  script_content:,
22
20
  compiled_type:,
23
21
  metadata:,
@@ -26,7 +24,6 @@ module Script
26
24
  @id = id
27
25
  @extension_point_type = extension_point_type
28
26
  @script_name = script_name
29
- @description = description
30
27
  @script_content = script_content
31
28
  @compiled_type = compiled_type
32
29
  @metadata = metadata
@@ -37,7 +34,6 @@ module Script
37
34
  script_service.push(
38
35
  extension_point_type: @extension_point_type,
39
36
  script_name: @script_name,
40
- description: @description,
41
37
  script_content: @script_content,
42
38
  compiled_type: @compiled_type,
43
39
  api_key: api_key,
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Domain
6
+ class ScriptProject
7
+ include SmartProperties
8
+
9
+ property! :id, accepts: String
10
+ property :env, accepts: ShopifyCli::Resources::EnvFile
11
+
12
+ property! :extension_point_type, accepts: String
13
+ property! :script_name, accepts: String
14
+ property! :language, accepts: String
15
+
16
+ property :config_ui, accepts: ConfigUi
17
+
18
+ def initialize(*)
19
+ super
20
+
21
+ ShopifyCli::Core::Monorail.metadata = {
22
+ "script_name" => script_name,
23
+ "extension_point_type" => extension_point_type,
24
+ "language" => language,
25
+ }
26
+ end
27
+
28
+ def api_key
29
+ env[:api_key]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -38,9 +38,13 @@ module Script
38
38
  end
39
39
 
40
40
  def extension_point_version
41
+ if extension_point.sdks.assemblyscript.versioned?
42
+ return extension_point.sdks.assemblyscript.version
43
+ end
44
+
41
45
  out, status = ctx.capture2e("npm show #{extension_point.sdks.assemblyscript.package} version --json")
42
46
  raise Domain::Errors::ServiceFailureError, out unless status.success?
43
- JSON.parse(out)
47
+ "^#{JSON.parse(out)}"
44
48
  end
45
49
 
46
50
  def write_package_json
@@ -51,7 +55,7 @@ module Script
51
55
  "devDependencies": {
52
56
  "@shopify/scripts-sdk-as": "#{extension_point.sdks.assemblyscript.sdk_version}",
53
57
  "@shopify/scripts-toolchain-as": "#{extension_point.sdks.assemblyscript.toolchain_version}",
54
- "#{extension_point.sdks.assemblyscript.package}": "^#{extension_point_version}",
58
+ "#{extension_point.sdks.assemblyscript.package}": "#{extension_point_version}",
55
59
  "@as-pect/cli": "^6.0.0",
56
60
  "assemblyscript": "^0.18.13"
57
61
  },
@@ -81,11 +81,11 @@ module Script
81
81
  end
82
82
 
83
83
  def bytecode
84
- blob = format(BYTECODE_FILE, name: script_name)
85
- raise Errors::WebAssemblyBinaryNotFoundError unless @ctx.file_exist?(blob)
84
+ filename = format(BYTECODE_FILE, name: script_name)
85
+ raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(filename)
86
86
 
87
- contents = File.read(blob)
88
- @ctx.rm(blob)
87
+ contents = ctx.binread(filename)
88
+ ctx.rm(filename)
89
89
 
90
90
  contents
91
91
  end
@@ -5,8 +5,6 @@ module Script
5
5
  module Infrastructure
6
6
  module Errors
7
7
  class AppNotInstalledError < ScriptProjectError; end
8
- class AppScriptNotPushedError < ScriptProjectError; end
9
- class AppScriptUndefinedError < ScriptProjectError; end
10
8
  class BuildError < ScriptProjectError; end
11
9
  class ConfigUiSyntaxError < ScriptProjectError; end
12
10
 
@@ -29,8 +27,19 @@ module Script
29
27
  end
30
28
 
31
29
  class DependencyInstallError < ScriptProjectError; end
30
+ class DeprecatedEPError < ScriptProjectError; end
32
31
  class EmptyResponseError < ScriptProjectError; end
33
32
  class ForbiddenError < ScriptProjectError; end
33
+ class InvalidContextError < ScriptProjectError; end
34
+
35
+ class InvalidLanguageError < ScriptProjectError
36
+ attr_reader :language, :extension_point_type
37
+ def initialize(language, extension_point_type)
38
+ super()
39
+ @language = language
40
+ @extension_point_type = extension_point_type
41
+ end
42
+ end
34
43
 
35
44
  class GraphqlError < ScriptProjectError
36
45
  attr_reader :errors
@@ -50,15 +59,8 @@ module Script
50
59
  end
51
60
  end
52
61
 
53
- class ScriptServiceUserError < ScriptProjectError
54
- def initialize(query_name, errors)
55
- super("Failed performing #{query_name}. Errors: #{errors}.")
56
- end
57
- end
58
-
62
+ class ScriptProjectAlreadyExistsError < ScriptProjectError; end
59
63
  class ShopAuthenticationError < ScriptProjectError; end
60
- class ShopScriptConflictError < ScriptProjectError; end
61
- class ShopScriptUndefinedError < ScriptProjectError; end
62
64
  class TaskRunnerNotFoundError < ScriptProjectError; end
63
65
  class BuildScriptNotFoundError < ScriptProjectError; end
64
66
  class InvalidBuildScriptError < ScriptProjectError; end
@@ -7,37 +7,35 @@ module Script
7
7
  include SmartProperties
8
8
  property! :ctx, accepts: ShopifyCli::Context
9
9
 
10
- def create_push_package(script_project:, script_content:, compiled_type:, metadata:, config_ui:)
11
- build_file_path = file_path(script_project.script_name, compiled_type)
10
+ def create_push_package(script_project:, script_content:, compiled_type:, metadata:)
11
+ build_file_path = file_path(script_project.id, script_project.script_name, compiled_type)
12
12
  write_to_path(build_file_path, script_content)
13
13
 
14
14
  Domain::PushPackage.new(
15
15
  id: build_file_path,
16
16
  extension_point_type: script_project.extension_point_type,
17
17
  script_name: script_project.script_name,
18
- description: script_project.description,
19
18
  script_content: script_content,
20
19
  compiled_type: compiled_type,
21
20
  metadata: metadata,
22
- config_ui: config_ui,
21
+ config_ui: script_project.config_ui,
23
22
  )
24
23
  end
25
24
 
26
- def get_push_package(script_project:, compiled_type:, metadata:, config_ui:)
27
- build_file_path = file_path(script_project.script_name, compiled_type)
25
+ def get_push_package(script_project:, compiled_type:, metadata:)
26
+ build_file_path = file_path(script_project.id, script_project.script_name, compiled_type)
28
27
  raise Domain::PushPackageNotFoundError unless ctx.file_exist?(build_file_path)
29
28
 
30
- script_content = File.read(build_file_path)
29
+ script_content = ctx.binread(build_file_path)
31
30
 
32
31
  Domain::PushPackage.new(
33
32
  id: build_file_path,
34
33
  extension_point_type: script_project.extension_point_type,
35
34
  script_name: script_project.script_name,
36
- description: script_project.description,
37
35
  script_content: script_content,
38
36
  compiled_type: compiled_type,
39
37
  metadata: metadata,
40
- config_ui: config_ui,
38
+ config_ui: script_project.config_ui,
41
39
  )
42
40
  end
43
41
 
@@ -45,11 +43,11 @@ module Script
45
43
 
46
44
  def write_to_path(path, content)
47
45
  ctx.mkdir_p(File.dirname(path))
48
- ctx.write(path, content)
46
+ ctx.binwrite(path, content)
49
47
  end
50
48
 
51
- def file_path(script_name, compiled_type)
52
- "#{ScriptProject.current.directory}/build/#{script_name}.#{compiled_type}"
49
+ def file_path(path_to_script, script_name, compiled_type)
50
+ "#{path_to_script}/build/#{script_name}.#{compiled_type}"
53
51
  end
54
52
  end
55
53
  end
@@ -51,7 +51,7 @@ module Script
51
51
  binary_path = "target/#{BUILD_TARGET}/release/#{binary_name}"
52
52
  raise Errors::WebAssemblyBinaryNotFoundError unless ctx.file_exist?(binary_path)
53
53
 
54
- File.read(binary_path)
54
+ ctx.binread(binary_path)
55
55
  end
56
56
  end
57
57
  end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ class ScriptProjectRepository
7
+ include SmartProperties
8
+ property! :ctx, accepts: ShopifyCli::Context
9
+
10
+ DEFAULT_CONFIG_UI_FILENAME = "config-ui.yml"
11
+
12
+ def create(script_name:, extension_point_type:, language:, no_config_ui:)
13
+ validate_metadata!(extension_point_type, language)
14
+
15
+ optional_identifiers = {}
16
+ config_ui_file = nil
17
+
18
+ unless no_config_ui
19
+ optional_identifiers.merge!(config_ui_file: DEFAULT_CONFIG_UI_FILENAME)
20
+ config_ui_file = ConfigUiRepository
21
+ .new(ctx: ctx)
22
+ .create(DEFAULT_CONFIG_UI_FILENAME, default_config_ui_content(script_name))
23
+ end
24
+
25
+ ShopifyCli::Project.write(
26
+ ctx,
27
+ project_type: :script,
28
+ organization_id: nil,
29
+ extension_point_type: extension_point_type,
30
+ script_name: script_name,
31
+ language: language,
32
+ **optional_identifiers
33
+ )
34
+
35
+ Domain::ScriptProject.new(
36
+ id: ctx.root,
37
+ env: project.env,
38
+ script_name: script_name,
39
+ extension_point_type: extension_point_type,
40
+ language: language,
41
+ config_ui: config_ui_file
42
+ )
43
+ end
44
+
45
+ def get
46
+ extension_point_type = project_config_value!("extension_point_type")
47
+ script_name = project_config_value!("script_name")
48
+ config_ui_file = project_config_value("config_ui_file")
49
+ language = project_config_value("language")&.downcase || default_language
50
+
51
+ validate_metadata!(extension_point_type, language)
52
+
53
+ config_ui = ConfigUiRepository.new(ctx: ctx).get(config_ui_file)
54
+
55
+ Domain::ScriptProject.new(
56
+ id: project.directory,
57
+ env: project.env,
58
+ script_name: script_name,
59
+ extension_point_type: extension_point_type,
60
+ language: language,
61
+ config_ui: config_ui
62
+ )
63
+ end
64
+
65
+ private
66
+
67
+ def project_config_value(key)
68
+ return nil unless project.config.key?(key)
69
+ project.config[key]
70
+ end
71
+
72
+ def project_config_value!(key)
73
+ raise Errors::InvalidContextError, key unless project.config.key?(key)
74
+ project.config[key]
75
+ end
76
+
77
+ def project
78
+ ShopifyCli::Project.current
79
+ end
80
+
81
+ def default_config_ui_content(title)
82
+ require "yaml" # takes 20ms, so deferred as late as possible.
83
+ YAML.dump({
84
+ "version" => 1,
85
+ "inputMode" => "single",
86
+ "title" => title,
87
+ "description" => "",
88
+ "fields" => [],
89
+ })
90
+ end
91
+
92
+ def default_language
93
+ Domain::ExtensionPoint::ExtensionPointAssemblyScriptSDK.language
94
+ end
95
+
96
+ def validate_metadata!(extension_point_type, language)
97
+ if Application::ExtensionPoints.deprecated_types.include?(extension_point_type)
98
+ raise Errors::DeprecatedEPError, extension_point_type
99
+ elsif !Application::ExtensionPoints.supported_language?(type: extension_point_type, language: language)
100
+ raise Errors::InvalidLanguageError.new(language, extension_point_type)
101
+ end
102
+ end
103
+
104
+ class ConfigUiRepository
105
+ include SmartProperties
106
+ property! :ctx, accepts: ShopifyCli::Context
107
+
108
+ def create(filename, content)
109
+ File.write(filename, content)
110
+
111
+ Domain::ConfigUi.new(
112
+ filename: filename,
113
+ content: content,
114
+ )
115
+ end
116
+
117
+ def get(filename)
118
+ return nil unless filename
119
+
120
+ path = File.join(ctx.root, filename)
121
+ raise Domain::Errors::MissingSpecifiedConfigUiDefinitionError, filename unless File.exist?(path)
122
+
123
+ content = File.read(path)
124
+ raise Domain::Errors::InvalidConfigUiDefinitionError, filename unless valid_config_ui?(content)
125
+
126
+ Domain::ConfigUi.new(
127
+ filename: filename,
128
+ content: content,
129
+ )
130
+ end
131
+
132
+ private
133
+
134
+ def valid_config_ui?(raw_yaml)
135
+ require "yaml" # takes 20ms, so deferred as late as possible.
136
+ YAML.safe_load(raw_yaml)
137
+ true
138
+ rescue Psych::SyntaxError
139
+ false
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end