@cardinali-studio/adminkit 2.2.13 → 2.2.14
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/dist/persistence.js +20 -9
- package/package.json +1 -1
package/dist/persistence.js
CHANGED
|
@@ -304,8 +304,10 @@ export class D1ContentRepository {
|
|
|
304
304
|
.bind(input.releaseId, input.requestChecksum, input.manifestChecksum, input.schemaPackageVersion, input.materializerVersion, input.authorSubject, input.now, state.current_release_id, ...selected.flatMap((entry) => [entry.documentId, entry.revisionId]));
|
|
305
305
|
const statements = [candidate];
|
|
306
306
|
for (const [documentId, revisionId] of manifest)
|
|
307
|
-
statements.push(this.db.prepare(
|
|
308
|
-
|
|
307
|
+
statements.push(this.db.prepare(`INSERT INTO content_release_entries (release_id, document_id, revision_id)
|
|
308
|
+
SELECT ?, ?, ? WHERE EXISTS (SELECT 1 FROM content_releases WHERE release_id = ? AND status = 'publishing')
|
|
309
|
+
AND EXISTS (SELECT 1 FROM content_revisions WHERE document_id = ? AND revision_id = ?)`)
|
|
310
|
+
.bind(input.releaseId, documentId, revisionId, input.releaseId, documentId, revisionId));
|
|
309
311
|
const results = await this.db.batch(statements);
|
|
310
312
|
if (results[0]?.meta?.changes !== 1)
|
|
311
313
|
throw new Error("stale_revision");
|
|
@@ -362,14 +364,22 @@ export class D1ContentRepository {
|
|
|
362
364
|
}
|
|
363
365
|
const candidateIndex = statements.length;
|
|
364
366
|
statements.push(candidate);
|
|
367
|
+
/* Every dependent write is guarded by the exact candidate. D1 batches are
|
|
368
|
+
* atomic on SQL errors, but a guarded INSERT that affects zero rows is not
|
|
369
|
+
* an error: without this predicate, a busy lane made these FK inserts
|
|
370
|
+
* reference a candidate that was never created and hid the intended
|
|
371
|
+
* deployment_lane_busy conflict behind a generic persistence failure. */
|
|
365
372
|
for (const [documentId, revisionId] of manifest)
|
|
366
|
-
statements.push(this.db.prepare(
|
|
367
|
-
|
|
373
|
+
statements.push(this.db.prepare(`INSERT INTO content_release_entries (release_id, document_id, revision_id)
|
|
374
|
+
SELECT ?, ?, ? WHERE EXISTS (SELECT 1 FROM content_releases WHERE release_id = ? AND status = 'publishing')
|
|
375
|
+
AND EXISTS (SELECT 1 FROM content_revisions WHERE document_id = ? AND revision_id = ?)`)
|
|
376
|
+
.bind(input.releaseId, documentId, revisionId, input.releaseId, documentId, revisionId));
|
|
368
377
|
if (input.siteAccessVersionId)
|
|
369
378
|
statements.push(this.db.prepare(`INSERT INTO content_release_site_access (release_id, version_id)
|
|
370
|
-
SELECT ?, ? WHERE EXISTS (SELECT 1 FROM
|
|
371
|
-
|
|
372
|
-
|
|
379
|
+
SELECT ?, ? WHERE EXISTS (SELECT 1 FROM content_releases WHERE release_id = ? AND status = 'publishing')
|
|
380
|
+
AND EXISTS (SELECT 1 FROM site_access_versions version JOIN site_access_state access_state ON access_state.singleton = 1
|
|
381
|
+
WHERE version.version_id = ? AND version.state IN ('draft','active') AND version.version_id IN (access_state.draft_version_id, access_state.active_version_id))`)
|
|
382
|
+
.bind(input.releaseId, input.siteAccessVersionId, input.releaseId, input.siteAccessVersionId));
|
|
373
383
|
for (const operationId of mediaOperationIds) {
|
|
374
384
|
/* `instr` is intentionally evaluated against the frozen release entries,
|
|
375
385
|
* not drafts or a mutable current pointer. A URL is JSON-escaped neither
|
|
@@ -384,8 +394,9 @@ export class D1ContentRepository {
|
|
|
384
394
|
AND revision.payload_json IS NOT NULL AND instr(revision.payload_json, '/media/' || source.source_key) > 0)`)
|
|
385
395
|
.bind(input.now, operationId, input.releaseId));
|
|
386
396
|
statements.push(this.db.prepare(`INSERT INTO content_release_media_operations (release_id, operation_id)
|
|
387
|
-
SELECT ?, ? WHERE EXISTS (SELECT 1 FROM
|
|
388
|
-
|
|
397
|
+
SELECT ?, ? WHERE EXISTS (SELECT 1 FROM content_releases WHERE release_id = ? AND status = 'publishing')
|
|
398
|
+
AND EXISTS (SELECT 1 FROM media_operations WHERE operation_id = ? AND state = 'bound')`)
|
|
399
|
+
.bind(input.releaseId, operationId, input.releaseId, operationId));
|
|
389
400
|
}
|
|
390
401
|
statements.push(this.db.prepare(`INSERT INTO production_deployment_attempts
|
|
391
402
|
(attempt_id, intent_kind, requested_release_id, requested_code_sha, code_sha, release_id, expected_fingerprint, phase, active_slot, created_at, updated_at)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardinali-studio/adminkit",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Motore riusabile di un pannello di amministrazione per siti Hugo su Cloudflare Pages: codec del front matter guidato dallo schema, form React, libreria media su R2. NIENTE di specifico di un sito qui dentro.",
|
|
6
6
|
"license": "UNLICENSED",
|