@samva/cli 0.4.0 → 0.6.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.
Files changed (4) hide show
  1. package/AGENTS.md +14 -2
  2. package/README.md +84 -34
  3. package/dist/bin.mjs +1890 -953
  4. package/package.json +8 -9
package/AGENTS.md CHANGED
@@ -4,12 +4,22 @@ Use `samva --help` and `samva <command> --help` as the command contract. For aut
4
4
  `SAMVA_API_KEY`, `--json` for one bounded result, and `--jsonl` with `--all` for streamed lists.
5
5
  Machine-readable results go to stdout; warnings and typed errors go to stderr.
6
6
 
7
- `samva templates export --dir <dir> --out <dir>` renders every local template's fixtures to HTML
7
+ `samva templates export --out <dir>` renders every local template's fixtures to HTML
8
8
  and text with the asset manifest, needing a Samva credential only to resolve a live `samva:brand`; `--asset-base <origin>` is for an
9
9
  export that will be delivered, which cannot carry a relative reference.
10
10
  `samva templates check --watch` is the continuous authoring gate. Human mode prints observations;
11
11
  machine watch output uses `--jsonl`. `--json` remains one-shot.
12
12
 
13
+ The developer loop for a template project is `samva templates dev` (the local visual editor, no
14
+ `vite.config.ts`), `check` (type-check, compile, and render every fixture), `render <template>
15
+ --fixture <name>` (subject, preheader, and plain-text body; `--format html`, `--channel sms|whatsapp`),
16
+ and `snapshot <template> --fixture <name>` (desktop and mobile PNGs, light and dark, in
17
+ `.samva/snapshots`, needing `playwright` in the project or a system Chrome). With `--json`, every
18
+ finding carries `code`, `severity`, `message`, `file`, `line`/`column`, `range`, and, where the
19
+ compiler has them, `fix` and a machine-applicable `edit`. Templates live in `templates/` and
20
+ `emails/`; a template is a `.tsx` file that default-exports `defineTemplate`, and the compiler reads
21
+ it without running it.
22
+
13
23
  `--publication-id` and `--input-contract-id` on `email send`, `scheduled-messages create`, and
14
24
  `campaigns create`/`update` choose which publication a template send renders: one exact publication,
15
25
  or the newest publication that still validates input identically. They are mutually exclusive and
@@ -47,11 +57,13 @@ repository. `samva templates clone <project-or-template-id>` clones an existing
47
57
  repository-local credential helper that exchanges Samva authorization for a short-lived,
48
58
  repository-scoped credential; the token is never stored in the remote URL or Git config. Normal
49
59
  `git fetch`, `git pull`, `git add`, `git commit`, and `git push` remain the synchronization commands.
60
+ A pushed commit is picked up on the next hosted workspace open; independent draft edits rebase,
61
+ and overlapping edits produce explicit conflicts.
50
62
  Install from the project's lockfile (`bun install --frozen-lockfile` or `npm ci`) before `samva templates check` or `samva templates build`, then
51
63
  publish a clean, pushed commit with `samva templates publish`. Publish checks that the selected
52
64
  commit is an ancestor of the fetched `origin/<default-branch>` and creates an immutable receipt; it
53
65
  does not push or rewrite history. A project holds several emails: `samva templates add
54
- <emails/x.tsx>` registers another entry under its `defineEmail` id, `samva templates publish --all`
66
+ <templates/x.tsx>` registers another entry under its `defineTemplate` id, `samva templates publish --all`
55
67
  publishes every active entry at one commit and exits non-zero if any failed, and `samva templates
56
68
  move <old> <new>` follows a `git mv`. The CLI loads the project's installed authoring toolchain so its
57
69
  compiler and editor versions stay pinned by the project lockfile.
package/README.md CHANGED
@@ -139,19 +139,24 @@ bun run dev
139
139
  ```
140
140
 
141
141
  The starter repository contains `@samva/markup`, `@samva/vite`, Vite, the project theme, and its
