@blocofy/cli 0.1.5 → 0.1.6
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/bin/blocofy.mjs +1 -1
- package/lib/dev-server.mjs +72 -16
- package/lib/local-theme.mjs +1 -1
- package/package.json +1 -1
package/bin/blocofy.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { fetchDevSession, pullTheme, pushTheme } from "../lib/theme-sync.mjs";
|
|
|
19
19
|
import { hyperlink, openUrl } from "../lib/term.mjs";
|
|
20
20
|
import { isValidToken, isValidUrl, normalizeUrl } from "../lib/validate.mjs";
|
|
21
21
|
|
|
22
|
-
const VERSION = "0.1.
|
|
22
|
+
const VERSION = "0.1.6";
|
|
23
23
|
const args = process.argv.slice(2);
|
|
24
24
|
|
|
25
25
|
/** Parse `--key value` and `--flag` (boolean) arguments. */
|
package/lib/dev-server.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
|
-
import { existsSync, readFileSync,
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
3
|
import { join, normalize, sep } from "node:path";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
LIVERELOAD_PATH,
|
|
7
|
+
THEME_DIRS,
|
|
7
8
|
contentTypeFor,
|
|
8
9
|
injectLivereload,
|
|
9
10
|
readLocalTemplates,
|
|
@@ -127,27 +128,82 @@ export function startDevServer({ dir, url, token, port, syncDraft = false, onErr
|
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
131
|
+
* Recursively snapshot theme-file mtimes → Map(relPath → mtimeMs). Only descends
|
|
132
|
+
* into THEME_DIRS at the top level, so node_modules / .git / build tooling don't
|
|
133
|
+
* bloat the scan. Used by the polling watcher.
|
|
133
134
|
*/
|
|
134
|
-
function
|
|
135
|
+
function snapshot(dir) {
|
|
136
|
+
const map = new Map();
|
|
137
|
+
const walk = (current, rel) => {
|
|
138
|
+
let entries;
|
|
139
|
+
try {
|
|
140
|
+
entries = readdirSync(current, { withFileTypes: true });
|
|
141
|
+
} catch {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
for (const entry of entries) {
|
|
145
|
+
if (!rel && !THEME_DIRS.has(entry.name)) continue; // top level: theme dirs only
|
|
146
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
147
|
+
const full = join(current, entry.name);
|
|
148
|
+
if (entry.isDirectory()) {
|
|
149
|
+
walk(full, childRel);
|
|
150
|
+
} else {
|
|
151
|
+
try {
|
|
152
|
+
map.set(childRel, statSync(full).mtimeMs);
|
|
153
|
+
} catch {
|
|
154
|
+
/* dosya kayboldu (atomik kaydetme yarış) — sonraki tarama yakalar */
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
walk(dir, "");
|
|
160
|
+
return map;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Watch `dir` by polling theme-file mtimes (default 300ms). fs.watch yerine polling:
|
|
165
|
+
* editörün kaydetme şekli (yerinde/atomik), dosya sistemi ve `recursive` desteği
|
|
166
|
+
* olmayan Node build'lerinden bağımsız çalışır — kaybolan event yok. Değişen/eklenen/
|
|
167
|
+
* silinen ilk dosyanın yolunu `onChange`'e geçirir (debounce'lu). `.close()` döner.
|
|
168
|
+
*/
|
|
169
|
+
function startWatch(dir, onChange, intervalMs = 300) {
|
|
170
|
+
let prev = snapshot(dir);
|
|
135
171
|
let timer = null;
|
|
136
172
|
let lastFile = null;
|
|
137
|
-
const fire = (
|
|
138
|
-
if (
|
|
173
|
+
const fire = (file) => {
|
|
174
|
+
if (file) lastFile = file;
|
|
139
175
|
if (timer) clearTimeout(timer);
|
|
140
|
-
timer = setTimeout(() => onChange(lastFile),
|
|
176
|
+
timer = setTimeout(() => onChange(lastFile), 80);
|
|
141
177
|
};
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
178
|
+
const tick = () => {
|
|
179
|
+
const cur = snapshot(dir);
|
|
180
|
+
let changed = null;
|
|
181
|
+
for (const [key, mtime] of cur) {
|
|
182
|
+
const before = prev.get(key);
|
|
183
|
+
if (before === undefined || before !== mtime) {
|
|
184
|
+
changed = key;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
149
187
|
}
|
|
150
|
-
|
|
188
|
+
if (!changed) {
|
|
189
|
+
for (const key of prev.keys()) {
|
|
190
|
+
if (!cur.has(key)) {
|
|
191
|
+
changed = key;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
prev = cur;
|
|
197
|
+
if (changed) fire(changed);
|
|
198
|
+
};
|
|
199
|
+
const interval = setInterval(tick, intervalMs);
|
|
200
|
+
if (interval.unref) interval.unref();
|
|
201
|
+
return {
|
|
202
|
+
close() {
|
|
203
|
+
clearInterval(interval);
|
|
204
|
+
if (timer) clearTimeout(timer);
|
|
205
|
+
},
|
|
206
|
+
};
|
|
151
207
|
}
|
|
152
208
|
|
|
153
209
|
/** Map a `/asset/*` path to a disk file (path-traversal safe); null if missing. */
|
package/lib/local-theme.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { extname, join, relative, sep } from "node:path";
|
|
|
7
7
|
* THEME_DIRS, keyed by relative path with the `.liquid` extension stripped.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const THEME_DIRS = new Set(["layout", "section", "block", "partial", "asset", "template"]);
|
|
10
|
+
export const THEME_DIRS = new Set(["layout", "section", "block", "partial", "asset", "template"]);
|
|
11
11
|
const LIQUID_KINDS = new Set(["layout", "section", "block", "partial", "template"]);
|
|
12
12
|
|
|
13
13
|
/**
|