@blocofy/cli 0.1.2 → 0.1.3

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
@@ -15,8 +15,9 @@ npx @blocofy/cli theme dev # http://localhost:3030 — local theme + live
15
15
  ```bash
16
16
  blocofy login [--url <url>] [--token <bcf_…>]
17
17
  # Save your platform URL + dev token (~/.blocofy/credentials.json, 0600).
18
- blocofy theme dev [dir] # Local dev server: edit a file and the browser reloads automatically.
19
- # --port <n> (default 3030)
18
+ blocofy theme dev [dir] # Local dev server. Prints 3 views — local preview, a live-domain
19
+ # preview link, and the theme editor — all auto-reloading on save.
20
+ # --port <n> (default 3030), --no-sync (local preview only)
20
21
  blocofy theme pull [dir] # Download the live theme to disk.
21
22
  blocofy theme push [dir] # Write the local theme to the live site (create/update; no delete).
22
23
  blocofy --version
@@ -28,8 +29,13 @@ blocofy --help
28
29
  `theme dev` starts a local HTTP server. For each page request it reads your local theme
29
30
  files and sends them to the platform's dev-render endpoint (`/api/dev/render`). The platform
30
31
  renders them with the site's **live data** and returns HTML — so the CLI ships no rendering
31
- engine and you see exactly the production output. A file watcher reloads the browser over
32
- Server-Sent Events when you save.
32
+ engine and you see exactly the production output.
33
+
34
+ It also continuously syncs your local files to a **draft theme** so you can view the same work
35
+ three ways — the local preview, a shareable live-domain preview link, and the admin theme
36
+ editor — without affecting your published theme. Save a file and **every open view reloads**
37
+ (the platform-rendered pages connect back to the local dev server's reload channel). Publish
38
+ the draft from the theme editor when you're ready.
33
39
 
34
40
  Credentials come from `~/.blocofy/credentials.json` (written by `blocofy login`) or the
35
41
  `BLOCOFY_URL` + `BLOCOFY_TOKEN` environment variables (for CI/automation).
package/bin/blocofy.mjs CHANGED
@@ -14,9 +14,9 @@ import { createInterface } from "node:readline/promises";
14
14
 
15
15
  import { credentialsPath, loadCredentials, saveCredentials } from "../lib/credentials.mjs";
16
16
  import { startDevServer } from "../lib/dev-server.mjs";
17
- import { pullTheme, pushTheme } from "../lib/theme-sync.mjs";
17
+ import { fetchDevSession, pullTheme, pushTheme } from "../lib/theme-sync.mjs";
18
18
 
19
- const VERSION = "0.1.2";
19
+ const VERSION = "0.1.3";
20
20
  const args = process.argv.slice(2);
21
21
 
22
22
  /** Parse `--key value` and `--flag` (boolean) arguments. */
@@ -127,7 +127,7 @@ async function themePush(rest) {
127
127
  }
128
128
  }
129
129
 
130
- function themeDev(rest) {
130
+ async function themeDev(rest) {
131
131
  const flags = parseFlags(rest);
132
132
  const positional = rest.filter((a) => !a.startsWith("--"));
133
133
  const themeDir = resolve(positional[0] ?? process.cwd());
@@ -140,12 +140,27 @@ function themeDev(rest) {
140
140
  const creds = requireCreds();
141
141
  const port = Number(flags.port) || 3030;
142
142
 
143
- console.log(`blocofy theme dev`);
144
- console.log(` theme dir : ${themeDir}`);
145
- console.log(` platform : ${creds.url}`);
146
- console.log(` token : ${creds.token.slice(0, 8)}… (${creds.source})`);
147
- console.log(` preview : http://localhost:${port}`);
148
- console.log(` → edit a theme file and save = the browser reloads automatically (livereload)`);
143
+ // Dev session: live-domain preview + theme editor URLs (+ a draft to sync into).
144
+ // Graceful: if the platform can't provide one, fall back to local-only preview.
145
+ let session = null;
146
+ if (!flags["no-sync"]) {
147
+ try {
148
+ session = await fetchDevSession({ url: creds.url, token: creds.token });
149
+ } catch (error) {
150
+ console.warn(
151
+ `Warning: dev session unavailable (${error?.message ?? error}). ` +
152
+ `Local preview only — live-domain/editor views + draft sync disabled.`,
153
+ );
154
+ }
155
+ }
156
+
157
+ console.log(`\nblocofy theme dev — ${creds.url} (token ${creds.token.slice(0, 8)}…)\n`);
158
+ console.log(` Local: http://localhost:${port}`);
159
+ if (session) {
160
+ console.log(` Preview: ${session.previewUrl}&hr=${port}`);
161
+ console.log(` Editor: ${session.editorUrl}&hr=${port}`);
162
+ }
163
+ console.log(`\n Edit a theme file and save — every open view reloads automatically.\n`);
149
164
 