142
- lockfile. The CLI deliberately loads `@samva/vite/build` from the current project, so local preview,
143
- check, and build use the compiler version recorded in that lockfile. The clone has a normal HTTPS
142
+ lockfile. The CLI deliberately loads `@samva/vite` from the current project, so local preview,
143
+ check, render, and build use the compiler version recorded in that lockfile. A project without
144
+ `@samva/markup`, `@samva/vite`, and `vite` fails with the install command
145
+ (`npm install --save-dev @samva/markup @samva/vite vite`). The clone has a normal HTTPS
144
146
  `origin`; its repository-local credential helper obtains a one-hour, repository-scoped Artifact
145
147
  credential from Samva when Git needs one. The credential is not written to the remote URL or Git
146
148
  configuration.
147
149
 
148
150
  ```sh
149
- samva templates check --dir emails
151
+ samva templates dev
152
+ samva templates check
150
153
  samva templates check --json
151
- samva templates build --dir emails --out dist/templates.json
154
+ samva templates render welcome --fixture default
155
+ samva templates snapshot welcome --fixture default
156
+ samva templates build --out dist/templates.json
152
157
  samva templates check --watch
153
158
  samva templates check --watch --jsonl
154
- git add emails theme.css
159
+ git add templates theme.css
155
160
  git commit -m "feat: update welcome email"
156
161
  git push origin main
157
162
  samva templates publish --commit HEAD --json
@@ -161,37 +166,47 @@ A project holds as many emails as you need, sharing its components, theme, and l
161
166
  another entry, register it, then publish every entry at one commit:
162
167
 
163
168
  ```sh
164
- samva templates add emails/reset.tsx
165
- git add emails && git commit -m "feat: add password reset" && git push origin main
169
+ samva templates add templates/reset.tsx
170
+ git add templates && git commit -m "feat: add password reset" && git push origin main
166
171
  samva templates publish --all
167
172
  ```
168
173
 
169
- `add` uses the entry's `defineEmail` id as the template's handle; pass `--slug` and `--name` to
174
+ `add` uses the entry's `defineTemplate` id as the template's handle; pass `--slug` and `--name` to
170
175
  choose others or to register an entry before the file exists. `publish --all` publishes every
171
176
  active template in the project, reports each result, exits non-zero when any entry failed, and
172
- lists `defineEmail` files that are not registered. Rerunning it after a partial failure is safe.
177
+ lists `defineTemplate` files under `templates/` or `emails/` that are not registered. Rerunning it after a partial failure is safe.
173
178
  After `git mv`, `samva templates move <old-path> <new-path>` points the template at the new file
174
179
  and keeps its id, handle, and publications.
175
180
 
176
- Email entries default-export `defineEmail` with an input schema and declared fixtures. `check`
177
- typechecks the project and renders every fixture; `build` writes those rendered fixtures, the input
178
- schema, and the compiled executable module graph. Helper modules without a default export are not
179
- templates, and every email definition must have a unique id. SMS and WhatsApp retain their
180
- structured-channel compiler.
181
-
182
- The JSON file written by `build` uses `schemaVersion: 2`: email previews have `kind: "email"` and
183
- contain actual fixture outputs; structured previews have `kind: "structured"`. Email source in the
184
- artifact is authored TSX. The CLI's stdout envelope remains version 1.
181
+ Templates live in `templates/`, and `emails/` is also recognized; every authoring command scans
182
+ whichever exist, and `--dir <dir>` scans only that one. A template is a `.tsx` file that
183
+ default-exports `defineTemplate` with an input schema, declared fixtures, and an `email`, `sms`, or
184
+ `whatsapp` body. The compiler reads the file without running it, so top-level code in a template
185
+ does not execute. `check` type-checks the project, compiles every template, and renders every
186
+ fixture through every channel the template declares; `build` writes those rendered fixtures, each
187
+ template's input schema, and its compiled IR. Modules without a template default export are
188
+ helpers, and every template needs a unique id.
189
+
190
+ The JSON file written by `build` uses `schemaVersion: 3`. Its `result` is the `@samva/vite/build`
191
+ result: `files[]`, one per template entry, each with `ok`, `diagnostics`, and a `template` carrying
192
+ `template` (the id), `channels`, `source`, `inputSchema`, `ir`, `fixtures[]` (each with its `email`
193
+ subject, preheader, HTML and text, its `sms` text, or its `whatsapp` message), and `compatibility`
194
+ findings. The former `preview.kind` `"email"` and `"structured"` shapes no longer exist. The CLI's
195
+ stdout envelope remains version 1.
185
196
 
186
197
  For imported email assets, pass their actual serving base to `check` or `build`, for example
187
198
  `samva templates build --out dist/templates.json --asset-base https://cdn.example.com/email`.
