@blocofy/cli 0.1.5 → 0.1.7

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 CHANGED
@@ -15,11 +15,12 @@ import { createInterface } from "node:readline/promises";
15
15
  import { credentialsPath, loadCredentials, saveCredentials } from "../lib/credentials.mjs";
16
16
  import { startDevServer } from "../lib/dev-server.mjs";
17
17
  import { readLocalTemplates } from "../lib/local-theme.mjs";
18
+ import { githubNote } from "../lib/messages.mjs";
18
19
  import { fetchDevSession, pullTheme, pushTheme } from "../lib/theme-sync.mjs";
19
20
  import { hyperlink, openUrl } from "../lib/term.mjs";
20
21
  import { isValidToken, isValidUrl, normalizeUrl } from "../lib/validate.mjs";
21
22
 
22
- const VERSION = "0.1.5";
23
+ const VERSION = "0.1.7";
23
24
  const args = process.argv.slice(2);
24
25
 
25
26
  /** Parse `--key value` and `--flag` (boolean) arguments. */
@@ -217,6 +218,13 @@ async function themeDev(rest) {
217
218
  console.log(`\n Press: ${keys}`);
218
219
  console.log(` Edit a theme file and save — every open view reloads automatically.\n`);
219
220
 
221
+ // Düzlem uyarısı: CLI yalnız tema KODUNU taşır; editörde yapılan içerik/ayar
222
+ // bulutta yaşar (githubNote → lib/messages.mjs, oturum durumuna göre uyarlanır).
223
+ const note = githubNote(session);
224
+ if (note) {
225
+ console.log(` ℹ ${note}\n`);
226
+ }
227
+
220
228
  // Tanılama: kaç tema dosyası izleniyor? Boşsa hot-reload mümkün değil — yanlış
221
229
  // dizinde ya da `theme pull` yapılmamış demektir; sebebini açıkça söyle.
222
230
  const localFiles = readLocalTemplates(themeDir);
@@ -1,9 +1,10 @@
1
1
  import { createServer } from "node:http";
2
- import { existsSync, readFileSync, statSync, watch } from "node:fs";
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
- * Watch `dir`; if recursive watching is unsupported (older Node/Linux), fall back to
131
- * a non-recursive watch. Calls `onChange` debounced. Returns null if unwatchable
132
- * (livereload disabled).
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 startWatch(dir, onChange) {
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 = (_event, filename) => {
138
- if (filename) lastFile = String(filename).split(sep).join("/");
173
+ const fire = (file) => {
174
+ if (file) lastFile = file;
139
175
  if (timer) clearTimeout(timer);
140
- timer = setTimeout(() => onChange(lastFile), 120);
176
+ timer = setTimeout(() => onChange(lastFile), 80);
141
177
  };
142
- try {
143
- return watch(dir, { recursive: true }, fire);
144
- } catch {
145
- try {
146
- return watch(dir, fire);
147
- } catch {
148
- return null;
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. */
@@ -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
  /**
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `theme dev` kullanıcı-yönelik mesajları (saf → test edilebilir). Düzlem uyarısı:
3
+ * CLI yalnız tema KODUNU taşır; editörde yapılan içerik/ayar bulutta yaşar.
4
+ */
5
+
6
+ /**
7
+ * Dev oturumuna göre "düzlem" uyarısı döndürür (string), oturum yoksa null.
8
+ * - GitHub bağlı → repo@branch + `git pull` ipucu.
9
+ * - Bağlı değil → içerik/ayar bulutta kalır + repo bağla ipucu.
10
+ * - Eski platform (githubConnected undefined) → ipuçsuz nötr uyarı.
11
+ */
12
+ export function githubNote(session) {
13
+ if (!session) return null;
14
+ if (session.githubConnected === true) {
15
+ return `GitHub: ${session.githubRepo}@${session.githubBranch} — editor edits auto-commit there; run 'git pull' to sync them here.`;
16
+ }
17
+ return (
18
+ "Content & settings edited in the admin editor stay server-side — they won't appear in these local files." +
19
+ (session.githubConnected === false ? " Connect a GitHub repo for two-way sync." : "")
20
+ );
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocofy/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Develop your Blocofy theme locally against live data with instant preview — login, theme dev, pull, push.",
5
5
  "type": "module",
6
6
  "license": "MIT",