150
165
  if (flags.dry) {
151
166
  console.log("(--dry: server not started)");
@@ -157,6 +172,7 @@ function themeDev(rest) {
157
172
  url: creds.url,
158
173
  token: creds.token,
159
174
  port,
175
+ syncDraft: Boolean(session),
160
176
  onError: (err) => {
161
177
  if (err && err.code === "EADDRINUSE") {
162
178
  console.error(`Port ${port} is in use. Try a different port: blocofy theme dev --port <n>`);
@@ -186,7 +202,10 @@ if (first === "--version" || first === "-v") {
186
202
  process.exit(1);
187
203
  });
188
204
  } else if (first === "theme" && rest[0] === "dev") {
189
- themeDev(rest.slice(1));
205
+ themeDev(rest.slice(1)).catch((error) => {
206
+ console.error(error?.message ?? error);
207
+ process.exit(1);
208
+ });
190
209
  } else if (first === "theme" && rest[0] === "pull") {
191
210
  themePull(rest.slice(1)).catch((error) => {
192
211
  console.error(error?.message ?? error);
@@ -8,6 +8,7 @@ import {
8
8
  injectLivereload,
9
9
  readLocalTemplates,
10
10
  } from "./local-theme.mjs";
11
+ import { pushTheme } from "./theme-sync.mjs";
11
12
 
12
13
  /**
13
14
  * Standalone dev server. For each page request it reads the local theme files and
@@ -18,7 +19,7 @@ import {
18
19
  * separate request); direct `/asset/*` references are served from disk. Images/JS
19
20
  * are remote (Directus/CDN), so no local serving is needed for them.
20
21
  */
21
- export function startDevServer({ dir, url, token, port, onError }) {
22
+ export function startDevServer({ dir, url, token, port, syncDraft = false, onError }) {
22
23
  const base = url.replace(/\/+$/, "");
23
24
  const clients = new Set();
24
25
 
@@ -56,6 +57,8 @@ export function startDevServer({ dir, url, token, port, onError }) {
56
57
  "content-type": "text/event-stream",
57
58
  "cache-control": "no-cache, no-transform",
58
59
  connection: "keep-alive",
60
+ // Cross-origin iframe'ler (canlı-domain önizleme + editör) subscribe edebilsin.
61
+ "access-control-allow-origin": "*",
59
62
  });
60
63
  res.write("retry: 1000\n\n");
61
64
  clients.add(res);
@@ -83,10 +86,27 @@ export function startDevServer({ dir, url, token, port, onError }) {
83
86
 
84
87
  if (onError) server.on("error", onError);
85
88
 
86
- const watcher = startWatch(dir, () => {
89
+ const broadcast = () => {
87
90
  for (const client of clients) client.write("data: reload\n\n");
91
+ };
92
+ // Değişimde: önce taslağa senkronla (canlı-domain önizleme + editör güncel olsun),
93
+ // SONRA reload yayınla → tüm görünümler en güncel taslağı çeker.
94
+ const watcher = startWatch(dir, async () => {
95
+ if (syncDraft) {
96
+ try {
97
+ await pushTheme({ dir, url, token, draft: true });
98
+ } catch {
99
+ /* senkron hatası reload'u engellemesin */
100
+ }
101
+ }
102
+ broadcast();
88
103
  });
89
104
 
105
+ // Açılışta taslağı bir kez doldur → uzak görünümler hemen güncel local'i gösterir.
106
+ if (syncDraft) {
107
+ void pushTheme({ dir, url, token, draft: true }).catch(() => {});
108
+ }
109
+
90
110
  server.listen(port);
91
111
 
92
112
  return {
@@ -34,6 +34,19 @@ export async function pullTheme({ dir, url, token }) {
34
34
  return { count };
35
35
  }
36
36
 
37
+ /**
38
+ * Dev session bilgisi (#119 `theme dev`): platform draft instance'ı hazırlar ve
39
+ * 3 görünümün URL'lerini döner — `{ draftInstanceId, previewUrl, editorUrl, site }`.
40
+ */
41
+ export async function fetchDevSession({ url, token }) {
42
+ const base = url.replace(/\/+$/, "");
43
+ const res = await fetch(`${base}/api/dev/session`, {
44
+ headers: { authorization: `Bearer ${token}` },
45
+ });
46
+ if (!res.ok) throw new Error(await errorText(res));
47
+ return res.json();
48
+ }
49
+
37
50
  /**
38
51
  * Write the local theme to the site (create/update; no delete). With `draft`,
39
52
  * writes to a draft theme instance instead of the live theme — preview & publish
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocofy/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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",