188
199
  These commands require an HTTPS base for delivery; they do not invent a URL or upload assets.
189
- `templates export --dir emails --out dist/email` remains the way to write a local HTML/text export
190
- with relative asset URLs. Like `check` and `build`, it treats the current directory as the project:
191
- its `theme.css` themes the export and `samva:brand` resolves live or from `.samva/brands`.
200
+ `templates export --out dist/email` remains the way to write a local HTML/text export
201
+ with relative asset URLs, plus `<fixture>.sms.txt` and `<fixture>.whatsapp.json` for those channels.
202
+ Like `check` and `build`, it treats the current directory as the project: its `theme.css` themes
203
+ the export and `samva:brand` resolves live or from `.samva/brands`.
204
+
205
+ `git fetch`, `git pull`, `git add`, `git commit`, and `git push` are ordinary Git operations.
206
+ The next hosted workspace open picks up a pushed commit, rebases independent draft edits, and
207
+ records explicit conflicts for overlapping edits.
192
208
 
193
- `git fetch`, `git pull`, `git add`, `git commit`, and `git push` are ordinary Git operations. The
194
- CLI's `init` and `clone` commands configure the repository-local helper; `publish` does not push
209
+ The CLI's `init` and `clone` commands configure the repository-local helper; `publish` does not push
195
210
  for you. It accepts a clean commit that is reachable from the fetched `origin/<default-branch>`
196
211
  and publishes that exact commit. A clone records its project in `samva.projectId`; pass
197
212
  `--project-id` from a checkout that `samva templates init` or `clone` did not create.
@@ -202,14 +217,47 @@ Artifact credential. `samva templates credential` is an internal helper command,
202
217
  credential store. Local OAuth credentials remain in the OS keyring; `SAMVA_API_KEY` remains the
203
218
  automation path.
204
219
 
220
+ `samva templates dev [--dir <dir>] [--port <n>] [--host <name>] [--open]` starts the local visual
221
+ editor from the project's `@samva/vite/dev` under Node.js, with no `vite.config.ts`. It prints the
222
+ editor URL and runs until interrupted; `SIGINT` and `SIGTERM` close the server.
223
+
205
224
  `samva templates check` runs the project's TypeScript configuration, then uses the project's
