shopify-cli 0.9.2 → 0.9.3

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/docs/_config.yml +3 -0
  4. data/docs/_data/nav.yml +9 -0
  5. data/docs/getting-started/index.md +5 -40
  6. data/docs/getting-started/install/index.md +39 -0
  7. data/docs/getting-started/migrate/index.md +63 -0
  8. data/docs/getting-started/uninstall/index.md +37 -0
  9. data/docs/getting-started/upgrade/index.md +37 -0
  10. data/docs/index.md +5 -6
  11. data/lib/project_types/extension/cli.rb +2 -1
  12. data/lib/project_types/extension/commands/tunnel.rb +1 -1
  13. data/lib/project_types/extension/forms/register.rb +2 -3
  14. data/lib/project_types/extension/graphql/get_app_by_api_key.graphql +9 -0
  15. data/lib/project_types/extension/tasks/converters/app_converter.rb +27 -0
  16. data/lib/project_types/extension/tasks/get_app.rb +22 -0
  17. data/lib/project_types/extension/tasks/get_apps.rb +1 -6
  18. data/lib/project_types/script/cli.rb +3 -2
  19. data/lib/project_types/script/commands/create.rb +5 -4
  20. data/lib/project_types/script/errors.rb +1 -0
  21. data/lib/project_types/script/forms/create.rb +8 -4
  22. data/lib/project_types/script/layers/application/create_script.rb +11 -18
  23. data/lib/project_types/script/layers/application/project_dependencies.rb +0 -5
  24. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +106 -0
  25. data/lib/project_types/script/layers/infrastructure/errors.rb +1 -1
  26. data/lib/project_types/script/layers/infrastructure/project_creator.rb +23 -0
  27. data/lib/project_types/script/layers/infrastructure/script_repository.rb +0 -33
  28. data/lib/project_types/script/messages/messages.rb +5 -6
  29. data/lib/project_types/script/templates/ts/as-pect.d.ts +1 -0
  30. data/lib/project_types/script/ui/error_handler.rb +5 -0
  31. data/lib/shopify-cli/tunnel.rb +33 -1
  32. data/lib/shopify-cli/version.rb +1 -1
  33. data/vendor/deps/cli-ui/REVISION +1 -1
  34. data/vendor/deps/cli-ui/lib/cli/ui.rb +52 -11
  35. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +11 -7
  36. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +34 -21
  37. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +107 -149
  38. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +99 -0
  39. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +119 -0
  40. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/box.rb +158 -0
  41. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +112 -0
  42. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +9 -15
  43. data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +47 -0
  44. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +9 -7
  45. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +39 -14
  46. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +62 -44
  47. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +7 -2
  48. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +23 -3
  49. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +34 -10
  50. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +12 -7
  51. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +26 -16
  52. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +3 -3
  53. data/vendor/deps/cli-ui/lib/cli/ui/widgets.rb +75 -0
  54. data/vendor/deps/cli-ui/lib/cli/ui/widgets/base.rb +27 -0
  55. data/vendor/deps/cli-ui/lib/cli/ui/widgets/status.rb +61 -0
  56. metadata +20 -7
  57. data/lib/project_types/extension/features/tunnel_url.rb +0 -20
  58. data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +0 -51
  59. data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +0 -36
  60. data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +0 -62
  61. data/vendor/deps/cli-ui/lib/cli/ui/box.rb +0 -15
@@ -51,15 +51,16 @@ module Script
51
51
  autoload :Errors, Project.project_filepath('layers/infrastructure/errors')
52
52
  autoload :AssemblyScriptDependencyManager,
53
53
  Project.project_filepath('layers/infrastructure/assemblyscript_dependency_manager')
54
+ autoload :AssemblyScriptProjectCreator,
55
+ Project.project_filepath('layers/infrastructure/assemblyscript_project_creator')
54
56
  autoload :AssemblyScriptTaskRunner, Project.project_filepath('layers/infrastructure/assemblyscript_task_runner')
55
57
  autoload :AssemblyScriptTsConfig, Project.project_filepath('layers/infrastructure/assemblyscript_tsconfig')
56
- autoload :DependencyManager, Project.project_filepath('layers/infrastructure/dependency_manager')
57
58
  autoload :PushPackageRepository, Project.project_filepath('layers/infrastructure/push_package_repository')
58
59
  autoload :ExtensionPointRepository, Project.project_filepath('layers/infrastructure/extension_point_repository')
60
+ autoload :ProjectCreator, Project.project_filepath('layers/infrastructure/project_creator')
59
61
  autoload :ScriptRepository, Project.project_filepath('layers/infrastructure/script_repository')
