CMS / foldkit-cms-drizzle

Publishing

CmsPublish runs your handler with the draft's value: create when the entry has no row, update, with the row's id added, when it has. Around it, in one transaction: the published column is set if it was empty, the revision is appended, the draft is removed, and the entry is told its row. A handler that fails after writing leaves nothing behind.

  • Every operation is one transaction, not only a publish: a save that made an entry and could not make its draft leaves neither.
  • You name the transaction, because Drizzle's differ by driver. Transaction.statements is begin and commit as statements, for a database that is one connection (a SQLite file). Transaction.drizzle is database.transaction, for a driver whose transactions are asynchronous (Postgres, libSQL); your handlers then get the transaction as their DrizzleDatabase. Statements over a pool would not roll back.
  • One connection holds one transaction, so under Transaction.statements this package's operations take turns at the database. Without that, a save arriving while a publish is failing would be rolled back with it, after it was reported done. A write of your own on the same connection does not take a turn unless you make it inside Transaction.statements too.
  • A publish names the revision it was made from (basedOn, the entry's revision, or null). A newer one is refused with Cms.refusal.conflict, not a publish over someone else's. The entry's revision is compared and set first, inside the transaction, so of two publishes made from one revision one writes nothing.
  • A draft your mutation's Input refuses is not published, and the error says why. The draft is kept.
  • A row that is already shown keeps the date it was first published on.
  • The row as your handler left it goes to the client with the entry and the revision, every column of it, so a handler need not patch what it wrote. What your handler returns (patches, connection changes, deletions) goes too.

Slugs

A content type with a slug role is found by it: cms.queries has Cms.bySlug(Posts), behind the same visible rule as every other read, so a visitor does not find what is not published.

A publish to a slug another row has is refused with Cms.refusal.field('slug', 'That address is taken: "hello" is already used'), which names the form key to show it on; a client reads it with Data.refusal. The check is advice; a unique index is the rule. Two publishes can both pass the check, and the one the index refuses gets the same error. Without a unique index on the column, that race publishes two rows at one address. The slug is read from the publish input's member of the same key as the Entity's.

Unpublishing

CmsUnpublish empties the published column. The row and its revisions are kept; a visitor stops seeing it, by every path, and publishing shows it again. Only a type with a published role offers it.