simplified-shopify-cli 0.1.2 → 0.1.4

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 CHANGED
@@ -17,18 +17,36 @@ Works on macOS, Linux, and Windows. No extra setup for macOS/zsh.
17
17
  **PowerShell:** use `npm.cmd` and commands such as `si.cmd` and `sp.cmd`,
18
18
  or enable [short commands](#shell-setup).
19
19
 
20
- ## 2. Add your store
20
+ ## 2. Store Abreviations Mapping
21
21
 
22
- ```sh
23
- sinit -g
24
- sstores add demo example-store -g
22
+ Personal config is created automatically on install at `~/.sshop.json`.
23
+
24
+
25
+ | Command | Description |
26
+ | ----------------------------- | ------------------------------- |
27
+ | `sstores add <alias> <store>` | Add or update a store alias |
28
+ | `sstores remove <alias>` | Remove a store alias |
29
+ | `sstores .` | Edit stores in your config file |
30
+
31
+
32
+ Example `~/.sshop.json`:
33
+
34
+ ```jsonc
35
+ {
36
+ "version": 1,
37
+ "stores": {
38
+ "sto": "example-store.myshopify.com",
39
+ "san": "example-sandbox.myshopify.com"
40
+ },
41
+ "defaultStore": "san",
42
+ "defaults": {
43
+ "nodelete": true, // keep local files when pulling
44
+ "themeEditorSync": true // sync Theme Editor changes during dev
45
+ }
46
+ }
25
47
  ```
26
48
 
27
- - `demo`: your chosen store abbreviation.
28
- - `example-store`: the prefix of your `example-store.myshopify.com` address.
29
- - Repeat `sstores add` for each store.
30
49
 
31
- `-g` saves settings for all projects. Skip `sinit -g` if already configured.
32
50
 
33
51
  ## 3. Start working
34
52
 
@@ -52,37 +70,43 @@ the remembered store; see [configuration](#configuration).
52
70
  ## Command cheat sheet
53
71
 
54
72
  Run theme commands from your theme project folder. Put quotes around theme names
55
- with spaces. `<store_abr>` means the short name you configured, such as `demo`.
56
-
57
- | Command | What it does |
58
- | --- | --- |
59
- | `si <store_abr>` | Select a store |
60
- | `si` | Show current store and theme |
61
- | `sl` | List themes |
62
- | `sd` | Start a development theme |
63
- | `sd "My Theme"` | Develop a named theme with editor sync |
64
- | `sp` | Pull the live theme |
65
- | `sp "My Theme"` | Pull a named theme |
66
- | `sp -p` | Pull only live template/config JSON |
67
- | `spl "My Theme"` | Pull named theme template/config JSON |
68
- | `sp -d` | Pull the development theme |
69
- | `spa` | Pull live; may delete unmatched local files |
70
- | `sc` | Check theme code |
71
- | `sf` | Fix supported code issues |
72
- | `lo` | Log out of Shopify |
73
- | `shelp` | Show help |
73
+ with spaces. `<store_abr>` means the short name you configured, such as `san`.
74
+
75
+
76
+ | Command | What it does |
77
+ | ---------------- | ------------------------------------------- |
78
+ | `si <store_abr>` | Select a store |
79
+ | `si` | Show current store and theme |
80
+ | `sl` | List themes |
81
+ | `sd` | Start a development theme |
82
+ | `sd "My Theme"` | Develop a named theme with editor sync |
83
+ | `sp` | Pull the live theme |
84
+ | `sp "My Theme"` | Pull a named theme |
85
+ | `sp -p` | Pull only live template/config JSON |
86
+ | `spl "My Theme"` | Pull named theme template/config JSON |
87
+ | `sp -d` | Pull the development theme |
88
+ | `spa` | Pull live; may delete unmatched local files |
89
+ | `sc` | Check theme code |
90
+ | `sf` | Fix supported code issues |
91
+ | `lo` | Log out of Shopify |
92
+ | `shelp` | Show help |
93
+
94
+
95
+
74
96
 
75
97
  ### Options
76
98
 
77
- | Option | Example | Meaning |
78
- | --- | --- | --- |
79
- | `-g` / `--global` | `sinit -g` | Personal config (setup commands) |
80
- | `-d` / `--development` | `sp -d` | Development theme (`sp`, `spl`, `spa`, `si`) |
81
- | `-p PORT` / `--port PORT` | `sd -p 9293` | Change the development port |
82
- | `-p` / `--json-only` | `sp -p` | Pull only template/config JSON |
83
- | `-j` / `--json` | `sl -j` | JSON output (`sl`, `si`) |
84
- | `--dry-run` | `sd "My Theme" --dry-run` | Preview without running |
85
- | `-s` and `-t` | `sd -s demo -t "My Theme"` | Choose store and theme |
99
+
100
+ | Option | Example | Meaning |
101
+ | ------------------------- | -------------------------- | ------------------------------------------------------------------ |
102
+ | `-g` / `--global` | `sinit -g` | Personal config (`sinit`, `simport`; `sstores` defaults to global) |
103
+ | `-d` / `--development` | `sp -d` | Development theme (`sp`, `spl`, `spa`, `si`) |
104
+ | `-p PORT` / `--port PORT` | `sd -p 9293` | Change the development port |
105
+ | `-p` / `--json-only` | `sp -p` | Pull only template/config JSON |
106
+ | `-j` / `--json` | `sl -j` | JSON output (`sl`, `si`) |
107
+ | `--dry-run` | `sd "My Theme" --dry-run` | Preview without running |
108
+ | `-s` and `-t` | `sd -s demo -t "My Theme"` | Choose store and theme |
109
+
86
110
 
87
111
  **Before running commands:** `sp` overwrites matching local files; `spa` can also
88
112
  delete unmatched files. `sd` uploads and continuously syncs changes to the selected
@@ -90,23 +114,25 @@ remote theme. `sf` changes local code. Use `--dry-run` to check your target firs
90
114
 
91
115
  ## Manage your stores
92
116
 
93
- | Command | What it does |
94
- | --- | --- |
95
- | `sstores` | List store aliases |
96
- | `sstores add <store_abr> example-store -g` | Add or update an alias |
97
- | `sstores remove <store_abr> -g` | Remove an alias |
98
- | `sconfig` | Show settings and config locations |
99
- | `sinit` | Create a project config |
100
- | `sinit -g` | Create personal config (never overwrites) |
101
- | `simport ./base_custom_cli.sh -g` | Import legacy store aliases |
117
+
118
+ | Command | What it does |
119
+ | --------------------------------------- | ----------------------------------------- |
120
+ | `sstores` | List store aliases |
121
+ | `sstores add <store_abr> example-store` | Add or update an alias |
122
+ | `sstores remove <store_abr>` | Remove an alias |
123
+ | `sconfig` | Show settings and config locations |
124
+ | `sstores .` | Open your personal stores config |
125
+ | `sinit` | Create a project config |
126
+ | `sinit -g` | Create personal config (never overwrites) |
127
+ | `simport ./base_custom_cli.sh -g` | Import legacy store aliases |
128
+
102
129
 
103
130
  `sinit` creates config. `si` selects a store.
104
131
  Keep credentials out of `.sshop.json`. Keep personal project configs out of Git.
105
132
 
106
133
  ## Shell setup
107
134
 
108
- <details>
109
- <summary>Windows PowerShell: use commands without .cmd</summary>
135
+ Windows PowerShell: use commands without .cmd
110
136
 
111
137
  If your PowerShell profile allows scripts, add:
112
138
 
@@ -119,10 +145,7 @@ To undo, remove the line and restart PowerShell.
119
145
 
120
146
  Command Prompt needs no setup. For WSL, install Node and both CLIs inside WSL.
121
147
 
122
- </details>
123
-
124
- <details>
125
- <summary>macOS/zsh or Bash: replace older Shopify aliases</summary>
148
+ macOS/zsh or Bash: replace older Shopify aliases
126
149
 
127
150
  If old Shopify aliases override these commands, remove them or add this
128
151
  after them in your shell profile:
@@ -133,12 +156,9 @@ eval "$(sshop shell)"
133
156
 
134
157
  Restart your terminal.
135
158
 
136
- </details>
137
-
138
159
  ## Configuration
139
160
 
140
- <details>
141
- <summary>Optional settings</summary>
161
+ Optional settings
142
162
 
143
163
  - Personal config: `~/.sshop.json` (macOS/Linux) or `%USERPROFILE%\.sshop.json` (Windows).
144
164
  - Project config: `.sshop.json`; overrides personal settings. Omit `-g` to edit it.
@@ -155,9 +175,6 @@ Use `-s STORE` for an unconfigured store prefix.
155
175
  Put extra Shopify options after `--`: `sd -- --verbose`.
156
176
  Keep store/theme options and `--dry-run` before `--`.
157
177
 
158
-
159
- </details>
160
-
161
178
  ## Uninstall
162
179
 
163
180
  ```sh
@@ -166,4 +183,4 @@ npm uninstall -g simplified-shopify-cli
166
183
 
167
184
  Remove any optional shell profile line too. Your config files are kept.
168
185
 
169
- [MIT License](LICENSE)
186
+ [MIT License](LICENSE)
package/docs/RELEASING.md CHANGED
@@ -1,3 +1,13 @@
1
+ # Release 0.1.4
2
+
3
+ README fix: use `jsonc` for the config example so inline default comments preview correctly.
4
+
5
+ # Release 0.1.3
6
+
7
+ Store setup improvements: `sstores` defaults to global config, `sstores .` opens the
8
+ personal config file, install creates `~/.sshop.json` automatically, and the
9
+ cheat sheet PDF was regenerated.
10
+
1
11
  # Release 0.1.2
2
12
 
3
13
  README update
@@ -17,6 +27,9 @@ alias import, dry-run output, development port shorthand (`sd -p`), JSON output
17
27
 
18
28
  ## Verification
19
29
 
30
+ - Regenerate `output/pdf/shopify-command-cheat-sheet.pdf` with
31
+ `npm run generate:pdf` when command docs change (requires Python 3 and
32
+ `reportlab`).
20
33
  - Node 22/24 CI on macOS, Linux, and Windows checks the installed archive,
21
34
  command entry points, real Shopify CLI help, and PowerShell shortcuts.
22
35
  - `npm run release:check` checks syntax, runs tests, builds and installs an
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplified-shopify-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Configurable store aliases and shortcuts for Shopify theme development",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,6 +27,7 @@
27
27
  "files": [
28
28
  "bin/",
29
29
  "src/",
30
+ "scripts/postinstall.js",
30
31
  "shell/",
31
32
  "examples/",
32
33
  "docs/",
@@ -35,7 +36,9 @@
35
36
  ],
36
37
  "scripts": {
37
38
  "test": "node --test",
38
- "check": "node --check bin/sshop.js && node --check src/cli.js && node --check src/config.js && node --check src/commands.js",
39
+ "check": "node --check bin/sshop.js && node --check src/cli.js && node --check src/config.js && node --check src/commands.js && node --check scripts/postinstall.js",
40
+ "postinstall": "node scripts/postinstall.js",
41
+ "generate:pdf": "python3 scripts/generate-cheat-sheet.py",
39
42
  "prepack": "npm run check && npm test",
40
43
  "release:check": "npm run check && npm test && node scripts/check-package.js"
41
44
  },
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { filename, writeConfig } from '../src/config.js';
6
+
7
+ const file = path.join(os.homedir(), filename);
8
+ if (!fs.existsSync(file)) {
9
+ writeConfig(file, { version: 1, stores: {}, defaults: { nodelete: true, themeEditorSync: true } }, { create: true });
10
+ console.log(`Created ${file}`);
11
+ }
package/src/cli.js CHANGED
@@ -13,6 +13,7 @@ Usage: sshop [--config FILE] COMMAND [arguments]
13
13
  stores List merged store aliases
14
14
  stores add ALIAS STORE [--global] Add/update a store in the selected config
15
15
  stores remove ALIAS [--global] Remove a store from the selected config
16
+ stores . [--global] Open the stores config file in your editor
16
17
  import FILE [--global] Import literal map_store aliases
17
18
  config Show effective config and source files
18
19
  shell [powershell] Print shell functions (optional)
@@ -32,7 +33,7 @@ Dev options: --port/-p PORT (example: sd demo -p 9293)
32
33
  List/info options: --json/-j (example: sl demo -j)
33
34
  Pull options: --live, --development/-d, --json-only/-p
34
35
  Info options: --development/-d
35
- Config writes: --global/-g (init, stores add/remove, import)
36
+ Config writes: --global/-g (init, import; stores add/remove/. default to global)
36
37
  Additional Shopify flags go after -- (example: -- --port 9293).
37
38
  Select the current store with si STORE; then omit STORE on later theme commands.
38
39
  A configured defaultStore overrides the remembered Shopify store. Use si to check.
@@ -43,7 +44,7 @@ Direct commands: sd, sp, sl, si, spl, spa, sc, sf, lo.
43
44
  Setup commands: sinit, sstores, sconfig, simport, shelp.
44
45
  `;
45
46
 
46
- export async function main(argv) {
47
+ export async function main(argv, { open = openPath } = {}) {
47
48
  const args = [...argv];
48
49
  let explicit = process.env.SSHOP_CONFIG;
49
50
  if (args[0] === '--config') {
@@ -94,13 +95,26 @@ export async function main(argv) {
94
95
  }
95
96
  console.log(`Saved ${file}`); return 0;
96
97
  }
98
+ if (command === 'stores' && args[0] === '.') {
99
+ const normalized = args.map(arg => arg === '-g' ? '--global' : arg);
100
+ const useGlobal = normalized.includes('--global');
101
+ if (normalized.filter(arg => arg !== '--global' && arg !== '.').length) throw new Error('Usage: sshop stores . [--global]');
102
+ if (useGlobal && explicit) throw new Error('Choose --global or --config, not both.');
103
+ const file = explicit ? path.resolve(explicit) : path.join(useGlobal ? os.homedir() : process.cwd(), filename);
104
+ if (!fs.existsSync(file)) {
105
+ writeConfig(file, { version: 1, stores: {}, defaults: { nodelete: true, themeEditorSync: true } }, { create: true });
106
+ console.log(`Created ${file}`);
107
+ }
108
+ await open(file);
109
+ return 0;
110
+ }
97
111
  const loaded = loadConfig({ explicit });
98
112
  if (command === 'config') {
99
113
  if (args.length) throw new Error('Usage: sshop config');
100
114
  console.log(JSON.stringify(loaded, null, 2)); return 0;
101
115
  }
102
116
  if (command === 'stores') {
103
- if (args.length && !(args.length === 1 && args[0] === 'list')) throw new Error('Usage: sshop stores [list|add|remove]');
117
+ if (args.length && !(args.length === 1 && args[0] === 'list')) throw new Error('Usage: sshop stores [list|add|remove|.]');
104
118
  const entries = Object.entries(loaded.config.stores).sort(([a], [b]) => a.localeCompare(b));
105
119
  console.log(entries.length ? entries.map(([alias, store]) => `${alias}\t${normalizeStore(store)}`).join('\n') : 'No store aliases yet. Run: sshop stores add demo example-store');
106
120
  return 0;
@@ -110,6 +124,17 @@ export async function main(argv) {
110
124
  return runShopify(built.args);
111
125
  }
112
126
 
127
+ export async function openPath(target, { platform = process.platform } = {}) {
128
+ const opener = platform === 'darwin' ? ['open', target]
129
+ : platform === 'win32' ? ['cmd', '/c', 'start', '', target]
130
+ : ['xdg-open', target];
131
+ return new Promise((resolve, reject) => {
132
+ const child = spawn(opener[0], opener.slice(1), { stdio: 'ignore', shell: platform === 'win32' });
133
+ child.once('error', error => reject(new Error(error.code === 'ENOENT' ? `Could not open ${target}. Set EDITOR or open the file manually.` : error.message)));
134
+ child.once('exit', code => code === 0 ? resolve() : reject(new Error(`Could not open ${target}.`)));
135
+ });
136
+ }
137
+
113
138
  export async function runShopify(args, { platform = process.platform } = {}) {
114
139
  // Use argument arrays, never eval or a shell command string.
115
140
  // Windows npm exposes shopify.cmd; invoke the package's JS entry with Node instead.
package/src/entry.js CHANGED
@@ -1,9 +1,16 @@
1
1
  import { main } from './cli.js';
2
2
 
3
+ function usesGlobalStoresConfig(command, args) {
4
+ return command === 'stores' && ['add', 'remove', '.'].includes(args[0]);
5
+ }
6
+
3
7
  export async function runEntry(command, input = process.argv.slice(2)) {
4
8
  const args = [...input];
5
9
  const global = [];
6
10
  if (args[0] === '--config') global.push(...args.splice(0, 2));
11
+ if (usesGlobalStoresConfig(command, args) && !global.length && !args.some(arg => arg === '-g' || arg === '--global')) {
12
+ args.push('-g');
13
+ }
7
14
  try {
8
15
  process.exitCode = await main([...global, ...(['--help', '-h', '--version'].includes(args[0]) ? args : [command, ...args])]);
9
16
  } catch (error) {