mirror of
https://github.com/robbyrussell/oh-my-zsh.git
synced 2026-09-27 21:46:08 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bcac0d11f | ||
|
|
e2be8df511 | ||
|
|
419fc5e9b5 | ||
|
|
338a1131c8 |
@@ -0,0 +1,112 @@
|
|||||||
|
# Shopify CLI plugin
|
||||||
|
|
||||||
|
This plugin adds aliases, helper functions and completion for the
|
||||||
|
[Shopify CLI](https://shopify.dev/docs/api/shopify-cli).
|
||||||
|
|
||||||
|
To use it, add `shopify` to the plugins array in your zshrc file:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
plugins=(... shopify)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
[Shopify CLI](https://shopify.dev/docs/api/shopify-cli) 4.0 or newer, installed
|
||||||
|
and on your `PATH`. The plugin does nothing if it is not:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
npm install -g @shopify/cli
|
||||||
|
# or
|
||||||
|
brew tap shopify/shopify && brew install shopify-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
| Alias | Command | Description |
|
||||||
|
| :----- | :-------- | :--------------------- |
|
||||||
|
| `shop` | `shopify` | The Shopify CLI itself |
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
| :------------- | :--------------------------------------------------------------------------------- |
|
||||||
|
| `shopd` | Runs `theme dev`, `app dev` or `hydrogen dev`, whichever fits the current project |
|
||||||
|
| `shopi` | Shows what the current project is connected to |
|
||||||
|
| `shopify_here` | Prints the kind of Shopify project you are in and the commands worth running in it |
|
||||||
|
| `shopify` | Wraps the CLI to confirm before irreversible commands. See Settings |
|
||||||
|
|
||||||
|
`shopd` and `shopi` work out which topic applies by looking at the project you
|
||||||
|
are standing in, so you do not have to remember whether this directory is a
|
||||||
|
theme, an app or a Hydrogen storefront. They complete like the command they
|
||||||
|
stand in for, so in a theme `shopd --<TAB>` offers the flags of
|
||||||
|
`shopify theme dev`.
|
||||||
|
|
||||||
|
## Completion
|
||||||
|
|
||||||
|
Every command completes with a description of what it does, at every level, and
|
||||||
|
so do their flags, short forms and allowed values. `--environment` completes
|
||||||
|
from the `[environments.*]` sections of your local `shopify.theme.toml` or
|
||||||
|
`shopify.app.toml`.
|
||||||
|
|
||||||
|
The Shopify CLI ships no completion generator of its own, so `_shopify` is
|
||||||
|
generated from `shopify commands --json` and kept in this repository. It targets
|
||||||
|
Shopify CLI 4.x.
|
||||||
|
|
||||||
|
## Settings
|
||||||
|
|
||||||
|
Set these with `zstyle` in your zshrc, before Oh My Zsh is sourced.
|
||||||
|
|
||||||
|
### Confirming destructive commands
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:shopify' confirm-destructive no
|
||||||
|
```
|
||||||
|
|
||||||
|
By default the plugin asks for confirmation before three irreversible
|
||||||
|
operations:
|
||||||
|
|
||||||
|
- `shopify theme push` with `--live`/`-l` or `--publish`/`-p`, which overwrites
|
||||||
|
or publishes the live storefront
|
||||||
|
- `shopify theme delete`, which the CLI's own help describes as impossible to
|
||||||
|
undo
|
||||||
|
- `shopify app deploy --allow-deletes`, which can permanently remove extensions
|
||||||
|
|
||||||
|
Nothing else is intercepted, and the prompt is skipped when the command already
|
||||||
|
carries `--force`/`-f` or when stdin is not a terminal, so scripts, pipelines
|
||||||
|
and CI are unaffected. Set the style to `no` to turn the prompt off entirely.
|
||||||
|
|
||||||
|
### Completing theme IDs
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:shopify' dynamic-theme-completion yes
|
||||||
|
```
|
||||||
|
|
||||||
|
Off by default. When enabled, `--theme` is completed from
|
||||||
|
`shopify theme list --json`, showing each theme's name and role next to its ID
|
||||||
|
instead of making you copy IDs by hand. It is opt-in because it runs the CLI and
|
||||||
|
makes a network call when you press <kbd>Tab</kbd>, and because it needs you to
|
||||||
|
be authenticated. Results are cached for five minutes.
|
||||||
|
|
||||||
|
### Disabling the aliases
|
||||||
|
|
||||||
|
This works for every Oh My Zsh plugin:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
zstyle ':omz:plugins:shopify' aliases no
|
||||||
|
```
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
- `shopify` is a shell function here. Run `command shopify` to reach the binary
|
||||||
|
directly.
|
||||||
|
- When a project has its own copy of the CLI in `node_modules/.bin/shopify`,
|
||||||
|
that one is used in preference to the global install. App and Hydrogen
|
||||||
|
projects normally pin the CLI in `package.json`, and running a different
|
||||||
|
global version against them is a common source of confusing errors.
|
||||||
|
- `--password` and `--store-password` are unrelated, and you often need both.
|
||||||
|
`--password` is the CLI's own authentication token, from the Theme Access app
|
||||||
|
or the Admin API. `--store-password` is the password for a
|
||||||
|
password-protected storefront.
|
||||||
|
- `shopify theme push` deletes remote files that are missing locally, and
|
||||||
|
`shopify theme pull` deletes local files that are missing remotely, unless you
|
||||||
|
pass `--nodelete`/`-n`. The plugin does not prompt for these.
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,203 @@
|
|||||||
|
# Shopify CLI: completion, aliases and guard rails.
|
||||||
|
# https://shopify.dev/docs/api/shopify-cli
|
||||||
|
|
||||||
|
if (( ! $+commands[shopify] )); then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prefer a project-local CLI: app and Hydrogen projects pin their own version.
|
||||||
|
# The walk stops at $HOME so a stray ~/node_modules cannot hijack every project.
|
||||||
|
# $commands avoids resolving back to the wrapper function below.
|
||||||
|
function _shopify_bin() {
|
||||||
|
local dir="$PWD"
|
||||||
|
while [[ -n "$dir" && "$dir" != "/" && "$dir" != "$HOME" ]]; do
|
||||||
|
if [[ -x "$dir/node_modules/.bin/shopify" ]]; then
|
||||||
|
print -r -- "$dir/node_modules/.bin/shopify"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
dir="${dir:h}"
|
||||||
|
done
|
||||||
|
print -r -- "$commands[shopify]"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print the project type in $PWD: hydrogen, app or theme.
|
||||||
|
# Hydrogen is tested first because those projects usually carry a
|
||||||
|
# shopify.app.toml too. shopify.theme.toml is not a theme marker: it only
|
||||||
|
# exists once environments are configured.
|
||||||
|
function _shopify_project_type() {
|
||||||
|
local dir="$PWD"
|
||||||
|
local -a app_config
|
||||||
|
|
||||||
|
while [[ -n "$dir" && "$dir" != "/" && "$dir" != "$HOME" ]]; do
|
||||||
|
if [[ -x "$dir/node_modules/.bin/h2" ]] ||
|
||||||
|
[[ -r "$dir/package.json" && "$(<"$dir/package.json")" == *'"@shopify/hydrogen"'* ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
app_config=("$dir"/shopify.app*.toml(N))
|
||||||
|
if (( $#app_config )); then
|
||||||
|
print -r -- app
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$dir/config/settings_schema.json" && -f "$dir/layout/theme.liquid" ]]; then
|
||||||
|
print -r -- theme
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
dir="${dir:h}"
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Does this invocation need confirming? Sets REPLY to the reason.
|
||||||
|
function _shopify_is_destructive() {
|
||||||
|
zstyle -T ':omz:plugins:shopify' confirm-destructive || return 1
|
||||||
|
|
||||||
|
# Nobody to answer: CI and pipelines are unaffected.
|
||||||
|
[[ -t 0 ]] || return 1
|
||||||
|
|
||||||
|
local topic="$1" subcommand="$2" arg
|
||||||
|
local -a long
|
||||||
|
local short=""
|
||||||
|
|
||||||
|
# Short flags can be bundled, so collect them as characters: -al counts as l.
|
||||||
|
for arg in "${@[3,-1]}"; do
|
||||||
|
[[ "$arg" == "--" ]] && break
|
||||||
|
case "$arg" in
|
||||||
|
--*) long+=("${arg%%=*}") ;;
|
||||||
|
-?*) short+="${${arg%%=*}#-}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# An explicit force flag states the intent already.
|
||||||
|
if (( long[(I)--force] )) || [[ "$short" == *f* ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$topic $subcommand" in
|
||||||
|
"theme push")
|
||||||
|
if (( long[(I)--live] || long[(I)--publish] )) || [[ "$short" == *[lp]* ]]; then
|
||||||
|
REPLY="this overwrites or publishes the live theme on the storefront."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"theme delete")
|
||||||
|
REPLY="deleting a theme cannot be undone."
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
"app deploy")
|
||||||
|
if (( long[(I)--allow-deletes] )); then
|
||||||
|
REPLY="this can permanently remove app extensions."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Adds a confirmation prompt before irreversible operations. Everything else
|
||||||
|
# passes straight through, so `theme dev` stays interactive and pipes stay clean.
|
||||||
|
function shopify() {
|
||||||
|
local REPLY
|
||||||
|
if _shopify_is_destructive "$@"; then
|
||||||
|
print -u2 -- "shopify: $REPLY"
|
||||||
|
if ! read -q "?Continue? [y/N] "; then
|
||||||
|
print -u2 -- ""
|
||||||
|
return 130
|
||||||
|
fi
|
||||||
|
print -u2 -- ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$(_shopify_bin)" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print the commands worth running in the current directory.
|
||||||
|
function shopify_here() {
|
||||||
|
local project_type
|
||||||
|
project_type="$(_shopify_project_type)"
|
||||||
|
|
||||||
|
case "$project_type" in
|
||||||
|
theme)
|
||||||
|
print -- "Shopify theme project."
|
||||||
|
print -- " shopify theme dev Preview locally with live reload"
|
||||||
|
print -- " shopify theme check Lint the theme"
|
||||||
|
print -- " shopify theme list List the themes on the store"
|
||||||
|
print -- " shopify theme pull Download a remote theme into this folder"
|
||||||
|
print -- " shopify theme push Upload this folder to a remote theme"
|
||||||
|
;;
|
||||||
|
app)
|
||||||
|
print -- "Shopify app project."
|
||||||
|
print -- " shopify app dev Run the app against a development store"
|
||||||
|
print -- " shopify app info Show how the app is configured"
|
||||||
|
print -- " shopify app deploy Deploy the app and its extensions"
|
||||||
|
print -- " shopify app logs Stream app logs"
|
||||||
|
;;
|
||||||
|
hydrogen)
|
||||||
|
print -- "Hydrogen storefront."
|
||||||
|
print -- " shopify hydrogen dev Run the storefront locally"
|
||||||
|
print -- " shopify hydrogen build Build for production"
|
||||||
|
print -- " shopify hydrogen deploy Deploy to Oxygen"
|
||||||
|
print -- " shopify hydrogen link Link this project to a storefront"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print -- "No Shopify project found here."
|
||||||
|
print -- " shopify theme init Start a new theme"
|
||||||
|
print -- " shopify app init Start a new app"
|
||||||
|
print -- " shopify hydrogen init Start a new Hydrogen storefront"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the dev server for whichever kind of project this is.
|
||||||
|
function shopd() {
|
||||||
|
local project_type
|
||||||
|
if ! project_type="$(_shopify_project_type)"; then
|
||||||
|
print -u2 -- "shopd: not inside a Shopify theme, app or Hydrogen project."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
shopify "$project_type" dev "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show what the current project is connected to.
|
||||||
|
function shopi() {
|
||||||
|
local project_type
|
||||||
|
if ! project_type="$(_shopify_project_type)"; then
|
||||||
|
print -u2 -- "shopi: not inside a Shopify theme, app or Hydrogen project."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
case "$project_type" in
|
||||||
|
hydrogen) shopify hydrogen list "$@" ;;
|
||||||
|
*) shopify "$project_type" info "$@" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Complete the helpers like the commands they stand in for.
|
||||||
|
if (( $+functions[compdef] )); then
|
||||||
|
_shopd() {
|
||||||
|
local project_type
|
||||||
|
project_type="$(_shopify_project_type)" || return 1
|
||||||
|
words=(shopify "$project_type" dev ${words[2,-1]})
|
||||||
|
(( CURRENT += 2 ))
|
||||||
|
_shopify
|
||||||
|
}
|
||||||
|
|
||||||
|
_shopi() {
|
||||||
|
local project_type
|
||||||
|
project_type="$(_shopify_project_type)" || return 1
|
||||||
|
if [[ "$project_type" == hydrogen ]]; then
|
||||||
|
words=(shopify hydrogen list ${words[2,-1]})
|
||||||
|
else
|
||||||
|
words=(shopify "$project_type" info ${words[2,-1]})
|
||||||
|
fi
|
||||||
|
(( CURRENT += 2 ))
|
||||||
|
_shopify
|
||||||
|
}
|
||||||
|
|
||||||
|
compdef _shopd shopd
|
||||||
|
compdef _shopi shopi
|
||||||
|
fi
|
||||||
|
|
||||||
|
alias shop='shopify'
|
||||||
Reference in New Issue
Block a user