caracms 0.7.0 → 0.8.1
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 +108 -19
- package/bin/caracms.mjs +11 -3
- package/bin/init.mjs +332 -34
- package/bin/media.mjs +60 -6
- package/bin/templates/railway-cloud.ts.txt +73 -0
- package/package.json +1 -1
- package/skills/caracms-adopt/SKILL.md +30 -13
- package/skills/caracms-hosting/SKILL.md +240 -0
- package/skills/caracms-tina/SKILL.md +45 -15
- package/src/body.ts +55 -0
- package/src/cli/validate.ts +1 -1
- package/src/cloud-middleware.ts +51 -5
- package/src/config.ts +20 -1
- package/src/content.ts +15 -6
- package/src/document-problems.ts +48 -0
- package/src/editor/client/collections/CollectionGrid.tsx +2 -2
- package/src/editor/client/collections/CollectionTable.tsx +3 -3
- package/src/editor/client/documents/DocMenu.tsx +56 -1
- package/src/editor/client/documents/actions.ts +30 -1
- package/src/editor/client/documents/dialogs.tsx +61 -3
- package/src/editor/client/editor.ts +98 -2
- package/src/editor/client/fields/LockupField.tsx +4 -4
- package/src/editor/client/inbox/InboxStage.tsx +25 -1
- package/src/editor/client/live/notices.tsx +19 -0
- package/src/editor/client/live/publish.tsx +58 -2
- package/src/editor/client/nav/DocRow.tsx +4 -4
- package/src/editor/client/pane/levels/CollectionLevel.tsx +2 -1
- package/src/editor/client/pane/levels/DocumentLevel.tsx +2 -1
- package/src/editor/client/pane/levels/DocumentsLevel.tsx +2 -2
- package/src/editor/client/pane/levels/FormLevel.tsx +33 -6
- package/src/editor/client/pane/levels/SubmissionsLevel.tsx +19 -2
- package/src/editor/client/pane/parts.tsx +67 -4
- package/src/editor/client/pane/switcher.tsx +4 -4
- package/src/editor/client/shell/Bar.tsx +11 -0
- package/src/editor/client/state/keeper.ts +28 -4
- package/src/editor/client/state/live.ts +18 -1
- package/src/editor/routes/_live.ts +1 -1
- package/src/editor/routes/admin.astro +9 -0
- package/src/editor/routes/discard.ts +11 -0
- package/src/editor/server/admin-props.ts +18 -2
- package/src/editor/server/arrange.ts +4 -4
- package/src/editor/server/create.ts +4 -4
- package/src/editor/server/drafts-store.ts +2 -2
- package/src/editor/server/empty-site.ts +23 -0
- package/src/editor/server/media/cloud-mux.ts +4 -1
- package/src/editor/server/media/config.ts +12 -5
- package/src/editor/server/media/upload.ts +2 -41
- package/src/editor/server/mode.ts +3 -1
- package/src/editor/server/move.ts +32 -4
- package/src/editor/server/write.ts +4 -4
- package/src/editor/styles/levels/live.css +2 -0
- package/src/editor/types.ts +92 -4
- package/src/email.ts +4 -1
- package/src/forms/cloud-store.ts +4 -1
- package/src/forms/inbox.ts +10 -5
- package/src/forms/store.ts +21 -4
- package/src/index.ts +21 -6
- package/src/live/auth/login.ts +4 -3
- package/src/live/auth/views.ts +8 -1
- package/src/live/autosaves.ts +94 -6
- package/src/live/cloud.ts +64 -20
- package/src/live/drafts-store.ts +17 -6
- package/src/live/editor.ts +232 -16
- package/src/live/git.ts +492 -22
- package/src/live/github.ts +84 -17
- package/src/live/locks.ts +22 -0
- package/src/live/messages.ts +49 -2
- package/src/live/mode.ts +19 -8
- package/src/live/notices.ts +5 -1
- package/src/live/runtime.ts +2 -1
- package/src/live/services.ts +114 -0
- package/src/live/status.ts +5 -0
- package/src/live/sweep.ts +44 -1
- package/src/live/webhook.ts +8 -3
- package/src/media.ts +9 -3
package/README.md
CHANGED
|
@@ -10,8 +10,17 @@ is, under the MIT license.
|
|
|
10
10
|
|
|
11
11
|
## Start
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
Two steps: create an Astro site, then add caracms to it with `npx caracms init`.
|
|
14
|
+
(`npm create caracms` says the same.)
|
|
15
|
+
|
|
16
|
+
**1. Create the Astro site** (Astro 7, on Node 22.12 or later), or use one you have:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
npm create astro@latest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**2. In it, add caracms.** From the site's root, in a clean git checkout, install it and
|
|
23
|
+
commit the install:
|
|
15
24
|
|
|
16
25
|
```sh
|
|
17
26
|
npm install caracms --save-exact
|
|
@@ -27,8 +36,10 @@ one diff to review. Then look at what `init` would do:
|
|
|
27
36
|
npx caracms init
|
|
28
37
|
```
|
|
29
38
|
|
|
30
|
-
It
|
|
31
|
-
|
|
39
|
+
It asks where the site will run, [CaraCMS Cloud](#caracms-cloud) or self-hosted, then
|
|
40
|
+
prints every file it would add and every edit it would make, as a diff, and changes
|
|
41
|
+
nothing. (It asks only in a terminal: an agent or a script passes `--cloud` or
|
|
42
|
+
`--self-hosted`.) When it looks right, apply it and install what it added:
|
|
32
43
|
|
|
33
44
|
```sh
|
|
34
45
|
npx caracms init --write
|
|
@@ -45,9 +56,12 @@ job of the `caracms-adopt` skill, one page at a time.
|
|
|
45
56
|
|
|
46
57
|
Run from the site's root:
|
|
47
58
|
|
|
48
|
-
- `caracms init [--write] [--railway]`: add caracms to an Astro
|
|
49
|
-
site's skills, schemas and CLAUDE.md block up to date.
|
|
50
|
-
|
|
59
|
+
- `caracms init [--write] [--railway] [--cloud | --self-hosted]`: add caracms to an Astro
|
|
60
|
+
site, or bring a set-up site's skills, schemas and CLAUDE.md block up to date.
|
|
61
|
+
`--cloud` or `--self-hosted` says where the site runs, written into `caracms.config.ts`
|
|
62
|
+
as `services` ([Where the site runs](#where-the-site-runs-services)); `--cloud` on a
|
|
63
|
+
self-hosted site also prints the steps of the move. `--railway` also writes a Railway
|
|
64
|
+
setup; without it, `init` prints the variables any host needs (Hosting, below).
|
|
51
65
|
- `caracms validate [--fix] [--json]`: check the content against `caracms.config.ts`.
|
|
52
66
|
Exits 1 when there are errors. `--fix` runs `caracms schemas` first, then lays each
|
|
53
67
|
content file out as the editor saves it (two-space JSON; only whitespace changes).
|
|
@@ -59,8 +73,8 @@ Run from the site's root:
|
|
|
59
73
|
keeping every key ([Moving a site's images in](#moving-a-sites-images-in)).
|
|
60
74
|
- `caracms start`: serve the built site (Hosting, below).
|
|
61
75
|
|
|
62
|
-
The skills (`caracms-content`, `caracms-blocks
|
|
63
|
-
the rest works, matching the installed version.
|
|
76
|
+
The skills (`caracms-content`, `caracms-blocks`, `caracms-adopt`, `caracms-tina` and
|
|
77
|
+
`caracms-hosting`, in `skills/`) say how the rest works, matching the installed version.
|
|
64
78
|
|
|
65
79
|
## Collections and addresses
|
|
66
80
|
|
|
@@ -204,7 +218,8 @@ It prints where the IP comes from when it starts.
|
|
|
204
218
|
- Commit: `RAILWAY_GIT_COMMIT_SHA`, which Railway sets.
|
|
205
219
|
- `caracms init --railway` writes `.railway/railway.ts`, which describes the whole
|
|
206
220
|
project (the site, Redis, the buckets, imgproxy). Railway's own variables cover the
|
|
207
|
-
repo, so `GITHUB_REPO` isn't needed.
|
|
221
|
+
repo, so `GITHUB_REPO` isn't needed. With `--cloud` it writes only the site and Redis:
|
|
222
|
+
the cloud brings the rest.
|
|
208
223
|
- Try again: `CARACMS_RAILWAY_TOKEN`, a project token. Railway has no deploy hook.
|
|
209
224
|
|
|
210
225
|
### Render
|
|
@@ -315,8 +330,78 @@ site, signs every commit, and isn't tied to a person. Use it for anyone running
|
|
|
315
330
|
a handful of sites, or a repo that requires signed commits. Install it on the site's repo
|
|
316
331
|
only, with the same permissions as the token.
|
|
317
332
|
|
|
333
|
+
**Protect `drafts` from deletion.** It holds every change saved since the last Publish,
|
|
334
|
+
and to a branch tidy-up it looks like any stale branch. In the repo's Settings → Rules →
|
|
335
|
+
Rulesets, add a branch ruleset that targets `drafts` and turns on "Restrict deletions"
|
|
336
|
+
only (leave "Block force pushes" off: Publish moves `drafts` with a forced update). If
|
|
337
|
+
`drafts` goes anyway, the next start makes it again from the last commit the server
|
|
338
|
+
recorded, while GitHub still has that commit; when it can't, the editor says what was lost.
|
|
339
|
+
|
|
340
|
+
**Roll the site back with `git revert`, never a force-push.** A revert is a new commit on
|
|
341
|
+
`main`, which `drafts` takes in like any push; resetting `main` to an older commit and
|
|
342
|
+
force-pushing leaves the rolled-back content waiting in the editor, so the next Publish puts
|
|
343
|
+
it back (the editor warns everyone when it sees one).
|
|
344
|
+
|
|
318
345
|
### CaraCMS Cloud
|
|
319
346
|
|
|
347
|
+
#### Where the site runs: `services`
|
|
348
|
+
|
|
349
|
+
`caracms.config.ts` says where the site's services (GitHub access, images, forms and
|
|
350
|
+
email, video) come from, and nothing else decides it:
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
export default defineSite({
|
|
354
|
+
services: 'cloud', // or 'self-hosted'
|
|
355
|
+
collections: { … },
|
|
356
|
+
…
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
- **`'cloud'`**: everything comes through `CARACMS_CLOUD_KEY`. The self-hosted variables
|
|
361
|
+
(the GitHub token or App and `GITHUB_REPO`, the image, video, and form and email ones
|
|
362
|
+
below) are **ignored**, never read, and each is named once in the build log and once
|
|
363
|
+
when the server starts:
|
|
364
|
+
|
|
365
|
+
> S3_BUCKET is set, but this site runs on CaraCMS Cloud (caracms.config.ts): it's ignored. Remove it once the old bucket and imgproxy are retired.
|
|
366
|
+
|
|
367
|
+
So a site can move with its old variables still set, and remove them afterwards. A
|
|
368
|
+
production build or server with no key fails with "This site runs on CaraCMS Cloud
|
|
369
|
+
(caracms.config.ts), but CARACMS_CLOUD_KEY isn't set. Make a key for it in
|
|
370
|
+
app.caracms.com." (the build fails; a running server's `/admin` answers 503 with it, and
|
|
371
|
+
the public site keeps serving). It never falls back to the self-hosted variables.
|
|
372
|
+
`astro dev` without a key is local mode, as always.
|
|
373
|
+
- **`'self-hosted'`**: the site's own variables, as [the variables](#the-variables) list
|
|
374
|
+
them. A `CARACMS_CLOUD_KEY` beside them is ignored the same way.
|
|
375
|
+
- **Not set** (a site from before caracms 0.8.0): the key decides, and setting it beside
|
|
376
|
+
the site's own variables is refused, as each section below says. The next `caracms init`
|
|
377
|
+
adds the field.
|
|
378
|
+
|
|
379
|
+
`caracms init --cloud` or `--self-hosted` writes the field (as the first line inside
|
|
380
|
+
`defineSite({`). With neither, `init` asks in a terminal and, run by an agent or a script,
|
|
381
|
+
leaves a set-up site's mode unset (and says so) or stops on a new one. Once the field is
|
|
382
|
+
there, `init` reads it and never asks again.
|
|
383
|
+
|
|
384
|
+
**Moving a self-hosted site onto the cloud.** `caracms init --cloud` on a self-hosted site
|
|
385
|
+
writes the field and prints the steps of the move, in order, each with the check that it
|
|
386
|
+
worked: make the site, its key and the App's install in app.caracms.com; push the field
|
|
387
|
+
(the host's build fails until the key is set: the old deployment keeps serving); copy the
|
|
388
|
+
images in with [`caracms media push`](#moving-a-sites-images-in); set the key on the host;
|
|
389
|
+
upload the video clips again; remove every variable the cloud replaces (it names them all,
|
|
390
|
+
marking the ones it found in `.env` and `.railway/railway.ts`; it can't see the host's own
|
|
391
|
+
page, so check that too); retire what the cloud replaced; and, last, cut
|
|
392
|
+
`.railway/railway.ts` down to the site and Redis. `init` never edits an existing
|
|
393
|
+
`.railway/railway.ts`: `railway config apply` would remove the buckets with it. With a key
|
|
394
|
+
in the environment or `.env`, `init --cloud` also checks it, showing the site, its team,
|
|
395
|
+
the linked repo and whether the App is installed on it, or the cloud's reason for refusing
|
|
396
|
+
it (it never prints the key). The `caracms-hosting` skill walks through all of this.
|
|
397
|
+
|
|
398
|
+
**Leaving.** `caracms init --self-hosted` on a cloud site writes the field back and prints
|
|
399
|
+
the way back: set up the site's own services ([Hosting](#hosting)), copy the site's folder
|
|
400
|
+
from the cloud's media bucket to a bucket of your own (the keys in content stay the same),
|
|
401
|
+
set the variables, then remove the key.
|
|
402
|
+
|
|
403
|
+
#### GitHub access on CaraCMS Cloud
|
|
404
|
+
|
|
320
405
|
A site run by CaraCMS can take its GitHub access from CaraCMS Cloud instead of a token or
|
|
321
406
|
an App of its own. The cloud gives the site's server a short-lived token for the site's
|
|
322
407
|
repo, and only that repo, about once an hour.
|
|
@@ -329,8 +414,9 @@ repo, and only that repo, about once an hour.
|
|
|
329
414
|
site's server.
|
|
330
415
|
|
|
331
416
|
The key replaces `CARACMS_GITHUB_TOKEN` (or `GITHUB_APP_ID` and `GITHUB_APP_PRIVATE_KEY`)
|
|
332
|
-
and `GITHUB_REPO`: the repo comes from the cloud when the server starts
|
|
333
|
-
|
|
417
|
+
and `GITHUB_REPO`: the repo comes from the cloud when the server starts. With `services: 'cloud'`
|
|
418
|
+
they're ignored; on a site whose config doesn't say, setting `GITHUB_REPO` beside the key is
|
|
419
|
+
refused, and so is setting a token or an App as well. It
|
|
334
420
|
also replaces the image variables ([Images](#images-on-caracms-cloud), below), the
|
|
335
421
|
video ones ([Video](#video-on-caracms-cloud)), and the form and email ones
|
|
336
422
|
([Forms and email](#forms-and-email-on-caracms-cloud)).
|
|
@@ -350,7 +436,8 @@ start.
|
|
|
350
436
|
With the key, the site's images live in its own folder of CaraCMS Cloud's media bucket and
|
|
351
437
|
are served, resized and signed, from `img.caracms.cloud`. Set none of `S3_ENDPOINT`,
|
|
352
438
|
`S3_REGION`, `S3_BUCKET`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, `IMGPROXY_KEY`,
|
|
353
|
-
`IMGPROXY_SALT` or `CARACMS_MEDIA_URL
|
|
439
|
+
`IMGPROXY_SALT` or `CARACMS_MEDIA_URL`. With `services: 'cloud'` they're ignored; on a site
|
|
440
|
+
whose config doesn't say, setting any of them beside the key is refused with
|
|
354
441
|
|
|
355
442
|
> Set CARACMS_CLOUD_KEY or the site's own media variables, not both: remove S3_BUCKET.
|
|
356
443
|
|
|
@@ -374,8 +461,9 @@ site's `.env`), with the same rules and output, and its uploads count like any o
|
|
|
374
461
|
|
|
375
462
|
With the key, the site needs no submissions bucket and no Resend account. Set none of
|
|
376
463
|
`SUBMISSIONS_S3_BUCKET`, `SUBMISSIONS_S3_ACCESS_KEY_ID`, `SUBMISSIONS_S3_SECRET_ACCESS_KEY`,
|
|
377
|
-
`RESEND_API_KEY` or `FORMS_FROM
|
|
378
|
-
|
|
464
|
+
`RESEND_API_KEY` or `FORMS_FROM`. With `services: 'cloud'` they're ignored; on a site whose
|
|
465
|
+
config doesn't say, setting any of them beside the key is refused, at build and when the
|
|
466
|
+
server starts, with
|
|
379
467
|
|
|
380
468
|
> Set CARACMS_CLOUD_KEY or the site's own forms and email variables, not both: remove RESEND_API_KEY and FORMS_FROM.
|
|
381
469
|
|
|
@@ -406,8 +494,9 @@ them.
|
|
|
406
494
|
|
|
407
495
|
`caracms media push` copies everything under `uploads/` in the site's own bucket into its
|
|
408
496
|
CaraCMS Cloud folder, under the same keys, so the content doesn't change. It's the one
|
|
409
|
-
command that takes both credentials
|
|
410
|
-
|
|
497
|
+
command that takes both credentials. The old bucket's `S3_*` can stay in `.env` once the
|
|
498
|
+
config says `services: 'cloud'` (the running site ignores them); on a site whose config
|
|
499
|
+
doesn't say, give them on its command line instead (it refuses both):
|
|
411
500
|
|
|
412
501
|
```bash
|
|
413
502
|
S3_ENDPOINT=https://t3.storageapi.dev S3_REGION=auto S3_BUCKET=… S3_ACCESS_KEY_ID=… S3_SECRET_ACCESS_KEY=… npx caracms media push
|
|
@@ -423,8 +512,8 @@ CaraCMS to raise it, then run it again.
|
|
|
423
512
|
|
|
424
513
|
With the key, the site's clips are uploaded to CaraCMS Cloud's Mux and listed from the
|
|
425
514
|
site's own clips there; the editor works exactly as it does with a Mux account of your
|
|
426
|
-
own. Set neither `MUX_TOKEN_ID` nor `MUX_TOKEN_SECRET
|
|
427
|
-
refused with
|
|
515
|
+
own. Set neither `MUX_TOKEN_ID` nor `MUX_TOKEN_SECRET`. With `services: 'cloud'` they're
|
|
516
|
+
ignored; on a site whose config doesn't say, setting either beside the key is refused with
|
|
428
517
|
|
|
429
518
|
> Set CARACMS_CLOUD_KEY or the site's own Mux variables, not both: remove MUX_TOKEN_ID.
|
|
430
519
|
|
package/bin/caracms.mjs
CHANGED
|
@@ -31,7 +31,9 @@ import { createGate, describeClientIpSource, markProcessGated, parsePrelaunch, p
|
|
|
31
31
|
|
|
32
32
|
const USAGE = `Usage: caracms <command>, from the site's root
|
|
33
33
|
|
|
34
|
-
init [--write] [--railway]
|
|
34
|
+
init [--write] [--railway] [--cloud | --self-hosted]
|
|
35
|
+
Add caracms to an existing Astro site, and say where it runs (CaraCMS
|
|
36
|
+
Cloud or self-hosted). Shows the change; --write applies it.
|
|
35
37
|
schemas Write schemas/ from caracms.config.ts, and add $schema to content files.
|
|
36
38
|
validate [--fix] [--json] Check content against caracms.config.ts. --fix runs \`schemas\` first,
|
|
37
39
|
then lays content files out as the editor saves them;
|
|
@@ -180,10 +182,16 @@ async function main(argv) {
|
|
|
180
182
|
if (rest.length) return usage(`start takes no arguments.`);
|
|
181
183
|
return start();
|
|
182
184
|
case 'init': {
|
|
183
|
-
const f = flags('init', rest, ['--write', '--railway']);
|
|
185
|
+
const f = flags('init', rest, ['--write', '--railway', '--cloud', '--self-hosted']);
|
|
184
186
|
if (f.error) return usage(f.error);
|
|
185
187
|
const { run } = await import('./init.mjs');
|
|
186
|
-
process.exitCode = await run({
|
|
188
|
+
process.exitCode = await run({
|
|
189
|
+
root: process.cwd(),
|
|
190
|
+
write: f.set.has('--write'),
|
|
191
|
+
railway: f.set.has('--railway'),
|
|
192
|
+
cloud: f.set.has('--cloud'),
|
|
193
|
+
selfHosted: f.set.has('--self-hosted'),
|
|
194
|
+
});
|
|
187
195
|
return;
|
|
188
196
|
}
|
|
189
197
|
case 'schemas':
|