shopify-cli 0.9.2 → 0.9.3

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