@blocofy/cli 0.13.0 → 0.15.0
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 +173 -9
- package/bin/blocofy.mjs +545 -39
- package/lib/args.mjs +2 -2
- package/lib/dev-server.mjs +25 -7
- package/lib/theme-sync.mjs +336 -9
- package/lib/theme-work.mjs +369 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Show which site a command in `[dir]` would hit (verified), without writing anyth
|
|
|
61
61
|
### Theme
|
|
62
62
|
|
|
63
63
|
```
|
|
64
|
-
blocofy theme dev [dir] [--port <n>] [--no-sync] [--name <name>]
|
|
64
|
+
blocofy theme dev [dir] [--port <n>] [--no-sync] [--name <name>] [--instance <handle>]
|
|
65
65
|
```
|
|
66
66
|
Start a local dev server that renders your local theme files with the site's live content.
|
|
67
67
|
Press `l` to open it, `q` to quit. Edit a file and save → the view reloads. Saves sync to a
|
|
@@ -73,13 +73,17 @@ changing credentials, context or the project binding).
|
|
|
73
73
|
- `--port <n>` — local port (default 3030).
|
|
74
74
|
- `--no-sync` — local preview only (skip draft sync).
|
|
75
75
|
- `--name <name>` — name the draft when it is first created (ignored if it already exists).
|
|
76
|
+
- `--instance <handle>` — sync into this draft. Needed when the platform cannot tell which draft is the
|
|
77
|
+
CLI draft (see "Which draft a draft command writes to" below); the live theme's handle is refused.
|
|
76
78
|
|
|
77
79
|
```
|
|
78
80
|
blocofy theme pull [dir] [--draft] [--instance <handle>]
|
|
79
81
|
```
|
|
80
82
|
Download the live theme to disk. `dir` defaults to cwd.
|
|
81
|
-
- `--draft` — pull the draft
|
|
82
|
-
draft
|
|
83
|
+
- `--draft` — pull the CLI draft (what `theme dev` and `theme push --draft` write into) instead of
|
|
84
|
+
live. Read-only: it never creates the draft. With no CLI draft yet the platform answers
|
|
85
|
+
`target_missing` and the CLI stops (exit 2, nothing written) and tells you to run
|
|
86
|
+
`blocofy theme push --draft` first. It still needs a bound project.
|
|
83
87
|
- `--instance <handle>` — pull a specific theme by its handle (admin panel theme card, or
|
|
84
88
|
`blocofy status`).
|
|
85
89
|
|
|
@@ -94,11 +98,19 @@ the admin panel, never touching the live site. Publish it with `blocofy theme pu
|
|
|
94
98
|
non-interactive shells must add `--yes`.
|
|
95
99
|
- `--draft` — explicit draft (same as the default; safe).
|
|
96
100
|
- `--yes` — confirm a `--live` push without prompting (CI/agents).
|
|
97
|
-
- `--instance <handle>` — push to a specific theme by its handle
|
|
98
|
-
live-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
- `--instance <handle>` — push to a specific theme by its handle. The live theme's handle asks for
|
|
102
|
+
the same confirmation as `--live` (non-interactive shells add `--yes`); so does any handle the CLI
|
|
103
|
+
cannot tell apart from the live theme (the live theme is unknown, or a raw numeric id was given).
|
|
104
|
+
With `--draft --instance <handle>` the push is a draft write to that draft: it never writes the
|
|
105
|
+
live theme (refused locally and by the platform, `draft_target_is_live`).
|
|
106
|
+
On a site with **no live theme** (or when the live theme cannot be read) the CLI cannot tell any
|
|
107
|
+
handle apart from the live one, so it stays on the safe side by design: every `--instance` push
|
|
108
|
+
asks for confirmation (`--yes` in non-interactive shells), and `--draft --instance` and
|
|
109
|
+
`theme dev --instance` refuse.
|
|
110
|
+
- `--name <name>` — name the new draft: it is created as `CLI Draft — <name>` (draft mode only;
|
|
111
|
+
ignored on `--live`/`--instance`). When the push reuses the existing CLI draft instead, it says
|
|
112
|
+
`--name` was not applied. Do not rename the CLI draft by hand to a name that does not start with
|
|
113
|
+
`CLI Draft — `: the next draft push would refuse it and ask for `--instance`.
|
|
102
114
|
- `--dry-run` / `--validate` — check the push on the server without writing; the two flags are
|
|
103
115
|
aliases. The dry run covers exactly the files the push would send (remote-only files it keeps
|
|
104
116
|
included; with `--prune`, without the ones it would remove). A current platform plans the whole
|
|
@@ -108,6 +120,32 @@ the admin panel, never touching the live site. Publish it with `blocofy theme pu
|
|
|
108
120
|
compares with the CLI draft it writes to (named by handle); with no CLI draft yet, with the live
|
|
109
121
|
theme (the push would create the draft). `--live` compares with live, `--instance` with that theme.
|
|
110
122
|
|
|
123
|
+
**Which draft a draft command writes to.** A draft push, `theme pull --draft` and the `theme dev`
|
|
124
|
+
sync write to (or read) the CLI draft only when the platform can tell which draft that is: exactly
|
|
125
|
+
one draft created by a CLI push, still carrying a name the platform gives it (`CLI Draft`,
|
|
126
|
+
`CLI Draft — YYYY-MM-DD` or `CLI Draft — <name>`), and not a draft a site-state restore built.
|
|
127
|
+
Otherwise — two such drafts, a site-state restore draft, or a CLI draft renamed by hand — the command
|
|
128
|
+
writes nothing, lists the candidate drafts and exits 2 (`draft_target_ambiguous`). The message
|
|
129
|
+
pre-fills `--instance <handle>` only for a CLI-named draft that is not a restore draft; naming any
|
|
130
|
+
other listed draft would overwrite it. On a site whose only candidate is a site-state restore draft,
|
|
131
|
+
create a new draft theme in the admin panel and pass its handle with `--instance`, or publish or
|
|
132
|
+
delete the restore draft first. `theme publish` without `--instance` uses the same rule and never
|
|
133
|
+
publishes a guessed draft. With no draft at all, the first push creates one as before.
|
|
134
|
+
|
|
135
|
+
**When the platform cannot create the new draft.** A draft push (or the `theme dev` sync) that needs
|
|
136
|
+
a new CLI draft can be refused by the platform's capacity check. Nothing is written in any of these
|
|
137
|
+
cases; the CLI explains it in plain words first, then prints the `error [code]` line (the `--json`
|
|
138
|
+
envelope keeps the code and details):
|
|
139
|
+
- `quota_exceeded` (exit 2) — worded by `details.resource`, with the usage the platform reports: the
|
|
140
|
+
site's theme space is full (`theme_bytes`) or a site not on theme space reached its old draft count
|
|
141
|
+
(`theme_drafts`) — remove a draft you no longer need (neither is a plan limit); the plan's storage
|
|
142
|
+
is full (`storage_mb`) — the plan message.
|
|
143
|
+
- `capacity_unavailable` / `resource_busy` (exit 1) — temporary. The CLI has already retried within
|
|
144
|
+
its normal retry policy (waiting as long as the server's `Retry-After` asks); try again later.
|
|
145
|
+
- `source_stale` (exit 2) — the live theme the new draft copies changed meanwhile; run the command
|
|
146
|
+
again.
|
|
147
|
+
`theme dev` reports each of them in one line and tries again on the next save.
|
|
148
|
+
|
|
111
149
|
After a draft push the CLI prints the draft it wrote to (`Draft: <handle> "<name>" (new)` or
|
|
112
150
|
`(existing CLI draft, updated)`) and the `blocofy theme publish --instance <handle>` command.
|
|
113
151
|
- `--idempotency-key <k>` — attach a key so a retried push is not double-applied.
|
|
@@ -158,7 +196,68 @@ flag, publishes the draft that `theme dev` / `theme push --draft` writes into. T
|
|
|
158
196
|
refuses to publish a theme that has no pages (it would 404); preview first. The site is the one
|
|
159
197
|
`[dir]`'s project is bound to (`dir` defaults to cwd), so `blocofy theme push ./shop && blocofy
|
|
160
198
|
theme publish ./shop` always publishes `./shop`'s site, whatever directory you run it from.
|
|
161
|
-
- `--instance <handle>` — publish a specific theme.
|
|
199
|
+
- `--instance <handle>` — publish a specific theme. Without it the platform publishes only the
|
|
200
|
+
site's CLI draft; any other theme (a site-state restore draft, a renamed or panel-copied theme) is
|
|
201
|
+
refused with `publish_target_unconfirmed` (exit 2, nothing published) — name it with `--instance`.
|
|
202
|
+
|
|
203
|
+
### Theme work (new)
|
|
204
|
+
|
|
205
|
+
A **work** is a private, safe copy of the site's current live theme: you change it, visitors never
|
|
206
|
+
see it, and a person approves its publication in the admin panel (the CLI never publishes a work).
|
|
207
|
+
Work commands use the **v1 API key** (`blocofy login --api-key`, or `BLOCOFY_API_KEY` +
|
|
208
|
+
`BLOCOFY_API_URL`): the work belongs to the key that started it. The dev token alone is refused
|
|
209
|
+
(`LOGIN_REQUIRED`) before any request.
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
blocofy theme work start [dir] [--intent "<text>"] [--idempotency-key <k>]
|
|
213
|
+
blocofy theme work status <wk_…> [--dir <dir>]
|
|
214
|
+
blocofy theme work resume <wk_…> [--dir <dir>] [--require-fresh]
|
|
215
|
+
blocofy theme work cancel <wk_…> [--dir <dir>]
|
|
216
|
+
blocofy theme work seal <wk_…> [--dir <dir>]
|
|
217
|
+
blocofy theme work request-approval <wk_…> [--dir <dir>] [--open] [--wait [--interval <s>]]
|
|
218
|
+
blocofy theme push [dir] --draft --work <wk_…>
|
|
219
|
+
```
|
|
220
|
+
- `seal` prepares the work for review: its content is frozen and can no longer change. It asks for
|
|
221
|
+
no approval and publishes nothing. On a platform without this step it says so (`seal_unsupported`,
|
|
222
|
+
exit 2); `request-approval` prepares the work itself.
|
|
223
|
+
- `request-approval` asks a person to publish the work (an open work is prepared for review first)
|
|
224
|
+
and prints the **approval URL**. A signed-in site owner, or a team member with the theme permission,
|
|
225
|
+
approves on that Blocofy page. The URL carries no token: having it is not a permission to publish.
|
|
226
|
+
`--open` also opens it in your browser (only when it is this platform's approval page). `--wait`
|
|
227
|
+
polls the read-only publish status until the work is published or the request ends; the CLI never
|
|
228
|
+
publishes a work. How `--wait` ends:
|
|
229
|
+
|
|
230
|
+
| Exit | Code (`--json` envelope) | Meaning |
|
|
231
|
+
| --- | --- | --- |
|
|
232
|
+
| 0 | — | Approved and published; the work is live. |
|
|
233
|
+
| 2 | `approval_stale` | The live site changed after the request; nothing published. Start a new work from the current live site and ask again. |
|
|
234
|
+
| 2 | `approval_expired` | Nobody decided within 15 minutes; nothing published. Ask again. |
|
|
235
|
+
| 2 | `approval_declined` | The request was declined; nothing published. |
|
|
236
|
+
| 2 | `approval_superseded` | The work was reopened for changes; this request is no longer valid. Ask again. |
|
|
237
|
+
| 2 | `work_cancelled` | The work was cancelled; nothing published. |
|
|
238
|
+
| 1 | `publish_failed` | The work could not be completed; nothing published. Check `theme work status`. |
|
|
239
|
+
| 1 | `wait_timeout` | No decision yet; the CLI stopped waiting. The request stays valid until it expires. |
|
|
240
|
+
|
|
241
|
+
A refusal before the wait starts (for example `work_state_conflict`) exits as usual (2 for a 4xx,
|
|
242
|
+
1 for a 5xx); see [Exit codes](#exit-codes).
|
|
243
|
+
- `status` also shows where the publication stands (preparing, ready for review, waiting for
|
|
244
|
+
approval with its URL, published, needs update).
|
|
245
|
+
- `start` prints the work's handle (`wk_…`) and saves it in `.blocofy/local.json` (git-ignored; the
|
|
246
|
+
handle alone grants nothing). It sends an `Idempotency-Key` (yours, or a printed `cli-work-<uuid>`):
|
|
247
|
+
the same key returns the same work, never a second one. When the answer is lost (network, 5xx),
|
|
248
|
+
the CLI prints the exact command to run again with the same key.
|
|
249
|
+
- `status`, `resume` and `cancel` always take the handle; with none they suggest the project's saved
|
|
250
|
+
work and stop. `status` and `resume` say whether the site changed since the work started; a changed
|
|
251
|
+
site is never overwritten. `resume --require-fresh` refuses (`work_stale`) instead.
|
|
252
|
+
- `cancel` reads the work's `state_version` and sends it; the live site is untouched and the work's
|
|
253
|
+
theme stays in the theme library.
|
|
254
|
+
- `theme push --work <wk_…>` writes into that work's own draft theme (`--work` implies `--draft`; it
|
|
255
|
+
cannot be combined with `--live` or `--instance`). It needs **both** the dev token and the API key of
|
|
256
|
+
the same site, and refuses unless the work is open (`work_state_conflict`, nothing written).
|
|
257
|
+
- Refusals print a plain Turkish explanation first, then the `error [code]` line (`--json`: the
|
|
258
|
+
envelope only): `not_found`, `work_forbidden`, `work_state_conflict`, `work_stale`, `work_sealed`,
|
|
259
|
+
`work_base_unavailable`, `quota_exceeded`, `capacity_unavailable`, `resource_busy`,
|
|
260
|
+
`idempotency_key_reuse` (exit 2 for a 4xx, 1 for a 5xx).
|
|
162
261
|
|
|
163
262
|
### Status
|
|
164
263
|
|
|
@@ -461,6 +560,71 @@ Each retry prints a notice on stderr.
|
|
|
461
560
|
|
|
462
561
|
## Changelog
|
|
463
562
|
|
|
563
|
+
- **0.15.0** (2026-10-05) — Theme space, theme work and human-approved
|
|
564
|
+
publishing. Pairs with the platform release that replaces the 5-draft limit with a per-site theme
|
|
565
|
+
space.
|
|
566
|
+
- **Capacity refusals in plain words.** A theme write refused by the platform explains why in
|
|
567
|
+
plain Turkish first, then prints the usual `error [code]` line (`--json`: the envelope only):
|
|
568
|
+
- `quota_exceeded` (exit 2) is worded by `details.resource`. `theme_bytes`: the site's theme space
|
|
569
|
+
is full — on any push, a push to an existing draft with `--instance` included. It shows used /
|
|
570
|
+
allowance from `details`, says to free space by deleting unused draft themes from the theme
|
|
571
|
+
library (cancelled works' themes included; cancelling an open work also releases its reserved
|
|
572
|
+
publish space; an archived work's theme still counts), or to contact support, and never suggests a plan upgrade or says "new draft" (theme space is not
|
|
573
|
+
a plan quota). `theme_drafts` (the old draft count, on sites that have not moved to theme space)
|
|
574
|
+
is not a plan limit either: it says to remove a draft you no longer need, never to upgrade.
|
|
575
|
+
Only `storage_mb` keeps the plan message. The envelope carries the server's `details`.
|
|
576
|
+
- `work_revision_limit` (exit 2; `theme work seal`, or `request-approval` when it prepares the
|
|
577
|
+
work): a work can be sent for review at most 20 times (`details.limit`); start a new work.
|
|
578
|
+
- `capacity_unavailable` / `resource_busy` (exit 1, after the usual retries that honour
|
|
579
|
+
`Retry-After`; the envelope carries `retryAfterSeconds`): a temporary refusal, try again later.
|
|
580
|
+
A 503 on the write is no longer reported as "outcome unknown" (the platform wrote nothing),
|
|
581
|
+
unless an earlier attempt of the same push got no answer.
|
|
582
|
+
- `source_stale` (exit 2): the live theme changed while a new draft was copied; run it again.
|
|
583
|
+
- `theme dev` reports the same refusals in one line per save.
|
|
584
|
+
- **`theme pull --draft` is read-only.** Help and README no longer claim it creates the draft. With
|
|
585
|
+
no CLI draft the platform answers 404 `target_missing`; the CLI tells you to run
|
|
586
|
+
`blocofy theme push --draft` first (exit 2, nothing written). The command still needs a bound
|
|
587
|
+
project (kept for platforms from before this change).
|
|
588
|
+
- **New: theme work.** `theme work start|status|resume|cancel` and `theme push --work <wk_…>`
|
|
589
|
+
(v1 API key; see "Theme work"). A work is a private copy of the current live theme, named only by
|
|
590
|
+
its handle; the handle is saved in `.blocofy/local.json`. A plain `theme push` is unchanged and
|
|
591
|
+
never calls the work API.
|
|
592
|
+
- **New: human-approved publishing.** `theme work seal` (prepare for review, asks for no approval)
|
|
593
|
+
and `theme work request-approval [--open] [--wait [--interval <s>]]`: prints the approval URL (no
|
|
594
|
+
token in it), optionally opens it, and `--wait` polls the status read-only — exit 0 when
|
|
595
|
+
published, 2 when the request ends without a publication (`approval_stale`, `approval_expired`,
|
|
596
|
+
`approval_declined`, `approval_superseded`, `work_cancelled`), 1 on `wait_timeout` or
|
|
597
|
+
`publish_failed` (table under "Theme work"). `theme work status` shows the publish status. The CLI
|
|
598
|
+
never publishes a work.
|
|
599
|
+
- **`theme publish` names a work copy's refusal.** Publishing a theme work's copy directly is refused
|
|
600
|
+
by the platform (`work_not_publishable`, exit 2, nothing published); the CLI now keeps that code
|
|
601
|
+
(it printed `HTTP_409` before) and says to send the work for review and ask for approval.
|
|
602
|
+
- Unchanged: retry classes, `draft_target_ambiguous` handling, idempotency keys, target guards and
|
|
603
|
+
protocol headers.
|
|
604
|
+
- **0.14.0** — Draft commands no longer guess their draft (platform #989).
|
|
605
|
+
- **Behaviour change:** `theme push` (draft), `theme push --diff`, `theme pull --draft` and the
|
|
606
|
+
`theme dev` sync refuse, writing nothing, when the platform answers `draft_target_ambiguous` (or the
|
|
607
|
+
site status shows the same case): the message lists the candidate drafts and the exact
|
|
608
|
+
`--instance <handle>` command; exit code 2; never retried. A CLI draft you renamed is refused too.
|
|
609
|
+
- The refusal pre-fills `--instance` only for a safe candidate (CLI-named, not a restore draft) and
|
|
610
|
+
otherwise warns that naming a listed draft would overwrite it.
|
|
611
|
+
- `theme dev --instance <handle>` and `theme push --draft --instance <handle>` write to a chosen draft
|
|
612
|
+
(sent with `draft: true`; never the live theme).
|
|
613
|
+
- `theme dev` reports a draft-sync failure in one line, also at startup (it was silent there):
|
|
614
|
+
`draft_target_unverifiable` (the next save tries again) and `draft_target_is_live` (stops).
|
|
615
|
+
- **Behaviour change:** `theme publish` without `--instance` uses the same rule; it never publishes
|
|
616
|
+
a guessed draft.
|
|
617
|
+
- **Behaviour change:** `--name X` creates the draft as `CLI Draft — X`; the rename advice after a
|
|
618
|
+
reused draft is gone (a draft renamed by hand to another name is refused).
|
|
619
|
+
- **Behaviour change (CI):** `theme push --instance <the live theme's handle>` asks for the same
|
|
620
|
+
confirmation as `--live` (`--yes` in non-interactive shells); so does a handle the CLI cannot tell
|
|
621
|
+
apart from the live theme (live theme unknown, or a raw numeric id).
|
|
622
|
+
- `theme publish --instance <handle>` tells the platform the theme was named explicitly
|
|
623
|
+
(`explicit: true`); the automatic pick sends no flag and the platform re-checks it. A theme that is
|
|
624
|
+
not the site's CLI draft (a site-state restore draft, a renamed or panel-copied theme) is published
|
|
625
|
+
through the CLI only with `--instance`; otherwise the platform refuses with
|
|
626
|
+
`publish_target_unconfirmed` (exit 2, nothing published). Older CLIs get that refusal as a generic
|
|
627
|
+
error and can never publish such a theme.
|
|
464
628
|
- **0.13.0** — Draft push names its target (customer items PS-22/PS-23/PS-26).
|
|
465
629
|
- `theme push` (draft) prints the draft it wrote to — handle, name, new or existing — and
|
|
466
630
|
`blocofy theme publish --instance <handle>`. When it updated the existing CLI draft, it says
|