shopify-cli 2.3.0 → 2.6.1

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 (266) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/workflows/shopify.yml +104 -0
  4. data/.gitignore +3 -0
  5. data/.rubocop.yml +14 -14
  6. data/.rubocop_todo.yml +3 -3
  7. data/CHANGELOG.md +26 -0
  8. data/CONTRIBUTING.md +23 -0
  9. data/Dockerfile +17 -0
  10. data/Gemfile +1 -0
  11. data/Gemfile.lock +67 -24
  12. data/README.md +1 -1
  13. data/RELEASING.md +1 -1
  14. data/Rakefile +75 -18
  15. data/bin/console +11 -0
  16. data/bin/shopify +17 -4
  17. data/dev.yml +14 -1
  18. data/ext/shopify-cli/extconf.rb +2 -0
  19. data/ext/shopify-extensions/extconf.rb +21 -0
  20. data/ext/shopify-extensions/shopify_extensions.rb +152 -0
  21. data/ext/shopify-extensions/version +1 -0
  22. data/lib/project_types/extension/cli.rb +19 -3
  23. data/lib/project_types/extension/commands/build.rb +32 -3
  24. data/lib/project_types/extension/commands/check.rb +2 -2
  25. data/lib/project_types/extension/commands/connect.rb +1 -1
  26. data/lib/project_types/extension/commands/create.rb +59 -16
  27. data/lib/project_types/extension/commands/extension_command.rb +1 -1
  28. data/lib/project_types/extension/commands/info.rb +1 -1
  29. data/lib/project_types/extension/commands/push.rb +1 -1
  30. data/lib/project_types/extension/commands/register.rb +2 -2
  31. data/lib/project_types/extension/commands/serve.rb +5 -5
  32. data/lib/project_types/extension/commands/tunnel.rb +6 -6
  33. data/lib/project_types/extension/extension_project.rb +4 -4
  34. data/lib/project_types/extension/features/argo.rb +3 -3
  35. data/lib/project_types/extension/features/argo_config.rb +5 -5
  36. data/lib/project_types/extension/features/argo_serve.rb +21 -6
  37. data/lib/project_types/extension/features/argo_setup.rb +1 -1
  38. data/lib/project_types/extension/features/argo_setup_step.rb +1 -1
  39. data/lib/project_types/extension/features/argo_setup_steps.rb +2 -2
  40. data/lib/project_types/extension/forms/connect.rb +2 -2
  41. data/lib/project_types/extension/forms/create.rb +6 -3
  42. data/lib/project_types/extension/forms/questions/ask_app.rb +2 -2
  43. data/lib/project_types/extension/forms/questions/ask_name.rb +1 -1
  44. data/lib/project_types/extension/forms/questions/ask_registration.rb +2 -2
  45. data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
  46. data/lib/project_types/extension/forms/questions/ask_type.rb +2 -2
  47. data/lib/project_types/extension/messages/message_loading.rb +2 -2
  48. data/lib/project_types/extension/messages/messages.rb +3 -0
  49. data/lib/project_types/extension/models/development_server.rb +78 -0
  50. data/lib/project_types/extension/models/development_server_requirements.rb +35 -0
  51. data/lib/project_types/extension/models/lazy_specification_handler.rb +1 -1
  52. data/lib/project_types/extension/models/server_config/base.rb +31 -0
  53. data/lib/project_types/extension/models/server_config/development.rb +23 -0
  54. data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
  55. data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
  56. data/lib/project_types/extension/models/server_config/extension.rb +35 -0
  57. data/lib/project_types/extension/models/server_config/root.rb +18 -0
  58. data/lib/project_types/extension/models/server_config/user.rb +10 -0
  59. data/lib/project_types/extension/models/specification.rb +1 -1
  60. data/lib/project_types/extension/models/specification_handlers/default.rb +14 -2
  61. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +1 -1
  62. data/lib/project_types/extension/models/specifications.rb +4 -4
  63. data/lib/project_types/extension/tasks/choose_next_available_port.rb +2 -2
  64. data/lib/project_types/extension/tasks/configure_features.rb +1 -1
  65. data/lib/project_types/extension/tasks/configure_options.rb +1 -1
  66. data/lib/project_types/extension/tasks/converters/product_converter.rb +1 -1
  67. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
  68. data/lib/project_types/extension/tasks/create_extension.rb +2 -2
  69. data/lib/project_types/extension/tasks/fetch_specifications.rb +2 -2
  70. data/lib/project_types/extension/tasks/find_npm_packages.rb +5 -5
  71. data/lib/project_types/extension/tasks/get_app.rb +2 -2
  72. data/lib/project_types/extension/tasks/get_apps.rb +2 -2
  73. data/lib/project_types/extension/tasks/get_extensions.rb +2 -2
  74. data/lib/project_types/extension/tasks/get_product.rb +2 -2
  75. data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
  76. data/lib/project_types/extension/tasks/run_extension_command.rb +81 -0
  77. data/lib/project_types/extension/tasks/update_draft.rb +2 -2
  78. data/lib/project_types/node/cli.rb +3 -3
  79. data/lib/project_types/node/commands/connect.rb +4 -4
  80. data/lib/project_types/node/commands/create.rb +10 -14
  81. data/lib/project_types/node/commands/deploy/heroku.rb +4 -4
  82. data/lib/project_types/node/commands/deploy.rb +3 -3
  83. data/lib/project_types/node/commands/generate.rb +2 -2
  84. data/lib/project_types/node/commands/open.rb +3 -3
  85. data/lib/project_types/node/commands/serve.rb +15 -7
  86. data/lib/project_types/node/commands/tunnel.rb +6 -6
  87. data/lib/project_types/node/forms/create.rb +3 -3
  88. data/lib/project_types/node/messages/messages.rb +3 -0
  89. data/lib/project_types/php/cli.rb +27 -0
  90. data/lib/project_types/php/commands/connect.rb +19 -0
  91. data/lib/project_types/php/commands/create.rb +143 -0
  92. data/lib/project_types/php/commands/deploy/heroku.rb +129 -0
  93. data/lib/project_types/php/commands/deploy.rb +32 -0
  94. data/lib/project_types/php/commands/open.rb +16 -0
  95. data/lib/project_types/php/commands/serve.rb +51 -0
  96. data/lib/project_types/php/commands/tunnel.rb +37 -0
  97. data/lib/project_types/php/forms/create.rb +45 -0
  98. data/lib/project_types/php/messages/messages.rb +191 -0
  99. data/lib/project_types/rails/cli.rb +3 -3
  100. data/lib/project_types/rails/commands/connect.rb +4 -4
  101. data/lib/project_types/rails/commands/create.rb +12 -16
  102. data/lib/project_types/rails/commands/deploy/heroku.rb +4 -4
  103. data/lib/project_types/rails/commands/deploy.rb +3 -3
  104. data/lib/project_types/rails/commands/generate/webhook.rb +3 -3
  105. data/lib/project_types/rails/commands/generate.rb +3 -3
  106. data/lib/project_types/rails/commands/open.rb +3 -3
  107. data/lib/project_types/rails/commands/serve.rb +8 -8
  108. data/lib/project_types/rails/commands/tunnel.rb +6 -6
  109. data/lib/project_types/rails/forms/create.rb +3 -3
  110. data/lib/project_types/rails/gem.rb +1 -1
  111. data/lib/project_types/rails/ruby.rb +1 -1
  112. data/lib/project_types/script/cli.rb +16 -6
  113. data/lib/project_types/script/commands/create.rb +4 -2
  114. data/lib/project_types/script/commands/push.rb +2 -2
  115. data/lib/project_types/script/config/extension_points.yml +30 -29
  116. data/lib/project_types/script/forms/create.rb +1 -1
  117. data/lib/project_types/script/layers/application/create_script.rb +32 -12
  118. data/lib/project_types/script/layers/application/extension_points.rb +4 -4
  119. data/lib/project_types/script/layers/application/push_script.rb +13 -1
  120. data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
  121. data/lib/project_types/script/layers/domain/push_package.rb +0 -12
  122. data/lib/project_types/script/layers/domain/script_project.rb +2 -2
  123. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +57 -0
  124. data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +35 -0
  125. data/lib/project_types/script/layers/infrastructure/command_runner.rb +1 -1
  126. data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
  127. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
  128. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
  129. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
  130. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
  131. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
  132. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
  133. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +6 -6
  134. data/lib/project_types/script/layers/infrastructure/script_service.rb +25 -144
  135. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
  136. data/lib/project_types/script/layers/infrastructure/service_locator.rb +20 -0
  137. data/lib/project_types/script/messages/messages.rb +4 -0
  138. data/lib/project_types/script/tasks/ensure_env.rb +7 -7
  139. data/lib/project_types/script/ui/error_handler.rb +84 -76
  140. data/lib/project_types/script/ui/printing_spinner.rb +1 -1
  141. data/lib/project_types/theme/cli.rb +3 -3
  142. data/lib/project_types/theme/commands/check.rb +3 -3
  143. data/lib/project_types/theme/commands/delete.rb +7 -7
  144. data/lib/project_types/theme/commands/init.rb +3 -3
  145. data/lib/project_types/theme/commands/language_server.rb +2 -2
  146. data/lib/project_types/theme/commands/package.rb +2 -2
  147. data/lib/project_types/theme/commands/publish.rb +5 -5
  148. data/lib/project_types/theme/commands/pull.rb +9 -9
  149. data/lib/project_types/theme/commands/push.rb +12 -12
  150. data/lib/project_types/theme/commands/serve.rb +4 -4
  151. data/lib/project_types/theme/forms/confirm_store.rb +1 -1
  152. data/lib/project_types/theme/forms/select.rb +2 -2
  153. data/lib/{shopify-cli → shopify_cli}/admin_api/populate_resource_command.rb +3 -3
  154. data/lib/{shopify-cli → shopify_cli}/admin_api/schema.rb +4 -4
  155. data/lib/{shopify-cli → shopify_cli}/admin_api.rb +27 -27
  156. data/lib/{shopify-cli → shopify_cli}/api.rb +12 -8
  157. data/lib/shopify_cli/command/app_sub_command.rb +16 -0
  158. data/lib/{shopify-cli → shopify_cli}/command.rb +3 -3
  159. data/lib/{shopify-cli → shopify_cli}/commands/config.rb +14 -14
  160. data/lib/{shopify-cli → shopify_cli}/commands/help.rb +4 -4
  161. data/lib/{shopify-cli → shopify_cli}/commands/login.rb +7 -7
  162. data/lib/shopify_cli/commands/logout.rb +39 -0
  163. data/lib/{shopify-cli → shopify_cli}/commands/populate/customer.rb +4 -4
  164. data/lib/{shopify-cli → shopify_cli}/commands/populate/draft_order.rb +4 -4
  165. data/lib/{shopify-cli → shopify_cli}/commands/populate/product.rb +4 -4
  166. data/lib/shopify_cli/commands/populate.rb +23 -0
  167. data/lib/shopify_cli/commands/store.rb +15 -0
  168. data/lib/{shopify-cli → shopify_cli}/commands/switch.rb +5 -5
  169. data/lib/{shopify-cli → shopify_cli}/commands/system.rb +10 -10
  170. data/lib/shopify_cli/commands/version.rb +15 -0
  171. data/lib/{shopify-cli → shopify_cli}/commands/whoami.rb +7 -7
  172. data/lib/shopify_cli/commands.rb +34 -0
  173. data/lib/{shopify-cli → shopify_cli}/connect.rb +3 -3
  174. data/lib/shopify_cli/constants.rb +54 -0
  175. data/lib/{shopify-cli → shopify_cli}/context.rb +6 -6
  176. data/lib/{shopify-cli → shopify_cli}/core/entry_point.rb +7 -7
  177. data/lib/{shopify-cli → shopify_cli}/core/executor.rb +8 -4
  178. data/lib/{shopify-cli → shopify_cli}/core/finalize.rb +1 -1
  179. data/lib/{shopify-cli → shopify_cli}/core/help_resolver.rb +2 -2
  180. data/lib/{shopify-cli → shopify_cli}/core/monorail.rb +8 -8
  181. data/lib/shopify_cli/core.rb +8 -0
  182. data/lib/{shopify-cli → shopify_cli}/db.rb +8 -8
  183. data/lib/shopify_cli/environment.rb +91 -0
  184. data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
  185. data/lib/shopify_cli/exception_reporter.rb +55 -0
  186. data/lib/{shopify-cli → shopify_cli}/feature.rb +8 -8
  187. data/lib/{shopify-cli → shopify_cli}/form.rb +2 -2
  188. data/lib/{shopify-cli → shopify_cli}/git.rb +38 -8
  189. data/lib/{shopify-cli → shopify_cli}/helpers/haikunator.rb +1 -1
  190. data/lib/shopify_cli/helpers.rb +5 -0
  191. data/lib/{shopify-cli → shopify_cli}/heroku.rb +38 -13
  192. data/lib/{shopify-cli → shopify_cli}/http_request.rb +1 -1
  193. data/lib/{shopify-cli → shopify_cli}/identity_auth/servlet.rb +1 -1
  194. data/lib/{shopify-cli → shopify_cli}/identity_auth.rb +24 -31
  195. data/lib/{shopify-cli → shopify_cli}/js_deps.rb +7 -7
  196. data/lib/{shopify-cli → shopify_cli}/js_system.rb +10 -10
  197. data/lib/{shopify-cli → shopify_cli}/lazy_delegator.rb +2 -2
  198. data/lib/{shopify-cli → shopify_cli}/messages/messages.rb +44 -2
  199. data/lib/{shopify-cli → shopify_cli}/method_object.rb +15 -8
  200. data/lib/shopify_cli/migrator/migration.rb +27 -0
  201. data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
  202. data/lib/shopify_cli/migrator.rb +48 -0
  203. data/lib/{shopify-cli → shopify_cli}/options.rb +1 -1
  204. data/lib/{shopify-cli → shopify_cli}/packager.rb +8 -8
  205. data/lib/{shopify-cli → shopify_cli}/partners_api/organizations.rb +1 -1
  206. data/lib/{shopify-cli → shopify_cli}/partners_api.rb +16 -40
  207. data/lib/shopify_cli/php_deps.rb +102 -0
  208. data/lib/{shopify-cli → shopify_cli}/process_supervision.rb +10 -8
  209. data/lib/{shopify-cli → shopify_cli}/project.rb +15 -15
  210. data/lib/{shopify-cli → shopify_cli}/project_commands.rb +3 -3
  211. data/lib/{shopify-cli → shopify_cli}/project_type.rb +5 -5
  212. data/lib/{shopify-cli → shopify_cli}/resolve_constant.rb +5 -5
  213. data/lib/{shopify-cli → shopify_cli}/resources/env_file.rb +1 -1
  214. data/lib/shopify_cli/resources.rb +5 -0
  215. data/lib/{shopify-cli → shopify_cli}/result.rb +11 -11
  216. data/lib/{shopify-cli → shopify_cli}/shopifolk.rb +6 -6
  217. data/lib/{shopify-cli → shopify_cli}/sub_command.rb +1 -1
  218. data/lib/{shopify-cli → shopify_cli}/task.rb +1 -1
  219. data/lib/{shopify-cli → shopify_cli}/tasks/confirm_store.rb +3 -3
  220. data/lib/{shopify-cli → shopify_cli}/tasks/create_api_client.rb +4 -4
  221. data/lib/shopify_cli/tasks/ensure_authenticated.rb +13 -0
  222. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_dev_store.rb +5 -5
  223. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_env.rb +3 -3
  224. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_loopback_url.rb +4 -4
  225. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_project_type.rb +3 -3
  226. data/lib/{shopify-cli → shopify_cli}/tasks/select_org_and_shop.rb +8 -8
  227. data/lib/{shopify-cli → shopify_cli}/tasks/update_dashboard_urls.rb +6 -6
  228. data/lib/{shopify-cli → shopify_cli}/tasks.rb +10 -10
  229. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/certificate_manager.rb +5 -5
  230. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/header_hash.rb +1 -1
  231. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot-reload.js +0 -0
  232. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot_reload.rb +5 -6
  233. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/local_assets.rb +1 -1
  234. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/proxy.rb +2 -2
  235. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/sse.rb +1 -1
  236. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/watcher.rb +1 -1
  237. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/web_server.rb +1 -1
  238. data/lib/{shopify-cli → shopify_cli}/theme/dev_server.rb +3 -3
  239. data/lib/shopify_cli/theme/development_theme.rb +83 -0
  240. data/lib/{shopify-cli → shopify_cli}/theme/file.rb +1 -1
  241. data/lib/{shopify-cli → shopify_cli}/theme/ignore_filter.rb +1 -1
  242. data/lib/{shopify-cli → shopify_cli}/theme/mime_type.rb +1 -1
  243. data/lib/{shopify-cli → shopify_cli}/theme/syncer.rb +6 -6
  244. data/lib/{shopify-cli → shopify_cli}/theme/theme.rb +4 -4
  245. data/lib/{shopify-cli → shopify_cli}/transform_data_structure.rb +4 -4
  246. data/lib/{shopify-cli → shopify_cli}/tunnel.rb +14 -14
  247. data/lib/shopify_cli/version.rb +3 -0
  248. data/lib/shopify_cli.rb +61 -50
  249. data/shopify-cli.gemspec +13 -5
  250. data/utilities/docker.rb +47 -0
  251. data/utilities/utilities.rb +5 -0
  252. metadata +155 -97
  253. data/.github/workflows/build.yml +0 -28
  254. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
  255. data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +0 -60
  256. data/lib/shopify-cli/commands/logout.rb +0 -39
  257. data/lib/shopify-cli/commands/populate.rb +0 -23
  258. data/lib/shopify-cli/commands/store.rb +0 -15
  259. data/lib/shopify-cli/commands/version.rb +0 -15
  260. data/lib/shopify-cli/commands.rb +0 -34
  261. data/lib/shopify-cli/core.rb +0 -8
  262. data/lib/shopify-cli/helpers.rb +0 -5
  263. data/lib/shopify-cli/resources.rb +0 -5
  264. data/lib/shopify-cli/tasks/ensure_authenticated.rb +0 -13
  265. data/lib/shopify-cli/theme/development_theme.rb +0 -69
  266. data/lib/shopify-cli/version.rb +0 -3
