climaybe 3.1.1 → 3.1.2
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 +1 -1
- package/bin/version.txt +1 -1
- package/package.json +1 -1
- package/src/commands/switch.js +6 -1
- package/src/index.js +1 -1
- package/src/lib/build-scripts.js +33 -8
- package/src/lib/config.js +32 -1
- package/src/lib/dev-runtime.js +3 -2
- package/src/lib/theme-dev-kit.js +1 -0
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ Switch your local dev environment to a specific store (multi-store only).
|
|
|
94
94
|
npx climaybe switch voldt-norway
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
Copies `stores/<alias>/` JSON files to the repo root so you can preview that store locally.
|
|
97
|
+
Copies `stores/<alias>/` JSON files to the repo root so you can preview that store locally, and sets `default_store` in `climaybe.config.json` so `climaybe serve` / `shopify theme dev` targets that store. If your current git branch is `staging-<alias>` or `live-<alias>`, `climaybe serve` uses that store’s domain from config (even if `default_store` differs), matching CI preview behavior.
|
|
98
98
|
|
|
99
99
|
### `climaybe sync [alias]` / `climaybe theme sync`
|
|
100
100
|
|
package/bin/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.1.
|
|
1
|
+
3.1.2
|
package/package.json
CHANGED
package/src/commands/switch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
|
-
import { getStoreAliases, getMode } from '../lib/config.js';
|
|
2
|
+
import { getStoreAliases, getMode, readConfig, writeConfig } from '../lib/config.js';
|
|
3
3
|
import { storesToRoot } from '../lib/store-sync.js';
|
|
4
4
|
import { requireThemeProject } from '../lib/theme-guard.js';
|
|
5
5
|
|
|
@@ -23,6 +23,11 @@ export async function switchCommand(alias) {
|
|
|
23
23
|
|
|
24
24
|
const ok = storesToRoot(alias);
|
|
25
25
|
if (ok) {
|
|
26
|
+
const config = readConfig();
|
|
27
|
+
const domain = config?.stores?.[alias];
|
|
28
|
+
if (domain) {
|
|
29
|
+
writeConfig({ default_store: domain });
|
|
30
|
+
}
|
|
26
31
|
console.log(pc.bold(pc.green(`\n Switched to store: ${alias}\n`)));
|
|
27
32
|
console.log(pc.dim(' Root JSON files now reflect this store\'s data.'));
|
|
28
33
|
console.log(pc.dim(' Use "climaybe theme sync" (or "climaybe sync") to write changes back.\n'));
|
package/src/index.js
CHANGED
|
@@ -77,7 +77,7 @@ function registerThemeCommands(cmd) {
|
|
|
77
77
|
cmd.command('build').description('Build assets (Tailwind + scripts build)').action(() => buildAll());
|
|
78
78
|
cmd
|
|
79
79
|
.command('build-scripts')
|
|
80
|
-
.description('Build _scripts → assets
|
|
80
|
+
.description('Build _scripts → assets/*.js (+ *.min.js)')
|
|
81
81
|
.option('--minify', 'Minify output bundles')
|
|
82
82
|
.action(buildScriptsCommand);
|
|
83
83
|
cmd
|
package/src/lib/build-scripts.js
CHANGED
|
@@ -40,6 +40,8 @@ function stripModuleSyntax(content) {
|
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
cleaned = cleaned.replace(/^\s*export\s+default\s+/gm, '');
|
|
43
|
+
// Remove named exports (single-line and multiline forms).
|
|
44
|
+
cleaned = cleaned.replace(/(^|\n)\s*export\s*\{[\s\S]*?\}\s*;?/g, '$1');
|
|
43
45
|
cleaned = cleaned.replace(/^\s*export\s+\{[^}]*\}\s*;?\s*$/gm, '');
|
|
44
46
|
cleaned = cleaned.replace(/^\s*export\s+(?=(const|let|var|function|class)\b)/gm, '');
|
|
45
47
|
return cleaned;
|
|
@@ -172,6 +174,12 @@ function outputNameForEntrypoint(entryFile) {
|
|
|
172
174
|
return basename(entryFile);
|
|
173
175
|
}
|
|
174
176
|
|
|
177
|
+
function outputMinNameForEntrypoint(entryFile) {
|
|
178
|
+
const name = outputNameForEntrypoint(entryFile);
|
|
179
|
+
if (!name.endsWith('.js')) return `${name}.min.js`;
|
|
180
|
+
return name.replace(/\.js$/, '.min.js');
|
|
181
|
+
}
|
|
182
|
+
|
|
175
183
|
function buildSingleEntrypoint({ cwd, entryFile, minify = false }) {
|
|
176
184
|
const scriptsDir = join(cwd, '_scripts');
|
|
177
185
|
const entryPath = join(scriptsDir, entryFile);
|
|
@@ -179,26 +187,43 @@ function buildSingleEntrypoint({ cwd, entryFile, minify = false }) {
|
|
|
179
187
|
throw new Error(`Missing required file: _scripts/${entryFile}`);
|
|
180
188
|
}
|
|
181
189
|
|
|
182
|
-
const
|
|
190
|
+
const processedFilesReadable = new Set();
|
|
191
|
+
const processedFilesMinified = new Set();
|
|
183
192
|
const isolateFiles = collectFilesToIsolate({ scriptsDir, entryFile });
|
|
184
|
-
|
|
193
|
+
const readableContent = processScriptFile({
|
|
185
194
|
scriptsDir,
|
|
186
195
|
filePath: entryFile,
|
|
187
|
-
processedFiles,
|
|
188
|
-
minify,
|
|
196
|
+
processedFiles: processedFilesReadable,
|
|
197
|
+
minify: false,
|
|
198
|
+
isolateFiles
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
const minifiedContent = processScriptFile({
|
|
202
|
+
scriptsDir,
|
|
203
|
+
filePath: entryFile,
|
|
204
|
+
processedFiles: processedFilesMinified,
|
|
205
|
+
minify: true,
|
|
189
206
|
isolateFiles
|
|
190
207
|
});
|
|
191
|
-
finalContent = stripModuleSyntax(finalContent);
|
|
192
|
-
if (minify) finalContent = minifyScriptContent(finalContent);
|
|
193
208
|
|
|
194
209
|
const assetsDir = join(cwd, 'assets');
|
|
195
210
|
mkdirSync(assetsDir, { recursive: true });
|
|
196
211
|
|
|
197
212
|
const outFile = outputNameForEntrypoint(entryFile);
|
|
198
213
|
const outputPath = join(assetsDir, outFile);
|
|
199
|
-
|
|
214
|
+
const outReadable = stripModuleSyntax(readableContent).trim() + '\n';
|
|
215
|
+
const outMinified = minifyScriptContent(stripModuleSyntax(minifiedContent)).trim() + '\n';
|
|
216
|
+
|
|
217
|
+
// Back-compat: when minify=true, the primary output file is minified.
|
|
218
|
+
writeFileSync(outputPath, (minify ? outMinified : outReadable), 'utf-8');
|
|
219
|
+
|
|
220
|
+
// Always emit an explicit *.min.js asset so Shopify won't attempt CDN minification.
|
|
221
|
+
const outMinFile = outputMinNameForEntrypoint(entryFile);
|
|
222
|
+
const outputMinPath = join(assetsDir, outMinFile);
|
|
223
|
+
writeFileSync(outputMinPath, outMinified, 'utf-8');
|
|
200
224
|
|
|
201
|
-
|
|
225
|
+
const fileCount = Math.max(processedFilesReadable.size, processedFilesMinified.size);
|
|
226
|
+
return { entryFile, fileCount, outputPath, outputMinPath };
|
|
202
227
|
}
|
|
203
228
|
|
|
204
229
|
export function buildScripts({ cwd = process.cwd(), entry = null, minify = false } = {}) {
|
package/src/lib/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import { getLatestTagVersion } from './git.js';
|
|
3
|
+
import { getLatestTagVersion, isGitRepo, currentBranch } from './git.js';
|
|
4
4
|
|
|
5
5
|
const PKG = 'package.json';
|
|
6
6
|
const CLIMAYBE_CONFIG = 'climaybe.config.json';
|
|
@@ -188,6 +188,37 @@ export function getMode(cwd = process.cwd()) {
|
|
|
188
188
|
return aliases.length > 1 ? 'multi' : 'single';
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
/**
|
|
192
|
+
* When on git branches `staging-<alias>` or `live-<alias>`, resolve the Shopify domain
|
|
193
|
+
* for that store from config. Returns null if not a git repo, branch doesn't match,
|
|
194
|
+
* or the alias is unknown.
|
|
195
|
+
* @param {string} [cwd]
|
|
196
|
+
* @returns {string | null}
|
|
197
|
+
*/
|
|
198
|
+
export function getStoreDomainFromBranch(cwd = process.cwd()) {
|
|
199
|
+
if (!isGitRepo(cwd)) return null;
|
|
200
|
+
let branch;
|
|
201
|
+
try {
|
|
202
|
+
branch = currentBranch(cwd);
|
|
203
|
+
} catch {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
const config = readConfig(cwd);
|
|
207
|
+
const stores = config?.stores;
|
|
208
|
+
if (!stores || typeof stores !== 'object') return null;
|
|
209
|
+
|
|
210
|
+
let alias = '';
|
|
211
|
+
if (branch.startsWith('staging-')) {
|
|
212
|
+
alias = branch.slice('staging-'.length);
|
|
213
|
+
} else if (branch.startsWith('live-')) {
|
|
214
|
+
alias = branch.slice('live-'.length);
|
|
215
|
+
}
|
|
216
|
+
if (!alias) return null;
|
|
217
|
+
|
|
218
|
+
const domain = stores[alias];
|
|
219
|
+
return typeof domain === 'string' && domain.trim() ? domain.trim() : null;
|
|
220
|
+
}
|
|
221
|
+
|
|
191
222
|
/**
|
|
192
223
|
* Whether optional preview/cleanup workflows are enabled.
|
|
193
224
|
*/
|
package/src/lib/dev-runtime.js
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync } from 'node:fs';
|
|
|
3
3
|
import { watchTree } from './watch.js';
|
|
4
4
|
import { isAbsolute, join, relative } from 'node:path';
|
|
5
5
|
import pc from 'picocolors';
|
|
6
|
-
import { readConfig } from './config.js';
|
|
6
|
+
import { readConfig, getStoreDomainFromBranch } from './config.js';
|
|
7
7
|
import { buildScripts } from './build-scripts.js';
|
|
8
8
|
import { buildSchemas } from './schema-builder.js';
|
|
9
9
|
import { runShopify } from './shopify-cli.js';
|
|
@@ -211,7 +211,8 @@ function runThemeCheckFiltered({ cwd = process.cwd() } = {}) {
|
|
|
211
211
|
|
|
212
212
|
export function serveShopify({ cwd = process.cwd() } = {}) {
|
|
213
213
|
const config = readConfig(cwd) || {};
|
|
214
|
-
const
|
|
214
|
+
const branchStore = getStoreDomainFromBranch(cwd);
|
|
215
|
+
const store = branchStore || config.default_store || config.store || '';
|
|
215
216
|
const args = ['theme', 'dev', '--theme-editor-sync'];
|
|
216
217
|
if (store) args.push(`--store=${store}`);
|
|
217
218
|
// Keep Shopify on inherited stdio so reconciliation prompts remain interactive.
|