heyquarry-shopify-profile-sync 0.1.0
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
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d468da3b0e40914a555e63fe18f42324843da1cf9a34efc14bcce700b4356e7b
|
|
4
|
+
data.tar.gz: 4241e02242faf3241fc5c574fd2c3aa87d69ce5ceec628ef28ae34d26df5766f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 3f02c4cfad47cfcca693269c4f103a262632ea20fa31d74d9cd2db8c26971fbd152c3a255e2d1a2d55d52612aab3e3ba7e5e5f5e63aa5dbfb50c083ac8fa03f1
|
|
7
|
+
data.tar.gz: a70874641192926d0028392f09fa167a07071a11c5cc3be01bb79e74d13b8ba2273d140e701815f4533fb00c422f165b97226b02a2aac6531d44f004333c505c
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HeyQuarry
|
|
4
|
+
module ShopifyProfileSync
|
|
5
|
+
SHOP_PROFILE_QUERY = <<~GRAPHQL.squish
|
|
6
|
+
query HeyQuarryShopProfile {
|
|
7
|
+
shop {
|
|
8
|
+
id
|
|
9
|
+
name
|
|
10
|
+
email
|
|
11
|
+
contactEmail
|
|
12
|
+
myshopifyDomain
|
|
13
|
+
description
|
|
14
|
+
plan { displayName }
|
|
15
|
+
billingAddress { phone countryCodeV2 }
|
|
16
|
+
primaryDomain { host }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
GRAPHQL
|
|
20
|
+
|
|
21
|
+
module ShopQuery
|
|
22
|
+
module_function
|
|
23
|
+
|
|
24
|
+
def map_shop_to_payload(shop)
|
|
25
|
+
return nil unless shop.is_a?(Hash) && shop["myshopifyDomain"]
|
|
26
|
+
|
|
27
|
+
email = shop["email"]&.strip
|
|
28
|
+
email = shop["contactEmail"]&.strip if email.nil? || email.empty?
|
|
29
|
+
|
|
30
|
+
payload = { shopDomain: shop["myshopifyDomain"] }
|
|
31
|
+
payload[:email] = email if email && !email.empty?
|
|
32
|
+
payload[:phone] = shop.dig("billingAddress", "phone") if shop.dig("billingAddress", "phone")
|
|
33
|
+
payload[:shopifyPlan] = shop.dig("plan", "displayName") if shop.dig("plan", "displayName")
|
|
34
|
+
payload[:countryCode] = shop.dig("billingAddress", "countryCodeV2") if shop.dig("billingAddress", "countryCodeV2")
|
|
35
|
+
payload[:customDomain] = shop.dig("primaryDomain", "host") if shop.dig("primaryDomain", "host")
|
|
36
|
+
payload[:about] = shop["description"] if shop["description"]
|
|
37
|
+
payload[:shopGid] = shop["id"] if shop["id"]
|
|
38
|
+
payload[:shopName] = shop["name"] if shop["name"]
|
|
39
|
+
payload
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
module HeyQuarry
|
|
8
|
+
module ShopifyProfileSync
|
|
9
|
+
DEFAULT_PROFILE_URL = "https://www.heyquarry.com/api/shopify/shops/profile"
|
|
10
|
+
DEFAULT_ADMIN_API_VERSION = "2026-01"
|
|
11
|
+
|
|
12
|
+
SyncResult = Struct.new(:ok, :skipped, :shop_domain, :status, :error, keyword_init: true)
|
|
13
|
+
|
|
14
|
+
module Sync
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
def sync_from_session(shop_domain:, access_token:, api_key: nil, profile_url: nil, admin_api_version: DEFAULT_ADMIN_API_VERSION)
|
|
18
|
+
resolved = resolve_options(api_key: api_key, profile_url: profile_url)
|
|
19
|
+
shop = fetch_shop_from_session(shop_domain, access_token, admin_api_version)
|
|
20
|
+
payload = ShopQuery.map_shop_to_payload(shop)
|
|
21
|
+
return skipped("Shop profile missing myshopifyDomain") unless payload
|
|
22
|
+
|
|
23
|
+
post_profile(resolved[:profile_url], resolved[:api_key], payload)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def sync_from_admin_client(client, api_key: nil, profile_url: nil)
|
|
27
|
+
resolved = resolve_options(api_key: api_key, profile_url: profile_url)
|
|
28
|
+
response = client.query(query: SHOP_PROFILE_QUERY)
|
|
29
|
+
shop = response.body.dig("data", "shop")
|
|
30
|
+
payload = ShopQuery.map_shop_to_payload(shop)
|
|
31
|
+
return skipped("Shop profile missing myshopifyDomain") unless payload
|
|
32
|
+
|
|
33
|
+
post_profile(resolved[:profile_url], resolved[:api_key], payload)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def post_profile_to_heyquarry(payload, api_key: nil, profile_url: nil)
|
|
37
|
+
resolved = resolve_options(api_key: api_key, profile_url: profile_url)
|
|
38
|
+
return skipped("shopDomain is required") unless payload.is_a?(Hash) && payload[:shopDomain]
|
|
39
|
+
|
|
40
|
+
post_profile(resolved[:profile_url], resolved[:api_key], payload)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def resolve_options(api_key:, profile_url:)
|
|
44
|
+
key = api_key || ENV["HEYQUARRY_APP_API_KEY"]
|
|
45
|
+
raise ArgumentError, "HeyQuarry app API key is required. Pass api_key: or set HEYQUARRY_APP_API_KEY." if key.nil? || key.strip.empty?
|
|
46
|
+
|
|
47
|
+
url = profile_url || ENV["HEYQUARRY_PROFILE_URL"] || DEFAULT_PROFILE_URL
|
|
48
|
+
{ api_key: key.strip, profile_url: url.sub(%r{/\z}, "") }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def fetch_shop_from_session(shop_domain, access_token, admin_api_version)
|
|
52
|
+
host = shop_domain.sub(%r{\Ahttps?://}, "").sub(%r{/\z}, "")
|
|
53
|
+
uri = URI("https://#{host}/admin/api/#{admin_api_version}/graphql.json")
|
|
54
|
+
request = Net::HTTP::Post.new(uri)
|
|
55
|
+
request["Content-Type"] = "application/json"
|
|
56
|
+
request["X-Shopify-Access-Token"] = access_token
|
|
57
|
+
request.body = JSON.generate(query: SHOP_PROFILE_QUERY)
|
|
58
|
+
|
|
59
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
|
|
60
|
+
JSON.parse(response.body).dig("data", "shop")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def post_profile(profile_url, api_key, payload)
|
|
64
|
+
uri = URI(profile_url)
|
|
65
|
+
request = Net::HTTP::Post.new(uri)
|
|
66
|
+
request["Content-Type"] = "application/json"
|
|
67
|
+
request["X-App-Api-Key"] = api_key
|
|
68
|
+
request.body = JSON.generate(payload.transform_keys(&:to_s))
|
|
69
|
+
|
|
70
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(request) }
|
|
71
|
+
if response.is_a?(Net::HTTPSuccess)
|
|
72
|
+
SyncResult.new(ok: true, shop_domain: payload[:shopDomain], status: response.code.to_i)
|
|
73
|
+
else
|
|
74
|
+
SyncResult.new(
|
|
75
|
+
ok: false,
|
|
76
|
+
shop_domain: payload[:shopDomain],
|
|
77
|
+
status: response.code.to_i,
|
|
78
|
+
error: response.body.to_s[0, 300].presence || response.message,
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def skipped(message)
|
|
84
|
+
SyncResult.new(ok: false, skipped: true, error: message)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: heyquarry-shopify-profile-sync
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- HeyQuarry
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description:
|
|
14
|
+
email:
|
|
15
|
+
- support@heyquarry.com
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- lib/heyquarry/shopify_profile_sync.rb
|
|
21
|
+
- lib/heyquarry/shopify_profile_sync/shop_query.rb
|
|
22
|
+
- lib/heyquarry/shopify_profile_sync/sync.rb
|
|
23
|
+
- lib/heyquarry/shopify_profile_sync/version.rb
|
|
24
|
+
homepage: https://heyquarry.com
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT
|
|
27
|
+
metadata: {}
|
|
28
|
+
post_install_message:
|
|
29
|
+
rdoc_options: []
|
|
30
|
+
require_paths:
|
|
31
|
+
- lib
|
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
33
|
+
requirements:
|
|
34
|
+
- - ">="
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: 3.0.0
|
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
requirements: []
|
|
43
|
+
rubygems_version: 3.5.22
|
|
44
|
+
signing_key:
|
|
45
|
+
specification_version: 4
|
|
46
|
+
summary: Sync Shopify shop profile (email, plan, phone) to HeyQuarry after OAuth install.
|
|
47
|
+
test_files: []
|