@koda-sl/baker-cli 0.370.0-dev.0cc0d2b86 → 0.370.0-dev.1981aa822
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.
- package/README.md +7 -2
- package/dist/cli.js +285 -16
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3692,9 +3692,12 @@ baker shopify store # name, currency, home countr
|
|
|
3692
3692
|
baker shopify products --search "snowboard" # what the store sells: price, sale price, stock, where it can be bought
|
|
3693
3693
|
baker shopify products --stock out_of_stock # --stock in_stock|partly_out|out_of_stock, --collection <handle|id>
|
|
3694
3694
|
baker shopify products --limit 10 --cursor <c> # page with meta.next_cursor (25 by default, up to 100)
|
|
3695
|
-
baker shopify product <id|handle|link> # one product: options, prices by country, stock,
|
|
3695
|
+
baker shopify product <id|handle|link> # one product: options with buyUrl, prices by country, stock, photos, videos
|
|
3696
|
+
baker shopify product <handle> --content # its whole details: description, custom fields, subscriptions, translations
|
|
3697
|
+
baker shopify product <handle> --field "Size chart" # one custom field, whole
|
|
3698
|
+
baker shopify product <handle> --quantity 2 # buy links that put 2 of the option in the cart
|
|
3696
3699
|
baker shopify product <id> --out-of-stock # only the options that are out of stock (page with --variants-cursor)
|
|
3697
|
-
baker shopify collections --search "summer" # collections, with the handle --collection takes
|
|
3700
|
+
baker shopify collections --search "summer" # collections, with the handle --collection takes (--full: descriptions, images)
|
|
3698
3701
|
baker shopify stock --limit 20 # every product with every option out, and every product with some out
|
|
3699
3702
|
```
|
|
3700
3703
|
|
|
@@ -3702,6 +3705,8 @@ baker shopify stock --limit 20 # every product with every op
|
|
|
3702
3705
|
**`store`:** `--full` adds the admin link and every country. `capped: true` means a count stopped at its ceiling — `outOfStock` and `partlyOut` at 100, `collections` at 500 — so that count reads "that many or more"; a hint says which.
|
|
3703
3706
|
**`products`:** `--search <words>`, `--collection <handle|id>`, `--stock`, `--limit <1-100>`, `--cursor`; `--full` adds vendor, type, option count, photo link, visibility and status. Every price, here and in `product` (`price`, `compareAt`, each option's price, `pricesByCountry`), is one string with its currency beside each amount: `"USD 785.95"`, `"USD 9.95 – USD 49.95"`. A row's `availability` is absent when the product is on the store, `link_only` when it is buyable only through its link, `not_for_sale` (with `status`) when it can't be bought on the online store.
|
|
3704
3707
|
**`product`:** positional `<ref>` — the numeric id, the handle, a store product link (`…/products/<handle>`, even an all-digit handle), a Baker Products link, a Shopify admin product link (`admin.shopify.com/store/<shop>/products/<n>`), or `gid://shopify/Product/<n>`. Returns options (50 per page, `--variants-cursor` for more; 250 with `--full`), `outOptions` (up to 50, `outOptionsMore` for the rest), `pricesByCountry` when the store sells at more than one price, `photos[]` (`imageId` + a Baker-hosted `url`, never a Shopify link), `url` (the product's page in Baker) and `storeUrl`. `--full` adds the whole description, SEO, category, the admin link and each option's SKU, barcode, feed id and prices by country. `NOT_FOUND` carries a hint to search instead.
|
|
3708
|
+
|
|
3709
|
+
**Details and buy links (`product`):** every option carries `buyUrl` — the link for a page's buy button, following the store's own setting (`buyDestination`: `checkout`, `store_cart` or `product_page`) — with `buyUrlKind`, `unavailable` when it can't be bought, and `notes` for what a link can't do (`password_protected`, `subscription_only`, `subscription_optional`, `own_storefront`, `details_pending`). `--quantity <1-99>` sets how many it adds. `videos[]` lists the product's videos in the library (`videoId`, `playbackId`); `contentSummary` names what else Baker keeps. `--content` adds `content`: the formatted description, every custom field by its name (long values previewed, `truncated: true`), the rating, subscriptions, bundle, YouTube/Vimeo and 3D links, translations, and `unreadable` for content the store owner hasn't let Baker read yet. `--field <name|namespace.key>` returns one field whole. `--full` adds `--content`, all three links per option and each option's weight, unit price, shipping and tax. `store` adds `buyDestination`, `passwordProtected`, `languages`, `policies` (`--full`: their text, and the store's brand).
|
|
3705
3710
|
**`collections`:** `--search <words>`; each row has `handle`, Shopify's product count and, on a store with an online store, `onStore`.
|
|
3706
3711
|
**`stock`:** `--collection`, `--limit <1-200>` (default 50 per list), `--full` (SKUs and Baker links). Options that keep selling at zero or don't track stock are not out of stock.
|
|
3707
3712
|
|
package/dist/cli.js
CHANGED
|
@@ -8136,7 +8136,8 @@ var videoSourceSchema = z29.enum([
|
|
|
8136
8136
|
"twitter",
|
|
8137
8137
|
"vimeo",
|
|
8138
8138
|
"vk",
|
|
8139
|
-
"youtube"
|
|
8139
|
+
"youtube",
|
|
8140
|
+
"shopify"
|
|
8140
8141
|
]);
|
|
8141
8142
|
var videoTranscriptSegmentSchema = z29.object({
|
|
8142
8143
|
text: z29.string(),
|
|
@@ -64540,6 +64541,15 @@ var shopifyStoreConnectionSchema = z50.enum(["connected", "needs_reconnect", "di
|
|
|
64540
64541
|
var shopifyCatalogStateSchema = z50.enum(["starting", "importing", "ready", "failed"]);
|
|
64541
64542
|
var shopifyStorefrontSchema = z50.enum(["online_store", "own"]);
|
|
64542
64543
|
var shopifyAvailabilitySchema = z50.enum(["link_only", "not_for_sale"]);
|
|
64544
|
+
var shopifyBuyDestinationSchema = z50.enum(["checkout", "store_cart", "product_page"]);
|
|
64545
|
+
var shopifyBuyNoteSchema = z50.enum([
|
|
64546
|
+
"subscription_only",
|
|
64547
|
+
"subscription_optional",
|
|
64548
|
+
"password_protected",
|
|
64549
|
+
"own_storefront",
|
|
64550
|
+
"details_pending"
|
|
64551
|
+
]);
|
|
64552
|
+
var shopifyUnreadablePartSchema = z50.enum(["metaobjects", "definitions", "languages", "policies"]);
|
|
64543
64553
|
var shopifyStoreStateSchema = z50.object({
|
|
64544
64554
|
name: z50.string(),
|
|
64545
64555
|
connection: shopifyStoreConnectionSchema,
|
|
@@ -64564,13 +64574,24 @@ var shopifyProductsRequestSchema = z50.object({
|
|
|
64564
64574
|
cursor: z50.string().optional(),
|
|
64565
64575
|
full: flag.optional()
|
|
64566
64576
|
});
|
|
64577
|
+
var SHOPIFY_MAX_BUY_QUANTITY = 99;
|
|
64567
64578
|
var shopifyProductRequestSchema = z50.object({
|
|
64568
64579
|
ref: z50.string().min(1).max(500),
|
|
64569
64580
|
variantsCursor: z50.string().optional(),
|
|
64570
64581
|
outOfStock: flag.optional(),
|
|
64582
|
+
full: flag.optional(),
|
|
64583
|
+
/** The product's whole details: formatted description, custom fields, subscriptions, translations. */
|
|
64584
|
+
content: flag.optional(),
|
|
64585
|
+
/** One custom field whole, by its name or `namespace.key`. */
|
|
64586
|
+
field: z50.string().min(1).max(200).optional(),
|
|
64587
|
+
/** How many of the option each buy link puts in the cart (1-99, default 1). */
|
|
64588
|
+
quantity: z50.coerce.number().int().min(1).max(SHOPIFY_MAX_BUY_QUANTITY).optional()
|
|
64589
|
+
});
|
|
64590
|
+
var shopifyCollectionsRequestSchema = z50.object({
|
|
64591
|
+
search: z50.string().max(200).optional(),
|
|
64592
|
+
/** Each collection's description, image and SEO. */
|
|
64571
64593
|
full: flag.optional()
|
|
64572
64594
|
});
|
|
64573
|
-
var shopifyCollectionsRequestSchema = z50.object({ search: z50.string().max(200).optional() });
|
|
64574
64595
|
var shopifyStockRequestSchema = z50.object({
|
|
64575
64596
|
collection: z50.string().min(1).max(500).optional(),
|
|
64576
64597
|
limit: z50.coerce.number().int().min(1).max(200).optional(),
|
|
@@ -64602,8 +64623,35 @@ var shopifyStoreSummarySchema = z50.object({
|
|
|
64602
64623
|
})
|
|
64603
64624
|
).optional(),
|
|
64604
64625
|
productsUrl: z50.string(),
|
|
64626
|
+
/** Where the buy links send a shopper (S3b): the store's own setting, checkout unless changed. */
|
|
64627
|
+
buyDestination: shopifyBuyDestinationSchema,
|
|
64628
|
+
/** The store asks for a password before anyone can see it: a buy link meets it first. */
|
|
64629
|
+
passwordProtected: z50.literal(true).optional(),
|
|
64630
|
+
/** The store's published languages, primary first. */
|
|
64631
|
+
languages: z50.array(z50.object({ locale: z50.string(), name: z50.string(), primary: z50.boolean() })).optional(),
|
|
64632
|
+
policies: z50.array(
|
|
64633
|
+
z50.object({
|
|
64634
|
+
type: z50.string(),
|
|
64635
|
+
title: z50.string(),
|
|
64636
|
+
url: z50.string().optional(),
|
|
64637
|
+
// --full
|
|
64638
|
+
text: z50.string().optional()
|
|
64639
|
+
})
|
|
64640
|
+
).optional(),
|
|
64641
|
+
/** Store content Baker can't read until the store owner accepts Baker's new permissions. */
|
|
64642
|
+
unreadable: z50.array(shopifyUnreadablePartSchema).optional(),
|
|
64605
64643
|
// --full
|
|
64606
|
-
adminUrl: z50.string().optional()
|
|
64644
|
+
adminUrl: z50.string().optional(),
|
|
64645
|
+
brand: z50.object({
|
|
64646
|
+
slogan: z50.string().optional(),
|
|
64647
|
+
shortDescription: z50.string().optional(),
|
|
64648
|
+
logoUrl: z50.string().optional(),
|
|
64649
|
+
squareLogoUrl: z50.string().optional(),
|
|
64650
|
+
coverImageUrl: z50.string().optional(),
|
|
64651
|
+
colors: z50.array(
|
|
64652
|
+
z50.object({ role: z50.string(), background: z50.string().optional(), foreground: z50.string().optional() })
|
|
64653
|
+
)
|
|
64654
|
+
}).optional()
|
|
64607
64655
|
});
|
|
64608
64656
|
var shopifyStoreResponseSchema = z50.object({
|
|
64609
64657
|
store: shopifyStoreStateSchema,
|
|
@@ -64645,7 +64693,20 @@ var shopifyVariantSchema = z50.object({
|
|
|
64645
64693
|
compareAtPrice: shopifyPriceSchema.optional(),
|
|
64646
64694
|
stock: shopifyOptionStockSchema,
|
|
64647
64695
|
quantity: z50.number().optional(),
|
|
64696
|
+
/** The link for the page's buy button: never build a Shopify link by hand. Absent when the option can't be bought. */
|
|
64697
|
+
buyUrl: z50.string().optional(),
|
|
64698
|
+
buyUrlKind: shopifyBuyDestinationSchema.optional(),
|
|
64699
|
+
/** Why there is no buy link. */
|
|
64700
|
+
unavailable: z50.enum(["not_for_sale", "out_of_stock"]).optional(),
|
|
64701
|
+
notes: z50.array(shopifyBuyNoteSchema).optional(),
|
|
64648
64702
|
// --full
|
|
64703
|
+
checkout: z50.string().optional(),
|
|
64704
|
+
storeCart: z50.string().optional(),
|
|
64705
|
+
productPage: z50.string().optional(),
|
|
64706
|
+
weight: z50.string().optional(),
|
|
64707
|
+
unitPrice: z50.string().optional(),
|
|
64708
|
+
requiresShipping: z50.boolean().optional(),
|
|
64709
|
+
taxable: z50.boolean().optional(),
|
|
64649
64710
|
sku: z50.string().optional(),
|
|
64650
64711
|
barcode: z50.string().optional(),
|
|
64651
64712
|
selectedOptions: z50.array(z50.object({ name: z50.string(), value: z50.string() })).optional(),
|
|
@@ -64653,6 +64714,92 @@ var shopifyVariantSchema = z50.object({
|
|
|
64653
64714
|
inventoryPolicy: z50.enum(["DENY", "CONTINUE"]).optional(),
|
|
64654
64715
|
prices: z50.array(countryPriceSchema).optional()
|
|
64655
64716
|
});
|
|
64717
|
+
var shopifyProductVideoSchema = z50.object({
|
|
64718
|
+
videoId: z50.string(),
|
|
64719
|
+
playbackId: z50.string(),
|
|
64720
|
+
alt: z50.string().optional(),
|
|
64721
|
+
/** Seconds. */
|
|
64722
|
+
duration: z50.number().optional()
|
|
64723
|
+
});
|
|
64724
|
+
var shopifyFieldRefSchema = z50.object({
|
|
64725
|
+
kind: z50.enum(["image", "file", "video", "product", "variant", "collection", "metaobject", "other"]),
|
|
64726
|
+
id: z50.string(),
|
|
64727
|
+
url: z50.string().optional(),
|
|
64728
|
+
mimeType: z50.string().optional(),
|
|
64729
|
+
alt: z50.string().optional(),
|
|
64730
|
+
/** A product's or a collection's title, from Baker's copy. */
|
|
64731
|
+
title: z50.string().optional(),
|
|
64732
|
+
/** An image brought into the library: its imageId, to place like the product's photos. */
|
|
64733
|
+
imageId: z50.string().optional(),
|
|
64734
|
+
/** A custom content entry (a size chart, a care guide): its name and fields. */
|
|
64735
|
+
entry: z50.object({
|
|
64736
|
+
name: z50.string(),
|
|
64737
|
+
fields: z50.array(z50.object({ name: z50.string(), text: z50.string(), truncated: z50.literal(true).optional() }))
|
|
64738
|
+
}).optional()
|
|
64739
|
+
});
|
|
64740
|
+
var shopifyProductFieldSchema = z50.object({
|
|
64741
|
+
name: z50.string(),
|
|
64742
|
+
/** `namespace.key`: what `--field` takes when two fields share a name. */
|
|
64743
|
+
key: z50.string(),
|
|
64744
|
+
type: z50.string(),
|
|
64745
|
+
owner: z50.enum(["product", "option"]),
|
|
64746
|
+
variantId: z50.string().optional(),
|
|
64747
|
+
text: z50.string(),
|
|
64748
|
+
html: z50.string().optional(),
|
|
64749
|
+
refs: z50.array(shopifyFieldRefSchema).optional(),
|
|
64750
|
+
refsMore: z50.number().optional(),
|
|
64751
|
+
/** The text or the list is longer than shown: `--field <key>` returns it whole. */
|
|
64752
|
+
truncated: z50.literal(true).optional(),
|
|
64753
|
+
/** The store owner hasn't let Baker read what this field points at yet. */
|
|
64754
|
+
unreadable: z50.literal(true).optional()
|
|
64755
|
+
});
|
|
64756
|
+
var shopifyProductContentSchema = z50.object({
|
|
64757
|
+
descriptionHtml: z50.string(),
|
|
64758
|
+
descriptionTruncated: z50.literal(true).optional(),
|
|
64759
|
+
category: z50.string().optional(),
|
|
64760
|
+
giftCard: z50.literal(true).optional(),
|
|
64761
|
+
fields: z50.array(shopifyProductFieldSchema),
|
|
64762
|
+
rating: z50.object({ value: z50.number(), scaleMax: z50.number(), count: z50.number().optional() }).optional(),
|
|
64763
|
+
/** Subscriptions the product can be bought with; `subscriptionOnly` when only by subscription. */
|
|
64764
|
+
subscriptions: z50.array(
|
|
64765
|
+
z50.object({ name: z50.string(), plans: z50.array(z50.object({ name: z50.string(), category: z50.string().optional() })) })
|
|
64766
|
+
).optional(),
|
|
64767
|
+
subscriptionOnly: z50.literal(true).optional(),
|
|
64768
|
+
/** YouTube or Vimeo videos and 3D models: links with their preview image. */
|
|
64769
|
+
mediaLinks: z50.array(
|
|
64770
|
+
z50.object({
|
|
64771
|
+
kind: z50.enum(["external_video", "model_3d"]),
|
|
64772
|
+
url: z50.string(),
|
|
64773
|
+
embedUrl: z50.string().optional(),
|
|
64774
|
+
previewUrl: z50.string().optional(),
|
|
64775
|
+
alt: z50.string().optional()
|
|
64776
|
+
})
|
|
64777
|
+
),
|
|
64778
|
+
bundle: z50.array(z50.object({ productId: z50.string(), title: z50.string().optional(), quantity: z50.number() })).optional(),
|
|
64779
|
+
combinedListing: z50.object({ role: z50.string(), parentProductId: z50.string().optional(), childProductIds: z50.array(z50.string()) }).optional(),
|
|
64780
|
+
translations: z50.array(
|
|
64781
|
+
z50.object({
|
|
64782
|
+
locale: z50.string(),
|
|
64783
|
+
title: z50.string().optional(),
|
|
64784
|
+
description: z50.string().optional(),
|
|
64785
|
+
seoTitle: z50.string().optional(),
|
|
64786
|
+
seoDescription: z50.string().optional(),
|
|
64787
|
+
options: z50.array(
|
|
64788
|
+
z50.object({
|
|
64789
|
+
name: z50.string(),
|
|
64790
|
+
translatedName: z50.string().optional(),
|
|
64791
|
+
values: z50.array(z50.object({ value: z50.string(), translated: z50.string().optional() }))
|
|
64792
|
+
})
|
|
64793
|
+
),
|
|
64794
|
+
truncated: z50.literal(true).optional()
|
|
64795
|
+
})
|
|
64796
|
+
),
|
|
64797
|
+
/** Content the store owner hasn't let Baker read yet. */
|
|
64798
|
+
unreadable: z50.array(shopifyUnreadablePartSchema).optional(),
|
|
64799
|
+
/** Baker hasn't read this product's details yet, or Shopify didn't send some of them. */
|
|
64800
|
+
pending: z50.literal(true).optional(),
|
|
64801
|
+
failure: z50.string().optional()
|
|
64802
|
+
});
|
|
64656
64803
|
var shopifyProductDetailSchema = z50.object({
|
|
64657
64804
|
productId: z50.string(),
|
|
64658
64805
|
title: z50.string(),
|
|
@@ -64690,6 +64837,19 @@ var shopifyProductDetailSchema = z50.object({
|
|
|
64690
64837
|
).optional(),
|
|
64691
64838
|
/** When Baker last read this product from the store. */
|
|
64692
64839
|
observedAt: z50.string(),
|
|
64840
|
+
/** What else Baker keeps about it, in a line: "formatted description, 2 videos, Size chart, 4.7★ from 120 reviews". */
|
|
64841
|
+
contentSummary: z50.string().optional(),
|
|
64842
|
+
/** Its Shopify videos in the video library: place one with `<Video playbackId=…/>`. */
|
|
64843
|
+
videos: z50.array(shopifyProductVideoSchema),
|
|
64844
|
+
videosAdding: z50.number(),
|
|
64845
|
+
videosNotBrought: z50.number(),
|
|
64846
|
+
/** Where the buy links send a shopper, and how many each puts in the cart. */
|
|
64847
|
+
buyDestination: shopifyBuyDestinationSchema,
|
|
64848
|
+
quantity: z50.number(),
|
|
64849
|
+
/** --content (or --full): the whole of it. */
|
|
64850
|
+
content: shopifyProductContentSchema.optional(),
|
|
64851
|
+
/** --field: one custom field, whole. */
|
|
64852
|
+
field: shopifyProductFieldSchema.optional(),
|
|
64693
64853
|
// --full
|
|
64694
64854
|
visibility: shopifyVisibilitySchema.optional(),
|
|
64695
64855
|
seo: z50.object({ title: z50.string().optional(), description: z50.string().optional() }).optional(),
|
|
@@ -64706,7 +64866,11 @@ var shopifyCollectionRowSchema = z50.object({
|
|
|
64706
64866
|
handle: z50.string(),
|
|
64707
64867
|
/** Shopify's count at Baker's last read. */
|
|
64708
64868
|
products: z50.number(),
|
|
64709
|
-
onStore: z50.boolean().optional()
|
|
64869
|
+
onStore: z50.boolean().optional(),
|
|
64870
|
+
// --full
|
|
64871
|
+
description: z50.string().optional(),
|
|
64872
|
+
imageUrl: z50.string().optional(),
|
|
64873
|
+
seo: z50.object({ title: z50.string().optional(), description: z50.string().optional() }).optional()
|
|
64710
64874
|
});
|
|
64711
64875
|
var shopifyCollectionsResponseSchema = z50.object({
|
|
64712
64876
|
store: shopifyStoreStateSchema,
|
|
@@ -64848,8 +65012,56 @@ function stockHintsFor(product) {
|
|
|
64848
65012
|
}
|
|
64849
65013
|
return hints2;
|
|
64850
65014
|
}
|
|
65015
|
+
var BUY_NOTES = {
|
|
65016
|
+
password_protected: "The store asks for a password before anyone can see it: a shopper following a buy link meets it first \u2014 tell the user before sending traffic.",
|
|
65017
|
+
subscription_optional: "It can also be bought by subscription, but a buy link can only add it once \u2014 say so if the page promotes the subscription.",
|
|
65018
|
+
own_storefront: "The store sells through its own storefront: buy links go straight to Shopify's checkout.",
|
|
65019
|
+
details_pending: "Baker hasn't read this product's details yet (subscriptions among them): its buy links may change.",
|
|
65020
|
+
subscription_only: "It's sold only by subscription, which a buy link can't carry: its buy link is the product page, where the shopper picks the plan."
|
|
65021
|
+
};
|
|
65022
|
+
function buyHints(product) {
|
|
65023
|
+
const hints2 = [];
|
|
65024
|
+
if (product.variants.some((variant) => variant.buyUrl)) {
|
|
65025
|
+
hints2.push(
|
|
65026
|
+
`Use each option's \`buyUrl\` for the page's buy button \u2014 never build a Shopify link yourself (it follows the store's setting: ${product.buyDestination.replace("_", " ")}; \`--quantity <n>\` sets how many).`
|
|
65027
|
+
);
|
|
65028
|
+
}
|
|
65029
|
+
const notes = new Set(product.variants.flatMap((variant) => variant.notes ?? []));
|
|
65030
|
+
for (const note of notes) hints2.push(BUY_NOTES[note]);
|
|
65031
|
+
return hints2;
|
|
65032
|
+
}
|
|
65033
|
+
function contentHints(product) {
|
|
65034
|
+
const hints2 = [];
|
|
65035
|
+
const [video] = product.videos;
|
|
65036
|
+
if (video) {
|
|
65037
|
+
hints2.push(
|
|
65038
|
+
`Its videos are already in the video library: place one with \`<Video playbackId="${video.playbackId}" />\` \u2014 never a Shopify video link.`
|
|
65039
|
+
);
|
|
65040
|
+
}
|
|
65041
|
+
if (product.videosNotBrought > 0) {
|
|
65042
|
+
hints2.push(
|
|
65043
|
+
`${product.videosNotBrought} more videos stay in Shopify (Baker keeps up to 5 per product); use the ones listed.`
|
|
65044
|
+
);
|
|
65045
|
+
}
|
|
65046
|
+
if (product.videosAdding > 0) hints2.push(`${product.videosAdding} videos are still being added.`);
|
|
65047
|
+
if (product.contentSummary && !product.content) {
|
|
65048
|
+
hints2.push(
|
|
65049
|
+
"For a landing or an ad, read the whole of it with `--content` (formatted description, custom fields, subscriptions, translations)."
|
|
65050
|
+
);
|
|
65051
|
+
}
|
|
65052
|
+
const truncated = product.content?.fields.find((field) => field.truncated);
|
|
65053
|
+
if (truncated) {
|
|
65054
|
+
hints2.push(`Some fields are shown in part: read one whole with \`--field ${truncated.key}\`.`);
|
|
65055
|
+
}
|
|
65056
|
+
if (product.content?.unreadable?.length || product.content?.fields.some((field) => field.unreadable)) {
|
|
65057
|
+
hints2.push(
|
|
65058
|
+
"Some content isn't readable yet: ask the user to open Baker in their Shopify admin and accept the new permissions."
|
|
65059
|
+
);
|
|
65060
|
+
}
|
|
65061
|
+
return hints2;
|
|
65062
|
+
}
|
|
64851
65063
|
function productHints(product, store) {
|
|
64852
|
-
const hints2 = [...photoHints(product), ...stockHintsFor(product)];
|
|
65064
|
+
const hints2 = [...photoHints(product), ...stockHintsFor(product), ...buyHints(product), ...contentHints(product)];
|
|
64853
65065
|
if (product.availability === "not_for_sale") {
|
|
64854
65066
|
hints2.push(
|
|
64855
65067
|
`Can't be bought on the online store (${(product.status ?? "hidden").toLowerCase()}): a page or ad linking to it sends people to a page they can't buy from.`
|
|
@@ -64899,6 +65111,16 @@ function stockHints(answer, limit) {
|
|
|
64899
65111
|
}
|
|
64900
65112
|
function storeHints(summary) {
|
|
64901
65113
|
const hints2 = ["Share the Products page link (productsUrl) when the user wants to browse the catalog."];
|
|
65114
|
+
if (summary.unreadable?.length) {
|
|
65115
|
+
hints2.push(
|
|
65116
|
+
"Some of the store's content isn't readable yet: ask the user to open Baker in their Shopify admin and accept the new permissions."
|
|
65117
|
+
);
|
|
65118
|
+
}
|
|
65119
|
+
if (summary.passwordProtected) {
|
|
65120
|
+
hints2.push(
|
|
65121
|
+
"The store asks for a password before anyone can see it: shoppers from a landing or an ad meet it first."
|
|
65122
|
+
);
|
|
65123
|
+
}
|
|
64902
65124
|
if (summary.capped) {
|
|
64903
65125
|
const atCeiling = [
|
|
64904
65126
|
summary.outOfStock >= SHOPIFY_STOCK_COUNT_CAP ? `${SHOPIFY_STOCK_COUNT_CAP} or more products out of stock` : null,
|
|
@@ -64972,8 +65194,13 @@ var fullArg = {
|
|
|
64972
65194
|
};
|
|
64973
65195
|
registerSchema({
|
|
64974
65196
|
command: "shopify.store",
|
|
64975
|
-
description: 'Start here for the connected Shopify store: its name, currency, home country, how many products and collections it has, how many products are out of stock or partly out, the prices by country it sells at (only when it has more than one), and the link to the Products page in Baker. `capped: true` means a count stopped at its ceiling (100 out of stock or partly out, 500 collections): say "100 or more", never the number as exact. `meta.store` says whether Baker\'s copy is complete and whether Baker can still reach the store.',
|
|
64976
|
-
args: {
|
|
65197
|
+
description: 'Start here for the connected Shopify store: its name, currency, home country, how many products and collections it has, how many products are out of stock or partly out, the prices by country it sells at (only when it has more than one), where its buy links send a shopper (`buyDestination`: checkout, store_cart or product_page), its languages and policies, whether it asks for a password, and the link to the Products page in Baker. `capped: true` means a count stopped at its ceiling (100 out of stock or partly out, 500 collections): say "100 or more", never the number as exact. `meta.store` says whether Baker\'s copy is complete and whether Baker can still reach the store.',
|
|
65198
|
+
args: {
|
|
65199
|
+
full: {
|
|
65200
|
+
...fullArg,
|
|
65201
|
+
description: "Add the store's products page in Shopify admin, every country, each policy's text and the store's brand"
|
|
65202
|
+
}
|
|
65203
|
+
}
|
|
64977
65204
|
});
|
|
64978
65205
|
registerSchema({
|
|
64979
65206
|
command: "shopify.products",
|
|
@@ -65002,7 +65229,7 @@ registerSchema({
|
|
|
65002
65229
|
});
|
|
65003
65230
|
registerSchema({
|
|
65004
65231
|
command: "shopify.product",
|
|
65005
|
-
description: "One product of the connected store \u2014 accepts its id, its handle, a link to it on the store, in Baker or in Shopify admin. Returns its options with price and
|
|
65232
|
+
description: "One product of the connected store \u2014 accepts its id, its handle, a link to it on the store, in Baker or in Shopify admin. Returns its options with price, stock and `buyUrl` (the link for a page's buy button \u2014 never build a Shopify link yourself), prices by country, the options out of stock, its collections, its photos' library imageIds to place on a landing (`baker images download <imageIds> --out src/pages/<page>/_images/`) or pass to a creative, its videos' playbackIds (`<Video playbackId=\u2026/>`), and `contentSummary`: what else Baker keeps about it. Start here for a landing from a product: add `--content` for the formatted description, every custom field by its name (a size chart, care instructions), the rating, subscriptions and translations; `--field <name>` returns one field whole. `--out-of-stock` lists only the options out of stock.",
|
|
65006
65233
|
args: {
|
|
65007
65234
|
ref: { type: "positional", description: "Product id, handle, or a link to the product", required: true },
|
|
65008
65235
|
"variants-cursor": {
|
|
@@ -65016,16 +65243,35 @@ registerSchema({
|
|
|
65016
65243
|
required: false,
|
|
65017
65244
|
default: false
|
|
65018
65245
|
},
|
|
65246
|
+
content: {
|
|
65247
|
+
type: "boolean",
|
|
65248
|
+
description: "Its whole details: formatted description, custom fields by name (long ones previewed), rating, subscriptions, YouTube/3D links, translations",
|
|
65249
|
+
required: false,
|
|
65250
|
+
default: false
|
|
65251
|
+
},
|
|
65252
|
+
field: {
|
|
65253
|
+
type: "string",
|
|
65254
|
+
description: 'One custom field whole, by its name or its key (e.g. "Size chart" or custom.size_chart)',
|
|
65255
|
+
required: false
|
|
65256
|
+
},
|
|
65257
|
+
quantity: {
|
|
65258
|
+
type: "number",
|
|
65259
|
+
description: "How many of the option each buy link puts in the cart, 1-99 (default 1)",
|
|
65260
|
+
required: false
|
|
65261
|
+
},
|
|
65019
65262
|
full: {
|
|
65020
65263
|
...fullArg,
|
|
65021
|
-
description: "
|
|
65264
|
+
description: "Its details (as --content), whole description, SEO, category, admin link, 250 options per page with SKU, prices by country, every buy link and each option's weight, unit price, shipping and tax"
|
|
65022
65265
|
}
|
|
65023
65266
|
}
|
|
65024
65267
|
});
|
|
65025
65268
|
registerSchema({
|
|
65026
65269
|
command: "shopify.collections",
|
|
65027
|
-
description: "The connected store's collections, with the handle `--collection` takes and how many products Shopify counts in each.",
|
|
65028
|
-
args: {
|
|
65270
|
+
description: "The connected store's collections, with the handle `--collection` takes and how many products Shopify counts in each. `--full` adds each one's description, image and SEO.",
|
|
65271
|
+
args: {
|
|
65272
|
+
search: { type: "string", description: "Words in the collection's title or handle", required: false },
|
|
65273
|
+
full: { ...fullArg, description: "Add each collection's description, image and SEO" }
|
|
65274
|
+
}
|
|
65029
65275
|
});
|
|
65030
65276
|
registerSchema({
|
|
65031
65277
|
command: "shopify.stock",
|
|
@@ -65102,7 +65348,7 @@ var productsCommand = defineCommand209({
|
|
|
65102
65348
|
var productCommand = defineCommand209({
|
|
65103
65349
|
meta: {
|
|
65104
65350
|
name: "product",
|
|
65105
|
-
description: "One product: options, prices by country, stock, photo imageIds. Accepts an id, handle or link. Example: baker shopify product the-complete-snowboard"
|
|
65351
|
+
description: "One product: options with buy links, prices by country, stock, photo imageIds, video playbackIds. Accepts an id, handle or link. Example: baker shopify product the-complete-snowboard --content"
|
|
65106
65352
|
},
|
|
65107
65353
|
args: {
|
|
65108
65354
|
ref: { type: "positional", description: "Product id, handle, or a link to the product", required: true },
|
|
@@ -65112,6 +65358,18 @@ var productCommand = defineCommand209({
|
|
|
65112
65358
|
required: false
|
|
65113
65359
|
},
|
|
65114
65360
|
"out-of-stock": { type: "boolean", description: "Only the options out of stock", required: false, default: false },
|
|
65361
|
+
content: {
|
|
65362
|
+
type: "boolean",
|
|
65363
|
+
description: "Its whole details: formatted description, custom fields, subscriptions, translations",
|
|
65364
|
+
required: false,
|
|
65365
|
+
default: false
|
|
65366
|
+
},
|
|
65367
|
+
field: { type: "string", description: "One custom field whole, by its name or key", required: false },
|
|
65368
|
+
quantity: {
|
|
65369
|
+
type: "string",
|
|
65370
|
+
description: "How many each buy link puts in the cart, 1-99 (default 1)",
|
|
65371
|
+
required: false
|
|
65372
|
+
},
|
|
65115
65373
|
full: { type: "boolean", description: "Everything Baker keeps about it", required: false, default: false }
|
|
65116
65374
|
},
|
|
65117
65375
|
run: async ({ args: args5 }) => {
|
|
@@ -65129,6 +65387,9 @@ var productCommand = defineCommand209({
|
|
|
65129
65387
|
ref: args5.ref,
|
|
65130
65388
|
variantsCursor: args5["variants-cursor"],
|
|
65131
65389
|
outOfStock: args5["out-of-stock"],
|
|
65390
|
+
content: args5.content,
|
|
65391
|
+
field: args5.field,
|
|
65392
|
+
quantity: args5.quantity,
|
|
65132
65393
|
full: args5.full
|
|
65133
65394
|
})
|
|
65134
65395
|
);
|
|
@@ -65144,14 +65405,17 @@ var productCommand = defineCommand209({
|
|
|
65144
65405
|
var collectionsCommand = defineCommand209({
|
|
65145
65406
|
meta: {
|
|
65146
65407
|
name: "collections",
|
|
65147
|
-
description: "The store's collections, with the handles --collection takes. Example: baker shopify collections"
|
|
65408
|
+
description: "The store's collections, with the handles --collection takes. Example: baker shopify collections --full"
|
|
65409
|
+
},
|
|
65410
|
+
args: {
|
|
65411
|
+
search: { type: "string", description: "Words in the title or handle", required: false },
|
|
65412
|
+
full: { type: "boolean", description: "Add description, image and SEO", required: false, default: false }
|
|
65148
65413
|
},
|
|
65149
|
-
args: { search: { type: "string", description: "Words in the title or handle", required: false } },
|
|
65150
65414
|
run: async ({ args: args5 }) => {
|
|
65151
65415
|
try {
|
|
65152
65416
|
const answer = await apiGet(
|
|
65153
65417
|
"/api/shopify/collections",
|
|
65154
|
-
params({ search: args5.search })
|
|
65418
|
+
params({ search: args5.search, full: args5.full })
|
|
65155
65419
|
);
|
|
65156
65420
|
emit2(
|
|
65157
65421
|
answer.collections,
|
|
@@ -65197,13 +65461,18 @@ Examples:
|
|
|
65197
65461
|
baker shopify store # currency, countries, how many products, what is out of stock
|
|
65198
65462
|
baker shopify products --search "snowboard" # what we sell, with price and stock
|
|
65199
65463
|
baker shopify products --stock out_of_stock # --stock in_stock|partly_out|out_of_stock, --collection <handle>
|
|
65200
|
-
baker shopify product the-complete-snowboard # one product: options, prices
|
|
65464
|
+
baker shopify product the-complete-snowboard # one product: options with buyUrl, prices, photos, videos
|
|
65465
|
+
baker shopify product <handle> --content # its whole details: description, custom fields, subscriptions
|
|
65466
|
+
baker shopify product <handle> --field "Size chart" # one custom field, whole
|
|
65467
|
+
baker shopify product <handle> --quantity 2 # buy links that put 2 in the cart
|
|
65201
65468
|
baker shopify product <id> --out-of-stock # only its options that are out of stock
|
|
65202
65469
|
baker shopify stock # every product with options out of stock
|
|
65203
65470
|
baker shopify collections # collections, with handles for --collection
|
|
65204
65471
|
|
|
65205
65472
|
Product photos are already in the image library: place them by imageId
|
|
65206
65473
|
(baker images download <imageIds> --out src/pages/<page>/_images/), never by a cdn.shopify.com link.
|
|
65474
|
+
Product videos are in the video library: place them with <Video playbackId="\u2026" />.
|
|
65475
|
+
A page's buy button uses the option's buyUrl \u2014 never build a Shopify link yourself.
|
|
65207
65476
|
NO_SHOPIFY_CONNECTION means no store is connected: follow error.fix. SHOPIFY_NOT_AVAILABLE means it cannot be
|
|
65208
65477
|
connected here yet: carry on without it.
|
|
65209
65478
|
Full guide: __tooling__/docs/tools/baker/shopify.md`
|