206
- `@samva/vite/build` to evaluate default exports, emit SML, compile channel artifacts, and report
207
- phase/provenance diagnostics plus email-client compatibility findings. It writes no files and exits
208
- non-zero on TypeScript, discovery, module, theme, emit, compile, or breaking compatibility errors.
209
- `--watch` reuses one Vite evaluator across template, dependency, discovery, and theme changes.
210
- Human mode prints each observation; machine watch mode requires `--jsonl`. `--json` remains a
211
- bounded one-shot result. `SIGINT` and `SIGTERM` close the watcher and keep the CLI's documented
212
- interrupt exit codes.
225
+ `@samva/vite/build` to compile every template, render every fixture, and report located findings
226
+ plus email-client compatibility findings. It writes no files and exits non-zero on TypeScript,
227
+ compile, fixture, or breaking compatibility errors. `--watch` reuses one compiler session across
228
+ template, dependency, and theme changes. Human mode prints each observation; machine watch mode
229
+ requires `--jsonl`. `--json` remains a bounded one-shot result. `SIGINT` and `SIGTERM` close the
230
+ watcher and keep the CLI's documented interrupt exit codes.
231
+
232
+ Every finding in `check --json` (`problems[]`), `build --json`, `render --json`, and `export --json`
233
+ has the same fields: `code`, `severity`, `message`, `file`, `line` and `column` when located,
234
+ `range` (the located extent), `fix` (what to write instead) when the compiler has one, and `edit`
235
+ (a machine-applicable change) when it offers one; `check` and `build` add `phase`, and a finding
236
+ tied to one fixture names it in `fixture`. Human output prints
237
+ `file:line:column severity code: message` and the fix beneath it. `check --json` also carries
238
+ `warnings[]` for compile warnings and `compatibility` for client findings.
239
+
240
+ `samva templates render <template> --fixture <name>` renders one fixture of a local template
241
+ through the project's `@samva/vite/render`. `<template>` is a template id or its `.tsx` path.
242
+ `--channel email|sms|whatsapp` picks the body (default `email`), `--locale` and `--time-zone`
243
+ set formatter locale and IANA zone, `--asset-base` and `--offline` behave as for `check`, and
244
+ `--dir` narrows discovery. The default output is the subject, preheader, and plain-text body;
245
+ `--format html` prints the HTML and `--format json` (or `--json`) prints
246
+ `{ action: "templates.render", ok, template, fixture, subject, preheader?, html, text, diagnostics }`
247
+ (an SMS render carries `channel` and `text`; a WhatsApp render carries `channel` and `message`).
248
+ `--out <file>` writes the selected format to a file. A template or fixture that does not exist, or
249
+ a template that does not compile, exits `1` with located findings; an unknown name lists the valid
250
+ ones.
251
+
252
+ `samva templates snapshot <template> --fixture <name>` renders the email and screenshots it in a
253
+ headless browser at `desktop` (1280px) and `mobile` (390px) widths, in `light` and `dark` color
254
+ schemes, as full-page PNGs at `<out>/<template>-<fixture>-<viewport>-<scheme>.png` (default
255
+ `--out .samva/snapshots`). `--viewport desktop,mobile` and `--scheme light,dark` narrow the set.
256
+ `--json` prints `{ action: "templates.snapshot", ok, template, fixture, browser, out, files: [{ viewport,
257
+ scheme, width, path }] }`. The browser is the `playwright` (or `playwright-core`) your project
258
+ installs; without it, a system Google Chrome or Chromium, found in the usual locations or at
259
+ `SAMVA_CHROME`. With neither the command fails and names both remedies. Screenshots emulate the
260
+ color scheme; they do not reproduce a particular mail client's rendering.
213
261
 
214
262
  `samva templates build` runs the same compiler gate and writes the complete compiled result as a
215
263
  versioned JSON artifact for package and deployment pipelines. Its terminal/JSON result stays
@@ -357,14 +405,16 @@ samva webhooks test wep_abc123 --data '{"event":"webhook.test"}' --json
357
405
  samva webhooks test wep_abc123 --data @payload.json --json
358
406
  ```
359
407
 
360
- `samva email doctor` reports resolved profile, API URL, auth source, organization access,
361
- sending domains, senders, and domain-verification readback. It is read-only and does not inspect
362
- receiving configuration, verify DNS, send an email, replay fixtures, or check provider readiness.
408
+ `samva email doctor` reports resolved profile, API URL, auth source, organization access, the send
409
+ review decision, sendable domain and verified sender counts, and domain-verification readback.
410
+ `readyToSend` is true when a production send would be admitted and at least one domain or sender can
411
+ carry it. It is read-only and does not inspect receiving configuration, check DNS itself, send an
412
+ email, or replay fixtures.
363
413
  Use `samva email receiving status <domain-id>` to read a domain's receiving prerequisite status.
364
414
  `samva email receiving enable <domain-id> ...` acts by default; its `--dry-run` is offline and does
365
415
  not require credentials or call the API. Each check is `passed`, `failed`, or
366
416
  `unavailable`. A `failed` check carries the underlying error detail; `unavailable`, such as no
367
- sending domain configured yet, is informational. The command always prints the full report, then
417
+ sending domain yet or a review in progress, is informational; a rejected review fails. The command always prints the full report, then
368
418
  exits `1` if any check failed and `0` otherwise. The `--json` result's `data` adds an aggregate
369
419
  `ok` boolean, and human output marks checks with `✓`, `!`, and `✗` respectively.
370
420