Setting the file. One moment.
Discovery Reads · Rp Source Shopify · wix/skills · Skills Docs
ContentsBack to the top of the page lib/discovery-reads.js
lib/ discovery-reads.js
JavaScript · 219 lines · 9 KB
SAMPLE_LIMIT
=
3
;
15
16 const DISCOUNT_FIELDS = 'title status startsAt endsAt' ;
17 const DISCOUNT_TYPES = [
18 'DiscountCodeBasic' , 'DiscountCodeBxgy' , 'DiscountCodeFreeShipping' ,
19 'DiscountAutomaticBasic' , 'DiscountAutomaticBxgy' , 'DiscountAutomaticFreeShipping' ,
20 ];
21
22 const ENTITY_READS = Object. freeze ([
23 {
24 entity: 'products' ,
25 scopes: [ 'read_products' ],
26 count: 'query RpShopifyDiscoveryProductsCount { productsCount(limit: null) { count precision } }' ,
27 countPath: [ 'productsCount' ],
28 sample: `query RpShopifyDiscoveryProducts($first: Int!) { products(first: $first) { nodes {
29 id title handle status productType vendor tags createdAt updatedAt
30 options { name values }
31 variants(first: 3) { nodes { id title sku price compareAtPrice inventoryQuantity } }
32 } } }` ,
33 samplePath: [ 'products' ],
34 },
35 {
36 entity: 'collections' ,
37 scopes: [ 'read_products' ],
38 sample: `query RpShopifyDiscoveryCollections($first: Int!) { collections(first: $first) { nodes {
39 id title handle updatedAt sortOrder ruleSet { appliedDisjunctively }
40 } } }` ,
41 samplePath: [ 'collections' ],
42 },
43 {
44 entity: 'orders' ,
45 scopes: [ 'read_orders' , 'read_fulfillments' ],
46 count: 'query RpShopifyDiscoveryOrdersCount { ordersCount(limit: null) { count precision } }' ,
47 countPath: [ 'ordersCount' ],
48 sample: `query RpShopifyDiscoveryOrders($first: Int!) { orders(first: $first) { nodes {
49 id name createdAt processedAt cancelledAt currencyCode presentmentCurrencyCode displayFinancialStatus displayFulfillmentStatus
50 totalPriceSet { shopMoney { amount currencyCode } }
51 refunds { id createdAt }
52 fulfillments { id status createdAt }
53 } } }` ,
54 samplePath: [ 'orders' ],
55 },
56 {
57 entity: 'customers' ,
58 scopes: [ 'read_customers' ],
59 count: 'query RpShopifyDiscoveryCustomersCount { customersCount(limit: null) { count precision } }' ,
60 countPath: [ 'customersCount' ],
61 sample: `query RpShopifyDiscoveryCustomers($first: Int!) { customers(first: $first) { nodes {
62 id createdAt updatedAt tags numberOfOrders verifiedEmail
63 } } }` ,
64 samplePath: [ 'customers' ],
65 },
66 {
67 entity: 'gift-cards' ,
68 scopes: [ 'read_gift_cards' ],
69 count: 'query RpShopifyDiscoveryGiftCardsCount { giftCardsCount(limit: null) { count precision } }' ,
70 countPath: [ 'giftCardsCount' ],
71 sample: `query RpShopifyDiscoveryGiftCards($first: Int!) { giftCards(first: $first) { nodes {
72 id lastCharacters enabled createdAt expiresOn
73 initialValue { amount currencyCode } balance { amount currencyCode }
74 } } }` ,
75 samplePath: [ 'giftCards' ],
76 },
77 {
78 entity: 'discounts' ,
79 scopes: [ 'read_discounts' , 'read_price_rules' ],
80 sample: `query RpShopifyDiscoveryDiscounts($first: Int!) { discountNodes(first: $first) { nodes {
81 id discount { __typename ${ DISCOUNT_TYPES . map (( type ) => `... on ${ type } { ${ DISCOUNT_FIELDS } }` ). join ( ' ' ) } }
82 } } }` ,
83 samplePath: [ 'discountNodes' ],
84 },
85 {
86 entity: 'pages' ,
87 scopes: [ 'read_content' ],
88 sample: 'query RpShopifyDiscoveryPages($first: Int!) { pages(first: $first) { nodes { id title handle isPublished createdAt updatedAt } } }' ,
89 samplePath: [ 'pages' ],
90 },
91 {
92 entity: 'blogs' ,
93 scopes: [ 'read_content' ],
94 sample: 'query RpShopifyDiscoveryBlogs($first: Int!) { blogs(first: $first) { nodes { id title handle createdAt updatedAt } } }' ,
95 samplePath: [ 'blogs' ],
96 },
97 {
98 entity: 'articles' ,
99 scopes: [ 'read_content' ],
100 sample: 'query RpShopifyDiscoveryArticles($first: Int!) { articles(first: $first) { nodes { id title handle tags publishedAt createdAt blog { id } } } }' ,
101 samplePath: [ 'articles' ],
102 },
103 {
104 entity: 'menus' ,
105 scopes: [ 'read_online_store_navigation' ],
106 sample: 'query RpShopifyDiscoveryMenus($first: Int!) { menus(first: $first) { nodes { id title handle items { title type url } } } }' ,
107 samplePath: [ 'menus' ],
108 },
109 {
110 entity: 'locations' ,
111 scopes: [ 'read_locations' ],
112 sample: 'query RpShopifyDiscoveryLocations($first: Int!) { locations(first: $first) { nodes { id name isActive address { city countryCode } } } }' ,
113 samplePath: [ 'locations' ],
114 },
115 {
116 entity: 'inventory-items' ,
117 scopes: [ 'read_inventory' ],
118 sample: 'query RpShopifyDiscoveryInventoryItems($first: Int!) { inventoryItems(first: $first) { nodes { id sku tracked createdAt updatedAt } } }' ,
119 samplePath: [ 'inventoryItems' ],
120 },
121 {
122 entity: 'delivery-profiles' ,
123 scopes: [ 'read_shipping' ],
124 sample: 'query RpShopifyDiscoveryDeliveryProfiles($first: Int!) { deliveryProfiles(first: $first) { nodes { id name default } } }' ,
125 samplePath: [ 'deliveryProfiles' ],
126 },
127 {
128 // `metaobjects` needs a `type` argument, so discovery lists the definitions (each with its own
129 // count); an extract reads each type's metaobjects from them.
130 entity: 'metaobjects' ,
131 scopes: [ 'read_metaobjects' ],
132 sample: 'query RpShopifyDiscoveryMetaobjectDefinitions($first: Int!) { metaobjectDefinitions(first: $first) { nodes { id type name metaobjectsCount } } }' ,
133 samplePath: [ 'metaobjectDefinitions' ],
134 },
135 {
136 entity: 'files' ,
137 scopes: [ 'read_files' ],
138 sample: 'query RpShopifyDiscoveryFiles($first: Int!) { files(first: $first) { nodes { __typename id alt createdAt fileStatus } } }' ,
139 samplePath: [ 'files' ],
140 },
141 {
142 entity: 'url-redirects' ,
143 scopes: [ 'read_online_store_navigation' ],
144 sample: 'query RpShopifyDiscoveryUrlRedirects($first: Int!) { urlRedirects(first: $first) { nodes { id path target } } }' ,
145 samplePath: [ 'urlRedirects' ],
146 },
147 ]);
148
149 const SINGLETON_READS = Object. freeze ([
150 {
151 entity: 'shop' ,
152 scopes: [],
153 sample: 'query RpShopifyDiscoveryShop { shop { id name myshopifyDomain currencyCode ianaTimezone primaryDomain { host } } }' ,
154 samplePath: [ 'shop' ],
155 },
156 {
157 // `shopPolicies` returns ShopPolicy objects, which require read_legal_policies.
158 entity: 'shop-policies' ,
159 scopes: [ 'read_legal_policies' ],
160 sample: 'query RpShopifyDiscoveryShopPolicies { shop { shopPolicies { type title url } } }' ,
161 samplePath: [ 'shop' , 'shopPolicies' ],
162 },
163 ]);
164
165 const ALL_READS = Object. freeze ([ ... ENTITY_READS , ... SINGLETON_READS ]);
166
167 // The order-window step: the shop's creation time, and -- only for a store younger
168 // than the window -- the visible order with the earliest `processedAt`, which shows whether
169 // back-dated (imported) orders exist. Not entity captures: they never become capture rows.
170 const ORDER_WINDOW_READS = Object. freeze ([
171 {
172 entity: 'shop-created-at' ,
173 scopes: [],
174 query: 'query RpShopifyDiscoveryShopCreatedAt { shop { id createdAt } }' ,
175 },
176 {
177 entity: 'oldest-processed-order' ,
178 scopes: [ 'read_orders' ],
179 query: 'query RpShopifyDiscoveryOldestProcessedOrder { orders(first: 1, sortKey: PROCESSED_AT) { nodes { id processedAt } } }' ,
180 },
181 ]);
182
183 // The regional step: the shop's languages and country. Not entity captures: they never become
184 // capture rows. The currency and time zone come from the `shop` singleton above, not a second read.
185 // `shopLocales` needs the locales read scope, which discovery does not require: a denied read is an
186 // explicit unknown in the regional file, never a failed discovery -- so its `scopes` stay empty and
187 // it is a separate query from the country, which needs no scope.
188 const REGIONAL_READS = Object. freeze ([
189 {
190 entity: 'shop-locales' ,
191 scopes: [],
192 query: 'query RpShopifyDiscoveryShopLocales { shopLocales { locale primary published } }' ,
193 },
194 {
195 entity: 'shop-country' ,
196 scopes: [],
197 query: 'query RpShopifyDiscoveryShopCountry { shop { billingAddress { countryCodeV2 } } }' ,
198 },
199 ]);
200
201 function operationName ( query ) {
202 const match = / \b query \s + ( [A-Za-z_][A-Za-z0-9_] * )/ . exec ( String (query || '' ));
203 return match ? match[ 1 ] : null ;
204 }
205
206 function at ( object , pathParts ) {
207 return pathParts. reduce (( value , key ) => (value && typeof value === 'object' ? value[key] : undefined ), object);
208 }
209
210 module . exports = {
211 SAMPLE_LIMIT,
212 ENTITY_READS,
213 SINGLETON_READS,
214 ALL_READS,
215 ORDER_WINDOW_READS,
216 REGIONAL_READS,
217 operationName,
218 at,
219 };