@@ -5,20 +5,85 @@ module Script
5
5
  module Infrastructure
6
6
  module Languages
7
7
  class ProjectCreator
8
- PROJECT_CREATORS = {
9
- "assemblyscript" => AssemblyScriptProjectCreator,
10
- "rust" => RustProjectCreator,
11
- }
12
-
13
- def self.for(ctx, language, extension_point, script_name, path_to_project)
14
- raise Errors::ProjectCreatorNotFoundError unless PROJECT_CREATORS[language]
15
- PROJECT_CREATORS[language].new(
8
+ include SmartProperties
9
+ property! :ctx, accepts: ShopifyCLI::Context
10
+ property! :type, accepts: String
11
+ property! :project_name, accepts: String
12
+ property! :path_to_project, accepts: String
13
+ property! :sparse_checkout_repo, accepts: String
14
+ property! :sparse_checkout_branch, accepts: String
15
+ property! :sparse_checkout_set_path, accepts: String
16
+
17
+ def self.for(
18
+ ctx:,
19
+ language:,
20
+ type:,
21
+ project_name:,
22
+ path_to_project:,
23
+ sparse_checkout_repo:,
24
+ sparse_checkout_branch:,
25
+ sparse_checkout_set_path:
26
+ )
27
+
28
+ project_creators = {
29
+ "assemblyscript" => AssemblyScriptProjectCreator,
30
+ "typescript" => TypeScriptProjectCreator,
31
+ }
32
+
33
+ raise Errors::ProjectCreatorNotFoundError unless project_creators[language]
34
+ project_creators[language].new(
16
35
  ctx: ctx,
17
- extension_point: extension_point,
18
- script_name: script_name,
19
- path_to_project: path_to_project
36
+ type: type,
37
+ project_name: project_name,
38
+ path_to_project: path_to_project,
39
+ sparse_checkout_repo: sparse_checkout_repo,
40
+ sparse_checkout_branch: sparse_checkout_branch,
41
+ sparse_checkout_set_path: sparse_checkout_set_path
42
+ )
43
+ end
44
+
45
+ def self.config_file
46
+ raise NotImplementedError
47
+ end
48
+
49
+ # the sparse checkout process is common to all script types
50
+ def setup_dependencies
51
+ setup_sparse_checkout
52
+ clean
53
+ update_project_name(File.join(path_to_project, self.class.config_file))
54
+ end
55
+
56
+ private
57
+
58
+ def setup_sparse_checkout
59
+ ShopifyCLI::Git.sparse_checkout(
60
+ sparse_checkout_repo,
61
+ sparse_checkout_set_path,
62
+ sparse_checkout_branch,
63
+ ctx
20
64
  )
21
65
  end
66
+
67
+ def clean
68
+ source = File.join(path_to_project, sparse_checkout_set_path, ".")
69
+ FileUtils.cp_r(source, path_to_project)
70
+ ctx.rm_rf(sparse_checkout_set_path.split("/")[0])
71
+ ctx.rm_rf(".git")
72
+ end
73
+
74
+ def update_project_name(config_file)
75
+ raise Errors::ProjectConfigNotFoundError unless File.exist?(config_file)
76
+ upstream_name = "#{type.gsub("_", "-")}-default"
77
+ contents = File.read(config_file)
78
+
79
+ raise Errors::InvalidProjectConfigError unless contents.include?(upstream_name)
80
+ new_contents = contents.gsub(upstream_name, project_name)
81
+ File.write(config_file, new_contents)
82
+ end
83
+
84
+ def command_runner
85
+ @command_runner ||= CommandRunner.new(ctx: ctx)
86
+ end
22
87
  end
23
88
  end
24
89
  end
@@ -7,7 +7,7 @@ module Script
7
7
  class TaskRunner
8
8
  TASK_RUNNERS = {
9
9
  "assemblyscript" => AssemblyScriptTaskRunner,
10
- "rust" => RustTaskRunner,
10
+ "typescript" => TypeScriptTaskRunner,
11
11
  }
12
12
 
13
13
  def self.for(ctx, language, script_name)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ module Languages
7
+ class TypeScriptProjectCreator < ProjectCreator
8
+ MIN_NODE_VERSION = "14.15.0"
9
+ NPM_SET_REGISTRY_COMMAND = "npm --userconfig ./.npmrc config set @shopify:registry https://registry.npmjs.com"
10
+ NPM_SET_ENGINE_STRICT_COMMAND = "npm --userconfig ./.npmrc config set engine-strict true"
11
+
12
+ def self.config_file
13
+ "package.json"
14
+ end
15
+
16
+ def setup_dependencies
17
+ super
18
+ command_runner.call(NPM_SET_REGISTRY_COMMAND)
19
+ command_runner.call(NPM_SET_ENGINE_STRICT_COMMAND)
20
+
21
+ if ctx.file_exist?("yarn.lock")
22
+ ctx.rm("yarn.lock")
23
+ end
24
+
25
+ if ctx.file_exist?("package-lock.json")
26
+ ctx.rm("package-lock.json")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Script
4
+ module Layers
5
+ module Infrastructure
6
+ module Languages
7
+ class TypeScriptTaskRunner
8
+ BYTECODE_FILE = "build/%{name}.wasm"
9
+ METADATA_FILE = "build/metadata.json"
10
+ SCRIPT_SDK_BUILD = "npm run build"
11
+ GEN_METADATA = "npm run gen-metadata"
12
+
13
+ attr_reader :ctx, :script_name
14
+
15
+ def initialize(ctx, script_name)
16
+ @ctx = ctx
17
+ @script_name = script_name
18
+ end
19
+
20
+ def build
21
+ compile
22
+ bytecode
23
+ end
24
+
25
+ def compiled_type
26
+ "wasm"
27
+ end
28
+
29
+ def install_dependencies
30
+ check_node_version!
31
+
32
+ output, status = ctx.capture2e("npm install --no-audit --no-optional --legacy-peer-deps --loglevel error")
33
+ raise Errors::DependencyInstallError, output unless status.success?
34
+ end
35
+
36
+ def dependencies_installed?
37
+ # Assuming if node_modules folder exist at root of script folder, all deps are installed
38
+ ctx.dir_exist?("node_modules")
39
+ end
40
+
41
+ def metadata
42
+ unless @ctx.file_exist?(METADATA_FILE)
43
+ msg = @ctx.message("script.error.metadata_not_found_cause", METADATA_FILE)
44
+ raise Domain::Errors::MetadataNotFoundError, msg
45
+ end
46
+
47
+ raw_contents = File.read(METADATA_FILE)
48
+ Domain::Metadata.create_from_json(@ctx, raw_contents)
49
+ end
50
+
51
+ private
52
+
53
+ def check_node_version!
54
+ output, status = @ctx.capture2e("node", "--version")
55
+ raise Errors::DependencyInstallError, output unless status.success?
56
+
57
+ require "semantic/semantic"
58
+ version = ::Semantic::Version.new(output[1..-1])
59
+ unless version >= ::Semantic::Version.new(TypeScriptProjectCreator::MIN_NODE_VERSION)
60
+ raise Errors::DependencyInstallError,
61
+ "Node version must be >= v#{TypeScriptProjectCreator::MIN_NODE_VERSION}. "\
62
+ "Current version: #{output.strip}."
63
+ end
64
+ end
65
+
66
+ def compile
67
+ check_compilation_dependencies!
68
+ CommandRunner.new(ctx: ctx).call(SCRIPT_SDK_BUILD)
69
+ CommandRunner.new(ctx: ctx).call(GEN_METADATA)
70
+ end
71
+
72
+ def check_compilation_dependencies!
73
+ pkg = JSON.parse(File.read("package.json"))
74
+ build_script = pkg.dig("scripts", "build")
75
+
76
+ raise Errors::BuildScriptNotFoundError,
77
+ "Build script not found" if build_script.nil?
78
+
79
+ unless build_script.start_with?("javy")
80
+ raise Errors::InvalidBuildScriptError, "Invalid build script"
81
+ end
82
+ end
83
+
84
+ def bytecode
85
+ legacy_filename = format(BYTECODE_FILE, name: script_name)
86
+ filename = format(BYTECODE_FILE, name: "index")
87
+
88
+ bytecode_file = if ctx.file_exist?(filename)
89
+ filename
90
+ elsif ctx.file_exist?(legacy_filename)
91
+ legacy_filename
92
+ else
93
+ raise Errors::WebAssemblyBinaryNotFoundError
94
+ end
95
+
96
+ contents = ctx.binread(bytecode_file)
97
+ ctx.rm(bytecode_file)
98
+
99
+ contents
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -5,7 +5,7 @@ module Script
5
5
  module Infrastructure
6
6
  class PushPackageRepository
7
7
  include SmartProperties
8
- property! :ctx, accepts: ShopifyCli::Context
8
+ property! :ctx, accepts: ShopifyCLI::Context
9
9
 
10
10
  def create_push_package(script_project:, script_content:, compiled_type:, metadata:)
11
11
  build_file_path = file_path(script_project.id, compiled_type)
@@ -5,7 +5,7 @@ module Script
5
5
  module Infrastructure
6
6
  class ScriptProjectRepository
7
7
  include SmartProperties
8
- property! :ctx, accepts: ShopifyCli::Context
8
+ property! :ctx, accepts: ShopifyCLI::Context
9
9
 
10
10
  SCRIPT_JSON_FILENAME = "script.json"
11
11
  MUTABLE_ENV_VALUES = %i(uuid)
@@ -13,7 +13,7 @@ module Script
13
13
  def create(script_name:, extension_point_type:, language:)
14
14
  validate_metadata!(extension_point_type, language)
15
15
 
16
- ShopifyCli::Project.write(
16
+ ShopifyCLI::Project.write(
17
17
  ctx,
18
18
  project_type: :script,
19
19
  organization_id: nil,
@@ -63,7 +63,7 @@ module Script
63
63
  end
64
64
 
65
65
  def create_env(api_key:, secret:, uuid:)
66
- ShopifyCli::Resources::EnvFile.new(
66
+ ShopifyCLI::Resources::EnvFile.new(
67
67
  api_key: api_key,
68
68
  secret: secret,
69
69
  extra: {
@@ -125,11 +125,11 @@ module Script
125
125
  end
126
126
 
127
127
  def project
128
- @project ||= ShopifyCli::Project.current(force_reload: true)
128
+ @project ||= ShopifyCLI::Project.current(force_reload: true)
129
129
  end
130
130
 
131
131
  def default_language
132
- Domain::ExtensionPoint::ExtensionPointAssemblyScriptSDK.language
132
+ "assemblyscript"
133
133
  end
134
134
 
135
135
  def validate_metadata!(extension_point_type, language)
@@ -142,7 +142,7 @@ module Script
142
142
 
143
143
  class ScriptJsonRepository
144
144
  include SmartProperties
145
- property! :ctx, accepts: ShopifyCli::Context
145
+ property! :ctx, accepts: ShopifyCLI::Context
146
146
 
147
147
  def get
148
148
  current_script_json || raise(Domain::Errors::NoScriptJsonFile)
@@ -7,20 +7,19 @@ module Script
7
7
  module Layers
8
8
  module Infrastructure
9
9
  class ScriptService
10
- include SmartProperties
11
- property! :ctx, accepts: ShopifyCli::Context
10
+ def initialize(client:, api_key:)
11
+ @client = client
12
+ @api_key = api_key
13
+ end
12
14
 
13
- def push(
15
+ def set_app_script(
14
16
  uuid:,
15
17
  extension_point_type:,
16
- script_content:,
17
- api_key: nil,
18
18
  force: false,
19
19
  metadata:,
20
- script_json:
20
+ script_json:,
21
+ module_upload_url:
21
22
  )
22
- url = UploadScript.new(ctx).call(api_key, script_content)
23
-
24
23
  query_name = "app_script_set"
25
24
  variables = {
26
25
  uuid: uuid,
@@ -33,9 +32,9 @@ module Script
33
32
  scriptJsonVersion: script_json.version,
34
33
  configurationUi: script_json.configuration_ui,
35
34
  configurationDefinition: script_json.configuration&.to_json,
36
- moduleUploadUrl: url,
35
+ moduleUploadUrl: module_upload_url,
37
36
  }
38
- resp_hash = MakeRequest.new(ctx).call(query_name: query_name, api_key: api_key, variables: variables)
37
+ resp_hash = make_request(query_name: query_name, variables: variables)
39
38
  user_errors = resp_hash["data"]["appScriptSet"]["userErrors"]
40
39
 
41
40
  return resp_hash["data"]["appScriptSet"]["appScript"]["uuid"] if user_errors.empty?
@@ -63,149 +62,31 @@ module Script
63
62
  end
64
63
  end
65
64
 
66
- def get_app_scripts(api_key:, extension_point_type:)
65
+ def get_app_scripts(extension_point_type:)
67
66
  query_name = "get_app_scripts"
68
- variables = { appKey: api_key, extensionPointName: extension_point_type.upcase }
69
- response = MakeRequest.new(ctx).call(
70
- query_name: query_name,
71
- api_key: api_key,
72
- variables: variables
73
- )
67
+ variables = { appKey: @api_key, extensionPointName: extension_point_type.upcase }
68
+ response = make_request(query_name: query_name, variables: variables)
74
69
  response["data"]["appScripts"]
75
70
  end
76
71
 
77
- class ScriptServiceAPI < ShopifyCli::API
78
- property(:api_key, accepts: String)
79
-
80
- LOCAL_INSTANCE_URL = "https://script-service.myshopify.io"
81
-
82
- def self.query(ctx, query_name, api_key: nil, variables: {})
83
- api_client(ctx, api_key).query(query_name, variables: variables)
84
- end
85
-
86
- def self.api_client(ctx, api_key)
87
- instance_url = spin_instance_url || LOCAL_INSTANCE_URL
88
- new(
89
- ctx: ctx,
90
- url: "#{instance_url}/graphql",
91
- token: "",
92
- api_key: api_key
93
- )
94
- end
95
-
96
- def self.spin_instance_url
97
- workspace = ENV["SPIN_WORKSPACE"]
98
- namespace = ENV["SPIN_NAMESPACE"]
99
- return if workspace.nil? || namespace.nil?
100
-
101
- "https://script-service.#{workspace}.#{namespace}.us.spin.dev"
102
- end
103
-
104
- def auth_headers(*)
105
- tokens = { "APP_KEY" => api_key }.compact.to_json
106
- { "X-Shopify-Authenticated-Tokens" => tokens }
107
- end
108
- end
109
- private_constant(:ScriptServiceAPI)
110
-
111
- class PartnersProxyAPI < ShopifyCli::PartnersAPI
112
- def query(query_name, variables: {})
113
- variables[:query] = load_query(query_name)
114
- super("script_service_proxy", variables: variables)
115
- end
116
- end
117
- private_constant(:PartnersProxyAPI)
118
-
119
- class MakeRequest
120
- attr_reader :ctx
121
-
122
- def initialize(ctx)
123
- @ctx = ctx
124
- end
125
-
126
- def self.bypass_partners_proxy
127
- !ENV["BYPASS_PARTNERS_PROXY"].nil?
128
- end
129
-
130
- def call(query_name:, variables: nil, **options)
131
- resp = if MakeRequest.bypass_partners_proxy
132
- ScriptServiceAPI.query(ctx, query_name, variables: variables, **options)
133
- else
134
- proxy_through_partners(query_name: query_name, variables: variables, **options)
135
- end
136
- raise_if_graphql_failed(resp)
137
- resp
138
- end
139
-
140
- def proxy_through_partners(query_name:, variables: nil, **options)
141
- options[:variables] = variables.to_json if variables
142
- resp = PartnersProxyAPI.query(ctx, query_name, **options)
143
- raise_if_graphql_failed(resp)
144
- JSON.parse(resp["data"]["scriptServiceProxy"])
145
- end
72
+ def generate_module_upload_url
73
+ query_name = "module_upload_url_generate"
74
+ variables = {}
75
+ response = make_request(query_name: query_name, variables: variables)
76
+ user_errors = response["data"]["moduleUploadUrlGenerate"]["userErrors"]
146
77
 
147
- def raise_if_graphql_failed(response)
148
- raise Errors::EmptyResponseError if response.nil?
149
-
150
- return unless response.key?("errors")
151
- case error_code(response["errors"])
152
- when "forbidden"
153
- raise Errors::ForbiddenError
154
- when "forbidden_on_shop"
155
- raise Errors::ShopAuthenticationError
156
- when "app_not_installed_on_shop"
157
- raise Errors::AppNotInstalledError
158
- else
159
- raise Errors::GraphqlError, response["errors"]
160
- end
161
- end
162
-
163
- def error_code(errors)
164
- errors.map do |e|
165
- code = e.dig("extensions", "code")
166
- return code if code
167
- end
168
- end
78
+ raise Errors::GraphqlError, user_errors if user_errors.any?
79
+ response["data"]["moduleUploadUrlGenerate"]["url"]
169
80
  end
170
81
 
171
- class UploadScript
172
- attr_reader :ctx
173
-
174
- def initialize(ctx)
175
- @ctx = ctx
176
- end
177
-
178
- def call(api_key, script_content)
179
- apply_module_upload_url(api_key).tap do |url|
180
- upload(url, script_content)
181
- end
182
- end
183
-
184
- private
185
-
186
- def apply_module_upload_url(api_key)
187
- query_name = "module_upload_url_generate"
188
- variables = {}
189
- resp_hash = MakeRequest.new(ctx).call(query_name: query_name, api_key: api_key, variables: variables)
190
- user_errors = resp_hash["data"]["moduleUploadUrlGenerate"]["userErrors"]
82
+ private
191
83
 
192
- raise Errors::GraphqlError, user_errors if user_errors.any?
193
- resp_hash["data"]["moduleUploadUrlGenerate"]["url"]
194
- end
195
-
196
- def upload(url, script_content)
197
- url = URI(url)
198
-
199
- https = Net::HTTP.new(url.host, url.port)
200
- https.use_ssl = true
84
+ def make_request(query_name:, variables: {})
85
+ response = @client.query(query_name, variables: variables)
86
+ raise Errors::EmptyResponseError if response.nil?
87
+ raise Errors::GraphqlError, response["errors"] if response.key?("errors")
201
88
 
202
- request = Net::HTTP::Put.new(url)
203
- request["Content-Type"] = "application/wasm"
204
- request.body = script_content
205
-
206
- response = https.request(request)
207
- raise Errors::ScriptUploadError unless response.code == "200"
208
- end
89
+ response
209
90
  end
210
91
  end
211
92
  end
@@ -0,0 +1,27 @@
1
+ module Script
2
+ module Layers
3
+ module Infrastructure
4
+ class ScriptUploader
5
+ def initialize(script_service)
6
+ @script_service = script_service
7
+ end
8
+
9
+ def upload(script_content)
10
+ @script_service.generate_module_upload_url.tap do |url|
11
+ url = URI(url)
12
+
13
+ https = Net::HTTP.new(url.host, url.port)
14
+ https.use_ssl = true
15
+
16
+ request = Net::HTTP::Put.new(url)
17
+ request["Content-Type"] = "application/wasm"
18
+ request.body = script_content
19
+
20
+ response = https.request(request)
21
+ raise Errors::ScriptUploadError unless response.code == "200"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module Script
2
+ module Layers
3
+ module Infrastructure
4
+ class ServiceLocator
5
+ def self.api_client(ctx:, api_key:)
6
+ if ENV["BYPASS_PARTNERS_PROXY"]
7
+ ApiClients::ScriptServiceApiClient.new(ctx, api_key)
8
+ else
9
+ ApiClients::PartnersProxyApiClient.new(ctx, api_key)
10
+ end
11
+ end
12
+
13
+ def self.script_service(ctx:, api_key:)
14
+ client = api_client(ctx: ctx, api_key: api_key)
15
+ ScriptService.new(client: client, api_key: api_key)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -142,6 +142,10 @@ module Script
142
142
  "Check that your build npm script outputs the generated binary to the root of the directory." \
143
143
  "Generated binary should match the script name: <script_name>.wasm",
144
144
 
145
+ project_config_not_found: "Internal error - Script can't be created because the project's config file is missing from the repository.",
146
+
147
+ invalid_project_config: "Internal error - Script can't be created because the project's config file is invalid in the repository.",
148
+
145
149
  script_upload_cause: "Fail to upload script.",
146
150
  script_upload_help: "Try again.",
147
151
  },
@@ -2,7 +2,7 @@ require "shopify_cli"
2
2
 
3
3
  module Script
4
4
  module Tasks
5
- class EnsureEnv < ShopifyCli::Task
5
+ class EnsureEnv < ShopifyCLI::Task
6
6
  attr_accessor :ctx
7
7
 
8
8
  def call(ctx)
@@ -31,11 +31,11 @@ module Script
31
31
  def ask_org
32
32
  return stubbed_org if partner_proxy_bypass
33
33
 
34
- if ShopifyCli::Shopifolk.check && wants_to_run_against_shopify_org?
35
- ShopifyCli::Shopifolk.act_as_shopify_organization
34
+ if ShopifyCLI::Shopifolk.check && wants_to_run_against_shopify_org?
35
+ ShopifyCLI::Shopifolk.act_as_shopify_organization
36
36
  end
37
37
 
38
- orgs = ShopifyCli::PartnersAPI::Organizations.fetch_with_app(ctx)
38
+ orgs = ShopifyCLI::PartnersAPI::Organizations.fetch_with_app(ctx)
39
39
  if orgs.count == 1
40
40
  default = orgs.first
41
41
  ctx.puts(ctx.message("script.application.ensure_env.organization", default["businessName"], default["id"]))
@@ -69,7 +69,7 @@ module Script
69
69
  end
70
70
 
71
71
  def ask_app(apps)
72
- unless ShopifyCli::Shopifolk.acting_as_shopify_organization?
72
+ unless ShopifyCLI::Shopifolk.acting_as_shopify_organization?
73
73
  apps = apps.select { |app| app["appType"] == "custom" }
74
74
  end
75
75
 
@@ -89,8 +89,8 @@ module Script
89
89
  end
90
90
 
91
91
  def ask_script_uuid(app, extension_point_type)
92
- script_service = Layers::Infrastructure::ScriptService.new(ctx: ctx)
93
- scripts = script_service.get_app_scripts(api_key: app["apiKey"], extension_point_type: extension_point_type)
92
+ script_service = Layers::Infrastructure::ServiceLocator.script_service(ctx: ctx, api_key: app["apiKey"])
93
+ scripts = script_service.get_app_scripts(extension_point_type: extension_point_type)
94
94
 
95
95
  return nil unless scripts.count > 0 &&
96
96
  CLI::UI::Prompt.confirm(ctx.message("script.application.ensure_env.ask_connect_to_existing_script"))