shopify-cli 1.1.2 → 1.4.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.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +8 -0
- data/.github/workflows/release.yml +62 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +41 -2
- data/.rubocop_todo.yml +24 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +35 -36
- data/RELEASING.md +24 -26
- data/docs/core/index.md +16 -0
- data/lib/project_types/extension/cli.rb +6 -1
- data/lib/project_types/extension/commands/register.rb +1 -1
- data/lib/project_types/extension/features/argo/admin.rb +20 -0
- data/lib/project_types/extension/features/argo/base.rb +129 -0
- data/lib/project_types/extension/features/argo/checkout.rb +20 -0
- data/lib/project_types/extension/features/argo_config.rb +60 -0
- data/lib/project_types/extension/messages/messages.rb +11 -2
- data/lib/project_types/extension/models/type.rb +4 -0
- data/lib/project_types/extension/models/types/checkout_post_purchase.rb +6 -3
- data/lib/project_types/extension/models/types/product_subscription.rb +24 -0
- data/lib/project_types/node/commands/create.rb +6 -1
- data/lib/project_types/rails/commands/create.rb +6 -1
- data/lib/project_types/script/config/extension_points.yml +8 -8
- data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +2 -2
- data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +36 -1
- data/lib/project_types/script/layers/infrastructure/errors.rb +7 -0
- data/lib/project_types/script/messages/messages.rb +4 -3
- data/lib/project_types/script/ui/error_handler.rb +13 -5
- data/lib/shopify-cli/api.rb +5 -9
- data/lib/shopify-cli/commands/config.rb +33 -1
- data/lib/shopify-cli/commands/system.rb +9 -0
- data/lib/shopify-cli/core/entry_point.rb +1 -1
- data/lib/shopify-cli/core/monorail.rb +4 -3
- data/lib/shopify-cli/http_request.rb +15 -0
- data/lib/shopify-cli/js_system.rb +22 -5
- data/lib/shopify-cli/messages/messages.rb +30 -10
- data/lib/shopify-cli/project.rb +3 -3
- data/lib/shopify-cli/shopifolk.rb +67 -0
- data/lib/shopify-cli/tasks/create_api_client.rb +4 -2
- data/lib/shopify-cli/tasks/select_org_and_shop.rb +1 -0
- data/lib/shopify-cli/tunnel.rb +1 -1
- data/lib/shopify-cli/version.rb +1 -1
- data/lib/shopify_cli.rb +1 -0
- metadata +11 -4
- data/lib/project_types/extension/features/argo.rb +0 -48
- data/lib/project_types/extension/models/types/subscription_management.rb +0 -20
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Extension
|
3
|
+
module Features
|
4
|
+
module Argo
|
5
|
+
class Admin < Base
|
6
|
+
GIT_TEMPLATE = 'https://github.com/Shopify/argo-admin-template.git'
|
7
|
+
RENDERER_PACKAGE = '@shopify/argo-admin'
|
8
|
+
private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE
|
9
|
+
|
10
|
+
def git_template
|
11
|
+
GIT_TEMPLATE
|
12
|
+
end
|
13
|
+
|
14
|
+
def renderer_package_name
|
15
|
+
RENDERER_PACKAGE
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'base64'
|
3
|
+
require 'shopify_cli'
|
4
|
+
require 'semantic/semantic'
|
5
|
+
|
6
|
+
module Extension
|
7
|
+
module Features
|
8
|
+
module Argo
|
9
|
+
class Base
|
10
|
+
include SmartProperties
|
11
|
+
|
12
|
+
SCRIPT_PATH = %w(build main.js).freeze
|
13
|
+
|
14
|
+
NPM_LIST_COMMAND = %w(list).freeze
|
15
|
+
YARN_LIST_COMMAND = %w(list --pattern).freeze
|
16
|
+
NPM_LIST_PARAMETERS = %w(--prod).freeze
|
17
|
+
YARN_LIST_PARAMETERS = %w(--production).freeze
|
18
|
+
private_constant :NPM_LIST_COMMAND, :YARN_LIST_COMMAND, :NPM_LIST_PARAMETERS, :YARN_LIST_PARAMETERS
|
19
|
+
|
20
|
+
YARN_INSTALL_COMMAND = %w(install).freeze
|
21
|
+
YARN_INSTALL_PARAMETERS = %w(--silent).freeze
|
22
|
+
YARN_RUN_COMMAND = %w(run).freeze
|
23
|
+
YARN_RUN_SCRIPT_NAME = %w(build).freeze
|
24
|
+
private_constant :YARN_INSTALL_COMMAND, :YARN_INSTALL_PARAMETERS, :YARN_RUN_COMMAND, :YARN_RUN_SCRIPT_NAME
|
25
|
+
|
26
|
+
def create(directory_name, identifier, context)
|
27
|
+
Features::ArgoSetup.new(git_template: git_template).call(directory_name, identifier, context)
|
28
|
+
end
|
29
|
+
|
30
|
+
def config(context)
|
31
|
+
js_system = ShopifyCli::JsSystem.new(ctx: context)
|
32
|
+
if js_system.package_manager == 'yarn'
|
33
|
+
run_yarn_install(context, js_system)
|
34
|
+
run_yarn_run_script(context, js_system)
|
35
|
+
end
|
36
|
+
filepath = File.join(context.root, SCRIPT_PATH)
|
37
|
+
context.abort(context.message('features.argo.missing_file_error')) unless File.exist?(filepath)
|
38
|
+
begin
|
39
|
+
{
|
40
|
+
renderer_version: extract_argo_renderer_version(context),
|
41
|
+
serialized_script: Base64.strict_encode64(File.read(filepath).chomp),
|
42
|
+
}
|
43
|
+
rescue StandardError
|
44
|
+
context.abort(context.message('features.argo.script_prepare_error'))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def git_template
|
49
|
+
raise NotImplementedError, "'#{__method__}' must be implemented for #{self.class}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def renderer_package_name
|
53
|
+
# The renderer_package_name is used as a regex pattern to
|
54
|
+
# find a match in the output of yarn or npm list command.
|
55
|
+
# Use the full package name as it appears in the template without targeting a version.
|
56
|
+
# Examples: "@shopify/some-renderer-package", "argo-renderer-package"
|
57
|
+
|
58
|
+
raise NotImplementedError, "'#{__method__}' must be implemented for #{self.class}"
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def extract_argo_renderer_version(context)
|
64
|
+
result = run_list_command(context)
|
65
|
+
found_version = find_version_number(context, result)
|
66
|
+
context.abort(
|
67
|
+
context.message('features.argo.dependencies.argo_renderer_package_invalid_version_error')
|
68
|
+
) if found_version.nil?
|
69
|
+
::Semantic::Version.new(found_version).to_s
|
70
|
+
rescue ArgumentError
|
71
|
+
context.abort(
|
72
|
+
context.message('features.argo.dependencies.argo_renderer_package_invalid_version_error')
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
def find_version_number(context, result)
|
77
|
+
packages = result.to_json.split('\n')
|
78
|
+
found_package = packages.find do |package|
|
79
|
+
package.match(/#{renderer_package_name}@/)
|
80
|
+
end
|
81
|
+
if found_package.nil?
|
82
|
+
error = "'#{renderer_package_name}' not found."
|
83
|
+
context.abort(
|
84
|
+
context.message('features.argo.dependencies.argo_missing_renderer_package_error', error)
|
85
|
+
)
|
86
|
+
end
|
87
|
+
found_package.split('@')[2]&.strip
|
88
|
+
end
|
89
|
+
|
90
|
+
def run_list_command(context)
|
91
|
+
js_system = ShopifyCli::JsSystem.new(ctx: context)
|
92
|
+
result, error, status = js_system.call(
|
93
|
+
yarn: YARN_LIST_COMMAND + [renderer_package_name] + YARN_LIST_PARAMETERS,
|
94
|
+
npm: NPM_LIST_COMMAND + [renderer_package_name] + NPM_LIST_PARAMETERS,
|
95
|
+
capture_response: true
|
96
|
+
)
|
97
|
+
context.abort(
|
98
|
+
context.message('features.argo.dependencies.argo_missing_renderer_package_error', error)
|
99
|
+
) unless status.success?
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_yarn_install(context, js_system)
|
104
|
+
_result, error, status = js_system.call(
|
105
|
+
yarn: YARN_INSTALL_COMMAND + YARN_INSTALL_PARAMETERS,
|
106
|
+
npm: [],
|
107
|
+
capture_response: true
|
108
|
+
)
|
109
|
+
|
110
|
+
context.abort(
|
111
|
+
context.message('features.argo.dependencies.yarn_install_error', error)
|
112
|
+
) unless status.success?
|
113
|
+
end
|
114
|
+
|
115
|
+
def run_yarn_run_script(context, js_system)
|
116
|
+
_result, error, status = js_system.call(
|
117
|
+
yarn: YARN_RUN_COMMAND + YARN_RUN_SCRIPT_NAME,
|
118
|
+
npm: [],
|
119
|
+
capture_response: true
|
120
|
+
)
|
121
|
+
|
122
|
+
context.abort(
|
123
|
+
context.message('features.argo.dependencies.yarn_run_script_error', error)
|
124
|
+
) unless status.success?
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Extension
|
3
|
+
module Features
|
4
|
+
module Argo
|
5
|
+
class Checkout < Base
|
6
|
+
GIT_TEMPLATE = 'https://github.com/Shopify/argo-checkout-template.git'
|
7
|
+
RENDERER_PACKAGE = '@shopify/argo-checkout'
|
8
|
+
private_constant :GIT_TEMPLATE, :RENDERER_PACKAGE
|
9
|
+
|
10
|
+
def git_template
|
11
|
+
GIT_TEMPLATE
|
12
|
+
end
|
13
|
+
|
14
|
+
def renderer_package_name
|
15
|
+
RENDERER_PACKAGE
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Extension
|
4
|
+
module Features
|
5
|
+
class ArgoConfig
|
6
|
+
CONFIG_FILE_NAME = 'extension.config.yml'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def parse_yaml(context, permitted_keys = [])
|
10
|
+
file_name = File.join(context.root, CONFIG_FILE_NAME)
|
11
|
+
|
12
|
+
return {} unless File.size?(file_name)
|
13
|
+
|
14
|
+
require 'yaml' # takes 20ms, so deferred as late as possible.
|
15
|
+
begin
|
16
|
+
config = YAML.load_file(file_name)
|
17
|
+
|
18
|
+
# `YAML.load_file` returns nil if the file is not empty
|
19
|
+
# but does not contain any parsable yml data, e.g. only comments
|
20
|
+
# We consider this valid
|
21
|
+
return {} if config.nil?
|
22
|
+
|
23
|
+
unless config.is_a?(Hash)
|
24
|
+
raise ShopifyCli::Abort, ShopifyCli::Context.message('core.yaml.error.not_hash', CONFIG_FILE_NAME)
|
25
|
+
end
|
26
|
+
|
27
|
+
config.transform_keys!(&:to_sym)
|
28
|
+
assert_valid_config(config, permitted_keys) unless permitted_keys.empty?
|
29
|
+
|
30
|
+
config
|
31
|
+
rescue Psych::SyntaxError => e
|
32
|
+
raise(
|
33
|
+
ShopifyCli::Abort,
|
34
|
+
ShopifyCli::Context.message('core.yaml.error.invalid', CONFIG_FILE_NAME, e.message)
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def assert_valid_config(config, permitted_keys)
|
42
|
+
unpermitted_keys = config.keys.select do |k|
|
43
|
+
!permitted_keys.include?(k)
|
44
|
+
end
|
45
|
+
|
46
|
+
unless unpermitted_keys.empty?
|
47
|
+
raise(
|
48
|
+
ShopifyCli::Abort,
|
49
|
+
ShopifyCli::Context.message(
|
50
|
+
'features.argo.config.unpermitted_keys',
|
51
|
+
CONFIG_FILE_NAME,
|
52
|
+
unpermitted_keys.map { |k| "\n- #{k}" }.join
|
53
|
+
)
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -95,6 +95,15 @@ module Extension
|
|
95
95
|
node_not_installed: 'Node must be installed to create this extension.',
|
96
96
|
version_too_low: 'Your node version %s does not meet the minimum required version %s',
|
97
97
|
},
|
98
|
+
argo_missing_renderer_package_error: '%s Install the missing package and try again.',
|
99
|
+
argo_renderer_package_invalid_version_error: <<~MESSAGE,
|
100
|
+
The renderer package version is not a valid SemVer Version (http://semver.org)
|
101
|
+
MESSAGE
|
102
|
+
yarn_install_error: "Something went wrong while running 'yarn install'. %s.",
|
103
|
+
yarn_run_script_error: 'Something went wrong while running script. %s.',
|
104
|
+
},
|
105
|
+
config: {
|
106
|
+
unpermitted_keys: '`%s` contains the following unpermitted keys: %s',
|
98
107
|
},
|
99
108
|
},
|
100
109
|
},
|
@@ -109,8 +118,8 @@ module Extension
|
|
109
118
|
}
|
110
119
|
|
111
120
|
TYPES = {
|
112
|
-
|
113
|
-
name: 'Subscription
|
121
|
+
product_subscription: {
|
122
|
+
name: 'Product Subscription',
|
114
123
|
tagline: '(limit 1 per app)',
|
115
124
|
overrides: {
|
116
125
|
register: {
|
@@ -6,13 +6,16 @@ module Extension
|
|
6
6
|
module Types
|
7
7
|
class CheckoutPostPurchase < Models::Type
|
8
8
|
IDENTIFIER = 'CHECKOUT_POST_PURCHASE'
|
9
|
-
|
9
|
+
PERMITTED_CONFIG_KEYS = [:metafields]
|
10
10
|
def create(directory_name, context)
|
11
|
-
Features::Argo.
|
11
|
+
Features::Argo::Checkout.new.create(directory_name, IDENTIFIER, context)
|
12
12
|
end
|
13
13
|
|
14
14
|
def config(context)
|
15
|
-
|
15
|
+
{
|
16
|
+
**Features::ArgoConfig.parse_yaml(context, PERMITTED_CONFIG_KEYS),
|
17
|
+
**Features::Argo::Checkout.new.config(context),
|
18
|
+
}
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Extension
|
5
|
+
module Models
|
6
|
+
module Types
|
7
|
+
class ProductSubscription < Models::Type
|
8
|
+
IDENTIFIER = 'PRODUCT_SUBSCRIPTION'
|
9
|
+
|
10
|
+
def graphql_identifier
|
11
|
+
'SUBSCRIPTION_MANAGEMENT'
|
12
|
+
end
|
13
|
+
|
14
|
+
def create(directory_name, context)
|
15
|
+
Features::Argo::Admin.new.create(directory_name, IDENTIFIER, context)
|
16
|
+
end
|
17
|
+
|
18
|
+
def config(context)
|
19
|
+
Features::Argo::Admin.new.config(context)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -40,7 +40,7 @@ module Node
|
|
40
40
|
scopes: 'write_products,write_customers,write_draft_orders',
|
41
41
|
).write(@ctx)
|
42
42
|
|
43
|
-
partners_url = "
|
43
|
+
partners_url = "#{partners_endpoint}/#{form.organization_id}/apps/#{api_client['id']}"
|
44
44
|
|
45
45
|
@ctx.puts(@ctx.message('node.create.info.created', form.title, partners_url))
|
46
46
|
@ctx.puts(@ctx.message('node.create.info.serve', form.name, ShopifyCli::TOOL_NAME))
|
@@ -112,6 +112,11 @@ module Node
|
|
112
112
|
@ctx.debug(e)
|
113
113
|
end
|
114
114
|
end
|
115
|
+
|
116
|
+
def partners_endpoint
|
117
|
+
return 'https://partners.myshopify.io' if @ctx.getenv(ShopifyCli::PartnersAPI::LOCAL_DEBUG)
|
118
|
+
'https://partners.shopify.com'
|
119
|
+
end
|
115
120
|
end
|
116
121
|
end
|
117
122
|
end
|
@@ -55,7 +55,7 @@ module Rails
|
|
55
55
|
scopes: 'write_products,write_customers,write_draft_orders',
|
56
56
|
).write(@ctx)
|
57
57
|
|
58
|
-
partners_url = "
|
58
|
+
partners_url = "#{partners_endpoint}/#{form.organization_id}/apps/#{api_client['id']}"
|
59
59
|
|
60
60
|
@ctx.puts(@ctx.message('rails.create.info.created', form.title, partners_url))
|
61
61
|
@ctx.puts(@ctx.message('rails.create.info.serve', form.name, ShopifyCli::TOOL_NAME))
|
@@ -172,6 +172,11 @@ module Rails
|
|
172
172
|
def install_gem(name, version = nil)
|
173
173
|
Gem.install(@ctx, name, version)
|
174
174
|
end
|
175
|
+
|
176
|
+
def partners_endpoint
|
177
|
+
return 'https://partners.myshopify.io' if @ctx.getenv(ShopifyCli::PartnersAPI::LOCAL_DEBUG)
|
178
|
+
'https://partners.shopify.com'
|
179
|
+
end
|
175
180
|
end
|
176
181
|
end
|
177
182
|
end
|
@@ -1,24 +1,24 @@
|
|
1
1
|
discount:
|
2
2
|
assemblyscript:
|
3
3
|
package: "@shopify/extension-point-as-discount"
|
4
|
-
version: "^0.
|
5
|
-
sdk-version: "^
|
4
|
+
version: "^0.3.0"
|
5
|
+
sdk-version: "^7.0.0"
|
6
6
|
toolchain-version: "^1.1.0"
|
7
7
|
unit_limit_per_order:
|
8
8
|
assemblyscript:
|
9
9
|
package: "@shopify/extension-point-as-unit-limit-per-order"
|
10
|
-
version: "^0.
|
11
|
-
sdk-version: "^
|
10
|
+
version: "^0.2.0"
|
11
|
+
sdk-version: "^7.0.0"
|
12
12
|
toolchain-version: "^1.1.0"
|
13
13
|
payment_filter:
|
14
14
|
assemblyscript:
|
15
15
|
package: "@shopify/extension-point-as-payment-filter"
|
16
|
-
version: "^0.
|
17
|
-
sdk-version: "^
|
16
|
+
version: "^0.5.0"
|
17
|
+
sdk-version: "^7.0.0"
|
18
18
|
toolchain-version: "^1.1.0"
|
19
19
|
shipping_filter:
|
20
20
|
assemblyscript:
|
21
21
|
package: "@shopify/extension-point-as-shipping-filter"
|
22
|
-
version: "^0.
|
23
|
-
sdk-version: "^
|
22
|
+
version: "^0.3.0"
|
23
|
+
sdk-version: "^7.0.0"
|
24
24
|
toolchain-version: "^1.1.0"
|
@@ -86,8 +86,8 @@ module Script
|
|
86
86
|
"@shopify/scripts-toolchain-as": "#{extension_point.sdks[:ts].toolchain_version}",
|
87
87
|
"#{extension_point.sdks[:ts].package}": "#{extension_point.sdks[:ts].version}",
|
88
88
|
"@as-pect/cli": "4.0.0",
|
89
|
-
"as-wasi": "^0.2.
|
90
|
-
"assemblyscript": "^0.
|
89
|
+
"as-wasi": "^0.2.1",
|
90
|
+
"assemblyscript": "^0.14.0"
|
91
91
|
},
|
92
92
|
"scripts": {
|
93
93
|
"test": "asp --config test/as-pect.config.js --summary --verbose"
|
@@ -34,7 +34,9 @@ module Script
|
|
34
34
|
|
35
35
|
def dependencies_installed?
|
36
36
|
# Assuming if node_modules folder exist at root of script folder, all deps are installed
|
37
|
-
ctx.dir_exist?("node_modules")
|
37
|
+
return false unless ctx.dir_exist?("node_modules")
|
38
|
+
check_if_ep_dependencies_up_to_date!
|
39
|
+
true
|
38
40
|
end
|
39
41
|
|
40
42
|
private
|
@@ -58,6 +60,39 @@ module Script
|
|
58
60
|
def bytecode
|
59
61
|
File.read(format(BYTECODE_FILE, name: script_name))
|
60
62
|
end
|
63
|
+
|
64
|
+
def check_if_ep_dependencies_up_to_date!
|
65
|
+
return true if ENV['SHOPIFY_CLI_SCRIPTS_IGNORE_OUTDATED']
|
66
|
+
|
67
|
+
# ignore exit code since it will not be 0 unless every package is up to date which they probably won't be
|
68
|
+
out, _ = ctx.capture2e("npm", "outdated", "--json", "--depth", "0")
|
69
|
+
parsed_outdated_check = JSON.parse(out)
|
70
|
+
outdated_ep_packages = parsed_outdated_check
|
71
|
+
.select { |package_name, _| package_name.start_with?('@shopify/extension-point-as-') }
|
72
|
+
.select { |_, version_info| !package_is_up_to_date?(version_info) }
|
73
|
+
.keys
|
74
|
+
raise Errors::PackagesOutdatedError.new(outdated_ep_packages),
|
75
|
+
"NPM packages out of date: #{outdated_ep_packages.join(', ')}" unless outdated_ep_packages.empty?
|
76
|
+
end
|
77
|
+
|
78
|
+
def package_is_up_to_date?(version_info)
|
79
|
+
require 'semantic/semantic'
|
80
|
+
current_version = version_info['current']
|
81
|
+
latest_version = version_info['latest']
|
82
|
+
|
83
|
+
# making an assumption that the script developer knows what they're doing if they're not referencing a
|
84
|
+
# semver version
|
85
|
+
begin
|
86
|
+
current_version = ::Semantic::Version.new(current_version)
|
87
|
+
latest_version = ::Semantic::Version.new(latest_version)
|
88
|
+
rescue ArgumentError
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
|
92
|
+
return false if current_version.major < latest_version.major
|
93
|
+
return false if latest_version.major == 0 && current_version.minor < latest_version.minor
|
94
|
+
true
|
95
|
+
end
|
61
96
|
end
|
62
97
|
end
|
63
98
|
end
|