@blocofy/cli 0.14.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 CHANGED
@@ -80,8 +80,10 @@ changing credentials, context or the project binding).
80
80
  blocofy theme pull [dir] [--draft] [--instance <handle>]
81
81
  ```
82
82
  Download the live theme to disk. `dir` defaults to cwd.
83
- - `--draft` — pull the draft theme (what `theme dev` syncs into) instead of live; creates the
84
- draft if missing, so it needs a bound project.
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.
85
87
  - `--instance <handle>` — pull a specific theme by its handle (admin panel theme card, or
86
88
  `blocofy status`).
87
89
 
@@ -130,6 +132,20 @@ create a new draft theme in the admin panel and pass its handle with `--instance
130
132
  delete the restore draft first. `theme publish` without `--instance` uses the same rule and never
131
133
  publishes a guessed draft. With no draft at all, the first push creates one as before.
132
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
+
133
149
  After a draft push the CLI prints the draft it wrote to (`Draft: <handle> "<name>" (new)` or
134
150
  `(existing CLI draft, updated)`) and the `blocofy theme publish --instance <handle>` command.
135
151
  - `--idempotency-key <k>` — attach a key so a retried push is not double-applied.
@@ -184,6 +200,65 @@ theme publish ./shop` always publishes `./shop`'s site, whatever directory you r
184
200
  site's CLI draft; any other theme (a site-state restore draft, a renamed or panel-copied theme) is
185
201
  refused with `publish_target_unconfirmed` (exit 2, nothing published) — name it with `--instance`.
186
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).
261
+
187
262
  ### Status
188
263
 
189
264
  ```
@@ -485,6 +560,47 @@ Each retry prints a notice on stderr.
485
560
 
486
561
  ## Changelog
487
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.
488
604
  - **0.14.0** — Draft commands no longer guess their draft (platform #989).
489
605
  - **Behaviour change:** `theme push` (draft), `theme push --diff`, `theme pull --draft` and the
490
606
  `theme dev` sync refuse, writing nothing, when the platform answers `draft_target_ambiguous` (or the