60
62
  autoload :ScriptService, Project.project_filepath('layers/infrastructure/script_service')
61
63
  autoload :TaskRunner, Project.project_filepath('layers/infrastructure/task_runner')
62
- autoload :TestSuiteRepository, Project.project_filepath('layers/infrastructure/test_suite_repository')
63
64
  end
64
65
  end
65
66
 
@@ -19,16 +19,17 @@ module Script
19
19
  return @ctx.puts(self.class.help)
20
20
  end
21
21
 
22
- script = Layers::Application::CreateScript.call(
22
+ Layers::Application::CreateScript.call(
23
23
  ctx: @ctx,
24
24
  language: language,
25
25
  script_name: form.name,
26
26
  extension_point_type: form.extension_point
27
27
  )
28
- @ctx.puts(@ctx.message('script.create.script_path', folder: script.name))
29
- @ctx.puts(@ctx.message('script.create.script_created', script_id: File.join(script.name, script.id)))
28
+ project = ScriptProject.current
29
+ @ctx.puts(@ctx.message('script.create.script_path', folder: project.script_name))
30
+ @ctx.puts(@ctx.message('script.create.script_created', script_id: project.source_file))
30
31
  rescue StandardError => e
31
- ScriptProject.cleanup(ctx: @ctx, script_name: form.name, root_dir: cur_dir)
32
+ ScriptProject.cleanup(ctx: @ctx, script_name: form.name, root_dir: cur_dir) if form
32
33
  UI::ErrorHandler.pretty_print_and_raise(e, failed_op: @ctx.message('script.create.error.operation_failed'))
33
34
  end
34
35
 
@@ -3,6 +3,7 @@
3
3
  module Script
4
4
  module Errors
5
5
  class InvalidContextError < ScriptProjectError; end
6
+ class InvalidScriptNameError < ScriptProjectError; end
6
7
  class NoExistingAppsError < ScriptProjectError; end
7
8
  class NoExistingOrganizationsError < ScriptProjectError; end
8
9
  class NoExistingStoresError < ScriptProjectError
@@ -6,7 +6,7 @@ module Script
6
6
  flag_arguments :extension_point, :name
7
7
 
8
8
  def ask
9
- self.name = (name || ask_name).downcase.gsub(' ', '_')
9
+ self.name = valid_name
10
10
  self.extension_point ||= ask_extension_point
11
11
  end
12
12
 
@@ -20,9 +20,13 @@ module Script
20
20
  end
21
21
 
22
22
  def ask_name
23
- name = CLI::UI::Prompt.ask(@ctx.message('script.forms.create.script_name'))
24
- return name if name.match?(/^[0-9A-Za-z _-]*$/)
25
- @ctx.abort(@ctx.message('script.forms.create.error.invalid_name'))
23
+ CLI::UI::Prompt.ask(@ctx.message('script.forms.create.script_name'))
24
+ end
25
+
26
+ def valid_name
27
+ n = (name || ask_name).downcase.gsub(' ', '_')
28
+ return n if n.match?(/^[0-9A-Za-z_-]*$/)
29
+ raise Errors::InvalidScriptNameError
26
30
  end
27
31
  end
28
32
  end
@@ -9,14 +9,16 @@ module Script
9
9
  class << self
10
10
  def call(ctx:, language:, script_name:, extension_point_type:)
11
11
  extension_point = ExtensionPoints.get(type: extension_point_type)
12
- project = create_project(ctx, script_name, extension_point)
13
- install_dependencies(ctx, language, script_name, extension_point, project)
14
- create_definition(ctx, language, extension_point, script_name)
12
+ project = setup_project(ctx, script_name, extension_point)
13
+ project_creator = Infrastructure::ProjectCreator
14
+ .for(ctx, language, extension_point, script_name, project.directory)
15
+ install_dependencies(ctx, language, script_name, project, project_creator)
16
+ bootstrap(ctx, project_creator)
15
17
  end
16
18
 
17
19
  private
18
20
 
19
- def create_project(ctx, script_name, extension_point)
21
+ def setup_project(ctx, script_name, extension_point)
20
22
  ScriptProject.create(ctx, script_name)
21
23
  ScriptProject.write(
22
24
  ctx,
@@ -28,26 +30,17 @@ module Script
28
30
  ScriptProject.current
29
31
  end
30
32
 
31
- def install_dependencies(ctx, language, script_name, extension_point, project)
33
+ def install_dependencies(ctx, language, script_name, project, project_creator)
32
34
  task_runner = Infrastructure::TaskRunner.for(ctx, language, script_name, project.source_file)
33
- ProjectDependencies
34
- .bootstrap(ctx: ctx, language: language, extension_point: extension_point, script_name: script_name)
35
- ProjectDependencies
36
- .install(ctx: ctx, task_runner: task_runner)
35
+ project_creator.setup_dependencies
36
+ ProjectDependencies.install(ctx: ctx, task_runner: task_runner)
37
37
  end
38
38
 
39
- def create_definition(ctx, language, extension_point, script_name)
40
- script = nil
39
+ def bootstrap(ctx, project_creator)
41
40
  UI::StrictSpinner.spin(ctx.message('script.create.creating')) do |spinner|
42
- script = Infrastructure::ScriptRepository.new(ctx: ctx).create_script(
43
- language,
44
- extension_point,
45
- script_name
46
- )
47
- Infrastructure::TestSuiteRepository.new(ctx: ctx).create_test_suite(script)
41
+ project_creator.bootstrap
48
42
  spinner.update_title(ctx.message('script.create.created'))
49
43
  end
50
- script
51
44
  end
52
45
  end
53
46
  end
@@ -2,11 +2,6 @@ module Script
2
2
  module Layers
3
3
  module Application
4
4
  class ProjectDependencies
5
- def self.bootstrap(ctx:, language:, extension_point:, script_name:)
6
- dep_manager = Infrastructure::DependencyManager.for(ctx, language, extension_point, script_name)
7
- dep_manager.bootstrap
8
- end
9
-
10
5
  def self.install(ctx:, task_runner:)
11
6
  CLI::UI::Frame.open(ctx.message('script.project_deps.checking_with_npm')) do
12
7
  begin
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ class AssemblyScriptProjectCreator
7
+ include SmartProperties
8
+ property! :ctx, accepts: ShopifyCli::Context
9
+ property! :extension_point, accepts: Domain::ExtensionPoint
10
+ property! :script_name, accepts: String
11
+ property! :path_to_project, accepts: String
12
+
13
+ BOOTSTRAP_SRC = "npx --no-install shopify-scripts-bootstrap src %{src_base}"
14
+ BOOTSTRAP_TEST = "npx --no-install shopify-scripts-bootstrap test %{test_base}"
15
+ SOURCE_DIR = "src"
16
+ TEST_DIR = "test"
17
+ LANGUAGE = "ts"
18
+
19
+ def setup_dependencies
20
+ write_npmrc
21
+ write_package_json
22
+ end
23
+
24
+ def bootstrap
25
+ create_src_folder
26
+ create_test_folder
27
+ end
28
+
29
+ private
30
+
31
+ def create_src_folder
32
+ ctx.mkdir_p(src_base)
33
+ out, status = ctx.capture2e(format(BOOTSTRAP_SRC, src_base: src_base))
34
+ raise Domain::Errors::ServiceFailureError, out unless status.success?
35
+
36
+ write_tsconfig_file(SOURCE_DIR, ".")
37
+ end
38
+
39
+ def create_test_folder
40
+ ctx.mkdir_p(test_base)
41
+ out, status = ctx.capture2e(format(BOOTSTRAP_TEST, test_base: test_base))
42
+ raise Domain::Errors::ServiceFailureError, out unless status.success?
43
+
44
+ copy_template_file(test_base, 'as-pect.config.js')
45
+ copy_template_file(test_base, 'as-pect.d.ts')
46
+ write_tsconfig_file(TEST_DIR, "../#{SOURCE_DIR}")
47
+ end
48
+
49
+ def test_base
50
+ "#{path_to_project}/#{TEST_DIR}"
51
+ end
52
+
53
+ def src_base
54
+ "#{path_to_project}/#{SOURCE_DIR}"
55
+ end
56
+
57
+ def copy_template_file(destination, name)
58
+ template_file = Project.project_filepath("templates/#{LANGUAGE}/#{name}")
59
+ ctx.cp(template_file, "#{destination}/#{name}")
60
+ end
61
+
62
+ def write_npmrc
63
+ ctx.system(
64
+ 'npm', '--userconfig', './.npmrc', 'config', 'set', '@shopify:registry', 'https://registry.npmjs.com'
65
+ )
66
+ ctx.system(
67
+ 'npm', '--userconfig', './.npmrc', 'config', 'set', 'engine-strict', 'true'
68
+ )
69
+ end
70
+
71
+ def write_tsconfig_file(dir, path_to_source)
72
+ AssemblyScriptTsConfig
73
+ .new(dir_to_write_in: dir)
74
+ .with_extends_assemblyscript_config(relative_path_to_node_modules: ".")
75
+ .with_module_resolution_paths(paths: { "*": ["#{path_to_source}/*.ts"] })
76
+ .write
77
+ end
78
+
79
+ def write_package_json
80
+ package_json = <<~HERE
81
+ {
82
+ "name": "#{script_name}",
83
+ "version": "1.0.0",
84
+ "devDependencies": {
85
+ "@shopify/scripts-sdk-as": "#{extension_point.sdks[:ts].sdk_version}",
86
+ "@shopify/scripts-toolchain-as": "#{extension_point.sdks[:ts].toolchain_version}",
87
+ "#{extension_point.sdks[:ts].package}": "#{extension_point.sdks[:ts].version}",
88
+ "@as-pect/cli": "4.0.0",
89
+ "as-wasi": "^0.0.1",
90
+ "assemblyscript": "^0.12.0"
91
+ },
92
+ "scripts": {
93
+ "test": "asp --config test/as-pect.config.js --summary --verbose"
94
+ },
95
+ "engines": {
96
+ "node": ">=12.16"
97
+ }
98
+ }
99
+ HERE
100
+
101
+ ctx.write("package.json", package_json)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -7,7 +7,6 @@ module Script
7
7
  class AppNotInstalledError < ScriptProjectError; end
8
8
  class AppScriptUndefinedError < ScriptProjectError; end
9
9
  class BuildError < ScriptProjectError; end
10
- class DependencyError < ScriptProjectError; end
11
10
  class DependencyInstallError < ScriptProjectError; end
12
11
  class ForbiddenError < ScriptProjectError; end
13
12
  class GraphqlError < ScriptProjectError
@@ -17,6 +16,7 @@ module Script
17
16
  super("GraphQL failed with errors: #{errors}")
18
17
  end
19
18
  end
19
+ class ProjectCreatorNotFoundError < ScriptProjectError; end
20
20
  class ScriptRepushError < ScriptProjectError
21
21
  attr_reader :api_key
22
22
  def initialize(api_key)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ class ProjectCreator
7
+ PROJECT_CREATORS = {
8
+ "ts" => Infrastructure::AssemblyScriptProjectCreator,
9
+ }
10
+
11
+ def self.for(ctx, language, extension_point, script_name, path_to_project)
12
+ raise Errors::ProjectCreatorNotFoundError unless PROJECT_CREATORS[language]
13
+ PROJECT_CREATORS[language].new(
14
+ ctx: ctx,
15
+ extension_point: extension_point,
16
+ script_name: script_name,
17
+ path_to_project: path_to_project
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,23 +7,6 @@ module Script
7
7
  include SmartProperties
8
8
  property! :ctx, accepts: ShopifyCli::Context
9
9
 
10
- BOOTSTRAP_SRC = "npx --no-install shopify-scripts-bootstrap src %{src_base}"
11
-
12
- def create_script(language, extension_point, script_name)
13
- ctx.mkdir_p(src_base)
14
- out, status = CLI::Kit::System.capture2e(format(BOOTSTRAP_SRC, src_base: src_base))
15
- raise Domain::Errors::ServiceFailureError, out unless status.success?
16
-
17
- write_tsconfig if language == "ts"
18
-
19
- Domain::Script.new(
20
- script_id(language),
21
- script_name,
22
- extension_point.type,
23
- language
24
- )
25
- end
26
-
27
10
  def get_script(language, extension_point_type, script_name)
28
11
  source_file_path = src_code_file(language)
29
12
  unless File.exist?(source_file_path)
@@ -51,18 +34,6 @@ module Script
51
34
 
52
35
  private
53
36
 
54
- def write_sdk(extension_point_type, language, sdk_types)
55
- return unless language == "ts"
56
- File.write(sdk_types_file(extension_point_type, language), sdk_types)
57
- end
58
-
59
- def write_tsconfig
60
- AssemblyScriptTsConfig
61
- .new(dir_to_write_in: relative_path_to_src)
62
- .with_extends_assemblyscript_config(relative_path_to_node_modules: ".")
63
- .write
64
- end
65
-
66
37
  def project_base
67
38
  ScriptProject.current.directory
68
39
  end
@@ -82,10 +53,6 @@ module Script
82
53
  def file_name(language)
83
54
  "script.#{language}"
84
55
  end
85
-
86
- def sdk_types_file(extension_point_type, language)
87
- "#{src_base}/#{extension_point_type}.#{language}"
88
- end
89
56
  end
90
57
  end
91
58
  end
@@ -18,8 +18,12 @@ module Script
18
18
  invalid_context_cause: "Your .shopify-cli.yml file is not correct.",
19
19
  invalid_context_help: "See https://help.shopify.com",
20
20
 
21
+ invalid_script_name_cause: "Invalid script name.",
22
+ invalid_script_name_help: "Replace or remove unsupported characters. Valid characters "\
23
+ "are numbers, letters, hyphens, or underscores.",
24
+
21
25
  no_existing_apps_cause: "You don't have any apps.",
22
- no_existing_apps_help: "Please create an app with {{command:shopify create}} or"\
26
+ no_existing_apps_help: "Please create an app with {{command:shopify create}} or "\
23
27
  "visit https://partners.shopify.com/.",
24
28
 
25
29
  no_existing_orgs_cause: "You don't have any partner organizations.",
@@ -169,11 +173,6 @@ module Script
169
173
  create: {
170
174
  select_extension_point: "Which extension point do you want to use?",
171
175
  script_name: "Script Name",
172
-
173
- error: {
174
- invalid_name: "Invalid script name: replace or remove unsupported characters. Valid "\
175
- "characters are numbers, letters, spaces, hyphens, or underscores.",
176
- },
177
176
  },
178
177
  script_form: {
179
178
  ask_app_api_key_default: "Which app do you want this script to belong to?",
@@ -0,0 +1 @@
1
+ /// <reference types="@as-pect/assembly/types/as-pect" />
@@ -44,6 +44,11 @@ module Script
44
44
  cause_of_error: ShopifyCli::Context.message('script.error.invalid_context_cause'),
45
45
  help_suggestion: ShopifyCli::Context.message('script.error.invalid_context_help'),
46
46
  }
47
+ when Errors::InvalidScriptNameError
48
+ {
49
+ cause_of_error: ShopifyCli::Context.message('script.error.invalid_script_name_cause'),
50
+ help_suggestion: ShopifyCli::Context.message('script.error.invalid_script_name_help'),
51
+ }
47
52
  when Errors::NoExistingAppsError
48
53
  {
49
54
  cause_of_error: ShopifyCli::Context.message('script.error.no_existing_apps_cause'),
@@ -11,7 +11,7 @@ module ShopifyCli
11
11
  class Tunnel
12
12
  extend SingleForwardable
13
13
 
14
- def_delegators :new, :start, :stop, :auth
14
+ def_delegators :new, :start, :stop, :auth, :stats, :urls
15
15
 
16
16
  class FetchUrlError < RuntimeError; end
17
17
  class NgrokError < RuntimeError; end
@@ -23,6 +23,10 @@ module ShopifyCli
23
23
  linux: 'https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip',
24
24
  }
25
25
 
26
+ NGROK_TUNNELS_URI = URI.parse('http://localhost:4040/api/tunnels')
27
+ TUNNELS_FIELD = 'tunnels'
28
+ PUBLIC_URL_FIELD = 'public_url'
29
+
26
30
  ##
27
31
  # will find and stop a running tunnel process. It will also output if the
28
32
  # operation was successful or not
@@ -82,6 +86,34 @@ module ShopifyCli
82
86
  ctx.system(File.join(ShopifyCli::CACHE_DIR, 'ngrok'), 'authtoken', token)
83
87
  end
84
88
 
89
+ ##
90
+ # will return the statistics of the current running tunnels
91
+ #
92
+ # #### Returns
93
+ #
94
+ # * `stats` - the hash of running statistics returning from the ngrok api
95
+ #
96
+ def stats
97
+ response = Net::HTTP.get_response(NGROK_TUNNELS_URI)
98
+ JSON.parse(response.body)
99
+ rescue
100
+ {}
101
+ end
102
+
103
+ ##
104
+ # will return the urls of the current running tunnels
105
+ #
106
+ # #### Returns
107
+ #
108
+ # * `stats` - the array of urls
109
+ #
110
+ def urls
111
+ tunnels = stats.dig(TUNNELS_FIELD)
112
+ tunnels.map { |tunnel| tunnel.dig(PUBLIC_URL_FIELD) }
113
+ rescue
114
+ []
115
+ end
116
+
85
117
  private
86
118
 
87
119
  def install(ctx)
@@ -1,3 +1,3 @@
1
1
  module ShopifyCli
2
- VERSION = '0.9.2'
2
+ VERSION = '0.9.3'
3
3
  end
@@ -1 +1 @@
1
- 35e1b188f19b2ba0ab85bbf48ab983b1f72a361b
1
+ c59f601fe271432dfe304f30f08a48b2a343606e