canopycms 0.0.32 → 0.0.34
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/api/__test__/mock-client.d.ts.map +1 -1
- package/dist/api/__test__/mock-client.js.map +1 -1
- package/dist/api/branch-review.d.ts +1 -10
- package/dist/api/branch-review.d.ts.map +1 -1
- package/dist/api/branch-review.js +4 -11
- package/dist/api/branch-review.js.map +1 -1
- package/dist/api/branch-status.d.ts +1 -7
- package/dist/api/branch-status.d.ts.map +1 -1
- package/dist/api/branch-status.js +1 -8
- package/dist/api/branch-status.js.map +1 -1
- package/dist/api/branch-withdraw.d.ts.map +1 -1
- package/dist/api/branch-withdraw.js +1 -5
- package/dist/api/branch-withdraw.js.map +1 -1
- package/dist/api/branch.d.ts +1 -11
- package/dist/api/branch.d.ts.map +1 -1
- package/dist/api/branch.js +1 -4
- package/dist/api/branch.js.map +1 -1
- package/dist/api/client.d.ts +1 -2
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +2 -2
- package/dist/api/client.js.map +1 -1
- package/dist/api/comments.d.ts.map +1 -1
- package/dist/api/comments.js +2 -5
- package/dist/api/comments.js.map +1 -1
- package/dist/api/content.d.ts +9 -0
- package/dist/api/content.d.ts.map +1 -1
- package/dist/api/content.js +20 -3
- package/dist/api/content.js.map +1 -1
- package/dist/api/groups.js +1 -1
- package/dist/api/groups.js.map +1 -1
- package/dist/api/permissions.js +1 -1
- package/dist/api/permissions.js.map +1 -1
- package/dist/api/reference-options.d.ts.map +1 -1
- package/dist/api/reference-options.js +12 -1
- package/dist/api/reference-options.js.map +1 -1
- package/dist/api/resolve-references.d.ts.map +1 -1
- package/dist/api/resolve-references.js +5 -0
- package/dist/api/resolve-references.js.map +1 -1
- package/dist/api/validators.d.ts +15 -0
- package/dist/api/validators.d.ts.map +1 -1
- package/dist/api/validators.js +7 -0
- package/dist/api/validators.js.map +1 -1
- package/dist/asset-store.d.ts.map +1 -1
- package/dist/asset-store.js +4 -3
- package/dist/asset-store.js.map +1 -1
- package/dist/branch-metadata.d.ts.map +1 -1
- package/dist/branch-metadata.js +13 -23
- package/dist/branch-metadata.js.map +1 -1
- package/dist/cli/generate-ai-content.js +144 -110
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +88 -48
- package/dist/cli/init.js.map +1 -1
- package/dist/content-store.d.ts +12 -0
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +160 -106
- package/dist/content-store.js.map +1 -1
- package/dist/editor/Editor.d.ts.map +1 -1
- package/dist/editor/Editor.js +3 -3
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/FormRenderer.d.ts.map +1 -1
- package/dist/editor/FormRenderer.js +1 -0
- package/dist/editor/FormRenderer.js.map +1 -1
- package/dist/editor/fields/BlockField.d.ts.map +1 -1
- package/dist/editor/fields/BlockField.js +1 -0
- package/dist/editor/fields/BlockField.js.map +1 -1
- package/dist/editor/fields/MarkdownField.d.ts.map +1 -1
- package/dist/editor/fields/MarkdownField.js +1 -0
- package/dist/editor/fields/MarkdownField.js.map +1 -1
- package/dist/editor/fields/ReferenceField.d.ts.map +1 -1
- package/dist/editor/fields/ReferenceField.js +1 -0
- package/dist/editor/fields/ReferenceField.js.map +1 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.d.ts +0 -6
- package/dist/editor/fields/entry-link/EntryLinkContext.d.ts.map +1 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.js +1 -0
- package/dist/editor/fields/entry-link/EntryLinkContext.js.map +1 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts.map +1 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -0
- package/dist/editor/fields/entry-link/InsertEntryLink.js.map +1 -1
- package/dist/editor/hooks/useBranchActions.d.ts +2 -2
- package/dist/editor/hooks/useBranchActions.d.ts.map +1 -1
- package/dist/editor/hooks/useBranchActions.js +2 -2
- package/dist/editor/hooks/useBranchActions.js.map +1 -1
- package/dist/editor/hooks/useBranchManager.d.ts.map +1 -1
- package/dist/editor/hooks/useBranchManager.js +2 -1
- package/dist/editor/hooks/useBranchManager.js.map +1 -1
- package/dist/editor/hooks/useDraftManager.d.ts +1 -0
- package/dist/editor/hooks/useDraftManager.d.ts.map +1 -1
- package/dist/editor/hooks/useDraftManager.js +31 -4
- package/dist/editor/hooks/useDraftManager.js.map +1 -1
- package/dist/editor/hooks/useEntryManager.d.ts +5 -0
- package/dist/editor/hooks/useEntryManager.d.ts.map +1 -1
- package/dist/editor/hooks/useEntryManager.js +29 -2
- package/dist/editor/hooks/useEntryManager.js.map +1 -1
- package/dist/editor/hooks/useUserContext.d.ts.map +1 -1
- package/dist/editor/hooks/useUserContext.js +1 -0
- package/dist/editor/hooks/useUserContext.js.map +1 -1
- package/dist/schema/meta-loader.d.ts.map +1 -1
- package/dist/schema/meta-loader.js +2 -0
- package/dist/schema/meta-loader.js.map +1 -1
- package/dist/schema/schema-store.d.ts.map +1 -1
- package/dist/schema/schema-store.js +3 -2
- package/dist/schema/schema-store.js.map +1 -1
- package/dist/task-queue/task-queue.d.ts.map +1 -1
- package/dist/task-queue/task-queue.js +23 -21
- package/dist/task-queue/task-queue.js.map +1 -1
- package/dist/utils/async-mutex.d.ts +2 -0
- package/dist/utils/async-mutex.d.ts.map +1 -0
- package/dist/utils/async-mutex.js +28 -0
- package/dist/utils/async-mutex.js.map +1 -0
- package/dist/utils/atomic-write.d.ts +2 -2
- package/dist/utils/atomic-write.d.ts.map +1 -1
- package/dist/utils/atomic-write.js +2 -2
- package/dist/utils/atomic-write.js.map +1 -1
- package/dist/validation/deletion-checker.d.ts.map +1 -1
- package/dist/validation/deletion-checker.js +13 -17
- package/dist/validation/deletion-checker.js.map +1 -1
- package/dist/validation/field-traversal.d.ts.map +1 -1
- package/dist/validation/field-traversal.js +12 -2
- package/dist/validation/field-traversal.js.map +1 -1
- package/package.json +1 -1
- package/dist/settings-branch-utils.d.ts +0 -21
- package/dist/settings-branch-utils.d.ts.map +0 -1
- package/dist/settings-branch-utils.js +0 -33
- package/dist/settings-branch-utils.js.map +0 -1
|
@@ -711,7 +711,7 @@ async function atomicWriteFile(filePath, content) {
|
|
|
711
711
|
const dir = path.dirname(filePath);
|
|
712
712
|
await fs.mkdir(dir, { recursive: true });
|
|
713
713
|
const tempPath = `${filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
714
|
-
await fs.writeFile(tempPath, content, "utf-8");
|
|
714
|
+
await fs.writeFile(tempPath, content, typeof content === "string" ? "utf-8" : void 0);
|
|
715
715
|
try {
|
|
716
716
|
await fs.rename(tempPath, filePath);
|
|
717
717
|
} catch (err) {
|
|
@@ -721,6 +721,25 @@ async function atomicWriteFile(filePath, content) {
|
|
|
721
721
|
}
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
+
// dist/utils/async-mutex.js
|
|
725
|
+
var locks = /* @__PURE__ */ new Map();
|
|
726
|
+
async function withLock(key, fn) {
|
|
727
|
+
const prev = locks.get(key) ?? Promise.resolve();
|
|
728
|
+
let resolve;
|
|
729
|
+
const next = new Promise((r) => {
|
|
730
|
+
resolve = r;
|
|
731
|
+
});
|
|
732
|
+
locks.set(key, next);
|
|
733
|
+
await prev;
|
|
734
|
+
try {
|
|
735
|
+
return await fn();
|
|
736
|
+
} finally {
|
|
737
|
+
resolve();
|
|
738
|
+
if (locks.get(key) === next)
|
|
739
|
+
locks.delete(key);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
724
743
|
// dist/utils/body-field.js
|
|
725
744
|
function findBodyFieldName(fields) {
|
|
726
745
|
for (const field of fields) {
|
|
@@ -1160,6 +1179,12 @@ var ContentStoreError = class extends Error {
|
|
|
1160
1179
|
this.code = code;
|
|
1161
1180
|
}
|
|
1162
1181
|
};
|
|
1182
|
+
var ContentConflictError = class extends Error {
|
|
1183
|
+
constructor() {
|
|
1184
|
+
super("Content was modified by another editor");
|
|
1185
|
+
this.name = "ContentConflictError";
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1163
1188
|
function getDefaultEntryType(entries) {
|
|
1164
1189
|
if (!entries || entries.length === 0)
|
|
1165
1190
|
return void 0;
|
|
@@ -1337,6 +1362,7 @@ var ContentStore = class {
|
|
|
1337
1362
|
async read(collectionPath, slug = "", options = {}) {
|
|
1338
1363
|
const schemaItem = this.assertSchemaItem(collectionPath);
|
|
1339
1364
|
const { absolutePath, relativePath, entryTypeName: resolvedEntryTypeName } = await this.buildPaths(schemaItem, slug);
|
|
1365
|
+
const stat = await fs4.stat(absolutePath);
|
|
1340
1366
|
const raw = await fs4.readFile(absolutePath, "utf8");
|
|
1341
1367
|
let doc;
|
|
1342
1368
|
let format;
|
|
@@ -1391,6 +1417,7 @@ var ContentStore = class {
|
|
|
1391
1417
|
if (options.resolveReferences !== false) {
|
|
1392
1418
|
doc.data = await this.resolveReferencesInData(doc.data, fields);
|
|
1393
1419
|
}
|
|
1420
|
+
doc.version = stat.mtimeMs;
|
|
1394
1421
|
return doc;
|
|
1395
1422
|
}
|
|
1396
1423
|
async write(collectionPath, slug = "", input, entryTypeName) {
|
|
@@ -1420,64 +1447,70 @@ var ContentStore = class {
|
|
|
1420
1447
|
const { absolutePath, relativePath, id } = await this.buildPaths(schemaItem, slug, {
|
|
1421
1448
|
entryTypeName
|
|
1422
1449
|
});
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
if (
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1450
|
+
return withLock(absolutePath, async () => {
|
|
1451
|
+
await fs4.mkdir(path5.dirname(absolutePath), { recursive: true });
|
|
1452
|
+
if (input.expectedVersion !== void 0) {
|
|
1453
|
+
try {
|
|
1454
|
+
const existing = await fs4.stat(absolutePath);
|
|
1455
|
+
if (existing.mtimeMs !== input.expectedVersion) {
|
|
1456
|
+
throw new ContentConflictError();
|
|
1457
|
+
}
|
|
1458
|
+
} catch (err) {
|
|
1459
|
+
if (err instanceof ContentConflictError)
|
|
1460
|
+
throw err;
|
|
1461
|
+
if (isNodeError(err) && err.code === "ENOENT") {
|
|
1462
|
+
} else {
|
|
1463
|
+
throw err;
|
|
1464
|
+
}
|
|
1431
1465
|
}
|
|
1466
|
+
}
|
|
1467
|
+
let content;
|
|
1468
|
+
if (input.format === "json") {
|
|
1469
|
+
content = `${JSON.stringify(input.data ?? {}, null, 2)}
|
|
1470
|
+
`;
|
|
1471
|
+
} else if (input.format === "yaml") {
|
|
1472
|
+
content = yamlStringify(input.data ?? {});
|
|
1432
1473
|
} else {
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1474
|
+
content = matter.stringify(input.body, input.data ?? {});
|
|
1475
|
+
}
|
|
1476
|
+
await atomicWriteFile(absolutePath, content);
|
|
1477
|
+
if (id) {
|
|
1478
|
+
const existing = idIndex.findById(id);
|
|
1479
|
+
if (existing) {
|
|
1480
|
+
if (existing.relativePath !== relativePath) {
|
|
1481
|
+
idIndex.updatePath(existing.id, relativePath);
|
|
1482
|
+
}
|
|
1483
|
+
} else {
|
|
1484
|
+
idIndex.add({
|
|
1485
|
+
type: "entry",
|
|
1486
|
+
relativePath,
|
|
1487
|
+
collection: collectionPath,
|
|
1488
|
+
slug: slug || void 0
|
|
1489
|
+
});
|
|
1490
|
+
}
|
|
1439
1491
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
const json = JSON.stringify(input.data ?? {}, null, 2);
|
|
1443
|
-
await atomicWriteFile(absolutePath, `${json}
|
|
1444
|
-
`);
|
|
1445
|
-
updateIdIndex();
|
|
1446
|
-
return {
|
|
1492
|
+
const afterStat = await fs4.stat(absolutePath);
|
|
1493
|
+
const base = {
|
|
1447
1494
|
collection: schemaItem.logicalPath,
|
|
1448
1495
|
collectionName: schemaItem.name,
|
|
1449
|
-
format: "json",
|
|
1450
|
-
data: input.data ?? {},
|
|
1451
1496
|
relativePath,
|
|
1452
|
-
absolutePath
|
|
1497
|
+
absolutePath,
|
|
1498
|
+
version: afterStat.mtimeMs
|
|
1453
1499
|
};
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1500
|
+
if (input.format === "json") {
|
|
1501
|
+
return { ...base, format: "json", data: input.data ?? {} };
|
|
1502
|
+
}
|
|
1503
|
+
if (input.format === "yaml") {
|
|
1504
|
+
return { ...base, format: "yaml", data: input.data ?? {} };
|
|
1505
|
+
}
|
|
1459
1506
|
return {
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
format: "yaml",
|
|
1507
|
+
...base,
|
|
1508
|
+
format: input.format,
|
|
1463
1509
|
data: input.data ?? {},
|
|
1464
|
-
|
|
1465
|
-
|
|
1510
|
+
body: input.body,
|
|
1511
|
+
bodyFieldName: findBodyFieldName(fields)
|
|
1466
1512
|
};
|
|
1467
|
-
}
|
|
1468
|
-
const file = matter.stringify(input.body, input.data ?? {});
|
|
1469
|
-
await atomicWriteFile(absolutePath, file);
|
|
1470
|
-
updateIdIndex();
|
|
1471
|
-
return {
|
|
1472
|
-
collection: schemaItem.logicalPath,
|
|
1473
|
-
collectionName: schemaItem.name,
|
|
1474
|
-
format: input.format,
|
|
1475
|
-
data: input.data ?? {},
|
|
1476
|
-
body: input.body,
|
|
1477
|
-
bodyFieldName: findBodyFieldName(fields),
|
|
1478
|
-
relativePath,
|
|
1479
|
-
absolutePath
|
|
1480
|
-
};
|
|
1513
|
+
});
|
|
1481
1514
|
}
|
|
1482
1515
|
/**
|
|
1483
1516
|
* Read an entry by its ID (UUID).
|
|
@@ -1506,11 +1539,13 @@ var ContentStore = class {
|
|
|
1506
1539
|
const idIndex = await this.idIndex();
|
|
1507
1540
|
const collection = this.assertCollection(collectionPath);
|
|
1508
1541
|
const { absolutePath, relativePath } = await this.buildPaths(collection, slug);
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1542
|
+
return withLock(absolutePath, async () => {
|
|
1543
|
+
const id = idIndex.findByPath(relativePath);
|
|
1544
|
+
await fs4.unlink(absolutePath);
|
|
1545
|
+
if (id) {
|
|
1546
|
+
idIndex.remove(id);
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1514
1549
|
}
|
|
1515
1550
|
/**
|
|
1516
1551
|
* Rename an entry by changing its slug (middle segment of filename).
|
|
@@ -1530,49 +1565,57 @@ var ContentStore = class {
|
|
|
1530
1565
|
if (!safeNewSlug) {
|
|
1531
1566
|
throw new ContentStoreError("New slug cannot be empty", "VALIDATION");
|
|
1532
1567
|
}
|
|
1533
|
-
const { absolutePath: currentPath, relativePath: currentRelPath } = await this.buildPaths(collection, currentSlug);
|
|
1534
|
-
try {
|
|
1535
|
-
await fs4.access(currentPath);
|
|
1536
|
-
} catch {
|
|
1537
|
-
throw new ContentStoreError(`Entry not found: ${currentSlug}`, "NOT_FOUND");
|
|
1538
|
-
}
|
|
1539
1568
|
if (currentSlug === safeNewSlug) {
|
|
1540
1569
|
return { newPath: `${collectionPath}/${currentSlug}` };
|
|
1541
1570
|
}
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
const
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1571
|
+
const { absolutePath: currentPath, relativePath: currentRelPath } = await this.buildPaths(collection, currentSlug);
|
|
1572
|
+
return withLock(currentPath, async () => {
|
|
1573
|
+
try {
|
|
1574
|
+
await fs4.access(currentPath);
|
|
1575
|
+
} catch {
|
|
1576
|
+
throw new ContentStoreError(`Entry not found: ${currentSlug}`, "NOT_FOUND");
|
|
1577
|
+
}
|
|
1578
|
+
const currentFilename = path5.basename(currentPath);
|
|
1579
|
+
const parts = currentFilename.split(".");
|
|
1580
|
+
if (parts.length < 4) {
|
|
1581
|
+
throw new ContentStoreError(`Invalid entry filename format: ${currentFilename}`, "VALIDATION");
|
|
1582
|
+
}
|
|
1583
|
+
const entryTypeName = parts[0];
|
|
1584
|
+
const contentId = parts[parts.length - 2];
|
|
1585
|
+
const ext = `.${parts[parts.length - 1]}`;
|
|
1586
|
+
const newFilename = `${entryTypeName}.${safeNewSlug}.${contentId}${ext}`;
|
|
1587
|
+
const parentDir = path5.dirname(currentPath);
|
|
1588
|
+
const newPath = path5.join(parentDir, newFilename);
|
|
1589
|
+
try {
|
|
1590
|
+
const entries = await fs4.readdir(parentDir, { withFileTypes: true });
|
|
1591
|
+
for (const entry of entries) {
|
|
1592
|
+
if (entry.isDirectory())
|
|
1593
|
+
continue;
|
|
1594
|
+
const existingSlug = extractSlugFromFilename(entry.name, entryTypeName);
|
|
1595
|
+
if (existingSlug === safeNewSlug) {
|
|
1596
|
+
throw new ContentStoreError(`Entry with slug "${safeNewSlug}" already exists in collection "${collectionPath}"`, "VALIDATION");
|
|
1597
|
+
}
|
|
1561
1598
|
}
|
|
1599
|
+
} catch (err) {
|
|
1600
|
+
if (err instanceof ContentStoreError)
|
|
1601
|
+
throw err;
|
|
1562
1602
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1603
|
+
try {
|
|
1604
|
+
await fs4.link(currentPath, newPath);
|
|
1605
|
+
} catch (err) {
|
|
1606
|
+
if (isNodeError(err) && err.code === "EEXIST") {
|
|
1607
|
+
throw new ContentStoreError(`Entry with slug "${safeNewSlug}" already exists in collection "${collectionPath}"`, "VALIDATION");
|
|
1608
|
+
}
|
|
1565
1609
|
throw err;
|
|
1566
1610
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return { newPath: newLogicalPath };
|
|
1611
|
+
await fs4.unlink(currentPath);
|
|
1612
|
+
const newRelativePath = path5.relative(this.root, newPath);
|
|
1613
|
+
const entryId = idIndex.findByPath(currentRelPath);
|
|
1614
|
+
if (entryId) {
|
|
1615
|
+
idIndex.updatePath(entryId, newRelativePath);
|
|
1616
|
+
}
|
|
1617
|
+
return { newPath: `${collectionPath}/${safeNewSlug}` };
|
|
1618
|
+
});
|
|
1576
1619
|
}
|
|
1577
1620
|
/**
|
|
1578
1621
|
* List all entries in a collection tree (including subcollections).
|
|
@@ -1697,12 +1740,14 @@ var entryTypeMetaSchema = z6.object({
|
|
|
1697
1740
|
schema: z6.string().min(1),
|
|
1698
1741
|
// Entry schema registry key (validated at resolution time)
|
|
1699
1742
|
label: z6.string().optional(),
|
|
1743
|
+
description: z6.string().optional(),
|
|
1700
1744
|
default: z6.boolean().optional(),
|
|
1701
1745
|
maxItems: z6.number().int().positive().optional()
|
|
1702
1746
|
});
|
|
1703
1747
|
var collectionMetaSchema = z6.object({
|
|
1704
1748
|
name: z6.string().min(1),
|
|
1705
1749
|
label: z6.string().optional(),
|
|
1750
|
+
description: z6.string().optional(),
|
|
1706
1751
|
entries: z6.array(entryTypeMetaSchema).optional(),
|
|
1707
1752
|
order: z6.array(z6.string())
|
|
1708
1753
|
// Embedded IDs for ordering items (required)
|
|
@@ -3007,23 +3052,6 @@ var BranchMetadataConflictError = class extends Error {
|
|
|
3007
3052
|
this.name = "BranchMetadataConflictError";
|
|
3008
3053
|
}
|
|
3009
3054
|
};
|
|
3010
|
-
var fileLocks = /* @__PURE__ */ new Map();
|
|
3011
|
-
async function withFileLock(filePath, fn) {
|
|
3012
|
-
while (fileLocks.has(filePath)) {
|
|
3013
|
-
await fileLocks.get(filePath);
|
|
3014
|
-
}
|
|
3015
|
-
let resolve;
|
|
3016
|
-
const lockPromise = new Promise((r) => {
|
|
3017
|
-
resolve = r;
|
|
3018
|
-
});
|
|
3019
|
-
fileLocks.set(filePath, lockPromise);
|
|
3020
|
-
try {
|
|
3021
|
-
return await fn();
|
|
3022
|
-
} finally {
|
|
3023
|
-
fileLocks.delete(filePath);
|
|
3024
|
-
resolve();
|
|
3025
|
-
}
|
|
3026
|
-
}
|
|
3027
3055
|
var BranchMetadataFileManager = class _BranchMetadataFileManager {
|
|
3028
3056
|
constructor(branchRoot, baseRoot) {
|
|
3029
3057
|
this.branchRoot = path9.resolve(branchRoot);
|
|
@@ -3082,15 +3110,21 @@ var BranchMetadataFileManager = class _BranchMetadataFileManager {
|
|
|
3082
3110
|
await fs8.mkdir(path9.dirname(this.filePath), { recursive: true });
|
|
3083
3111
|
const content = JSON.stringify(payload, null, 2) + "\n";
|
|
3084
3112
|
if (expectedVersion === null) {
|
|
3113
|
+
const tempPath2 = `${this.filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
3114
|
+
await fs8.writeFile(tempPath2, content, "utf-8");
|
|
3085
3115
|
try {
|
|
3086
|
-
await fs8.
|
|
3087
|
-
return { version: newVersion, writeId };
|
|
3116
|
+
await fs8.link(tempPath2, this.filePath);
|
|
3088
3117
|
} catch (err) {
|
|
3118
|
+
await fs8.unlink(tempPath2).catch(() => {
|
|
3119
|
+
});
|
|
3089
3120
|
if (isFileExistsError(err)) {
|
|
3090
3121
|
throw new BranchMetadataConflictError();
|
|
3091
3122
|
}
|
|
3092
3123
|
throw err;
|
|
3093
3124
|
}
|
|
3125
|
+
await fs8.unlink(tempPath2).catch(() => {
|
|
3126
|
+
});
|
|
3127
|
+
return { version: newVersion, writeId };
|
|
3094
3128
|
}
|
|
3095
3129
|
const tempPath = `${this.filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
3096
3130
|
await fs8.writeFile(tempPath, content, "utf-8");
|
|
@@ -3134,7 +3168,7 @@ var BranchMetadataFileManager = class _BranchMetadataFileManager {
|
|
|
3134
3168
|
throw new Error("Unreachable");
|
|
3135
3169
|
}
|
|
3136
3170
|
async save(incoming) {
|
|
3137
|
-
return
|
|
3171
|
+
return withLock(this.filePath, () => this.withRetry(async () => {
|
|
3138
3172
|
const { meta: existing, version } = await this.load();
|
|
3139
3173
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3140
3174
|
const defaults = {
|
package/dist/cli/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAIhD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,CAAA;AAE1C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,KAAK,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;IACd,cAAc,EAAE,OAAO,CAAA;IACvB,EAAE,EAAE,OAAO,CAAA;IACX,4CAA4C;IAC5C,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,UAAU,iBAAiB;IACzB,KAAK,EAAE,KAAK,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;IACd,cAAc,EAAE,OAAO,CAAA;CACxB;AA+CD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqI9D;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2C7E;AAmED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEhB"}
|
package/dist/cli/init.js
CHANGED
|
@@ -519,7 +519,7 @@ async function atomicWriteFile(filePath, content) {
|
|
|
519
519
|
const dir = path4.dirname(filePath);
|
|
520
520
|
await fs3.mkdir(dir, { recursive: true });
|
|
521
521
|
const tempPath = `${filePath}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
522
|
-
await fs3.writeFile(tempPath, content, "utf-8");
|
|
522
|
+
await fs3.writeFile(tempPath, content, typeof content === "string" ? "utf-8" : void 0);
|
|
523
523
|
try {
|
|
524
524
|
await fs3.rename(tempPath, filePath);
|
|
525
525
|
} catch (err) {
|
|
@@ -572,18 +572,18 @@ async function dequeueTask(taskDir, logger = nullLogger) {
|
|
|
572
572
|
return null;
|
|
573
573
|
const now = Date.now();
|
|
574
574
|
const tasks = [];
|
|
575
|
-
for (const
|
|
575
|
+
for (const fileName of jsonFiles) {
|
|
576
576
|
try {
|
|
577
|
-
const content = await fs4.readFile(path5.join(pendingDir,
|
|
578
|
-
const
|
|
579
|
-
if (!
|
|
580
|
-
await moveToCorrupt(taskDir, pendingDir,
|
|
577
|
+
const content = await fs4.readFile(path5.join(pendingDir, fileName), "utf-8");
|
|
578
|
+
const task = parseTaskJson(content);
|
|
579
|
+
if (!task) {
|
|
580
|
+
await moveToCorrupt(taskDir, pendingDir, fileName, "Invalid JSON", logger);
|
|
581
581
|
continue;
|
|
582
582
|
}
|
|
583
|
-
if (
|
|
583
|
+
if (task.retryAfter && new Date(task.retryAfter).getTime() > now) {
|
|
584
584
|
continue;
|
|
585
585
|
}
|
|
586
|
-
tasks.push({ fileName
|
|
586
|
+
tasks.push({ fileName, task });
|
|
587
587
|
} catch (err) {
|
|
588
588
|
if (isNotFoundError2(err))
|
|
589
589
|
continue;
|
|
@@ -593,26 +593,28 @@ async function dequeueTask(taskDir, logger = nullLogger) {
|
|
|
593
593
|
if (tasks.length === 0)
|
|
594
594
|
return null;
|
|
595
595
|
tasks.sort((a, b) => a.task.createdAt.localeCompare(b.task.createdAt) || a.task.id.localeCompare(b.task.id));
|
|
596
|
-
const { fileName, task }
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
596
|
+
for (const { fileName, task } of tasks) {
|
|
597
|
+
if (await taskExistsIn(taskDir, task.id, ["completed", "failed"])) {
|
|
598
|
+
await fs4.unlink(path5.join(pendingDir, fileName)).catch(() => {
|
|
599
|
+
});
|
|
600
|
+
logger.debug("Skipped already-finished task", { id: task.id });
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
const sourcePath = path5.join(pendingDir, fileName);
|
|
604
|
+
const destPath = path5.join(processingDir, fileName);
|
|
605
|
+
try {
|
|
606
|
+
task.status = "processing";
|
|
607
|
+
await atomicWriteFile(destPath, JSON.stringify(task, null, 2));
|
|
608
|
+
await fs4.unlink(sourcePath);
|
|
609
|
+
logger.debug("Dequeued task", { id: task.id, action: task.action });
|
|
610
|
+
return task;
|
|
611
|
+
} catch (err) {
|
|
612
|
+
if (isNotFoundError2(err))
|
|
613
|
+
continue;
|
|
614
|
+
throw err;
|
|
615
|
+
}
|
|
615
616
|
}
|
|
617
|
+
return null;
|
|
616
618
|
}
|
|
617
619
|
async function completeTask(taskDir, taskId, result, logger = nullLogger) {
|
|
618
620
|
const processingPath = path5.join(taskDir, "processing", `${taskId}.json`);
|
|
@@ -916,6 +918,7 @@ var init_task_queue3 = __esm({
|
|
|
916
918
|
import fs5 from "node:fs/promises";
|
|
917
919
|
import path6 from "node:path";
|
|
918
920
|
import * as p from "@clack/prompts";
|
|
921
|
+
import { createJiti } from "jiti";
|
|
919
922
|
|
|
920
923
|
// dist/operating-mode/client-safe-strategy.js
|
|
921
924
|
var ProdClientSafeStrategy = class {
|
|
@@ -1120,6 +1123,15 @@ function operatingStrategy(mode) {
|
|
|
1120
1123
|
import fs from "node:fs/promises";
|
|
1121
1124
|
|
|
1122
1125
|
// dist/utils/error.js
|
|
1126
|
+
function getErrorMessage(err) {
|
|
1127
|
+
if (err instanceof Error) {
|
|
1128
|
+
return err.message;
|
|
1129
|
+
}
|
|
1130
|
+
if (typeof err === "string") {
|
|
1131
|
+
return err;
|
|
1132
|
+
}
|
|
1133
|
+
return String(err);
|
|
1134
|
+
}
|
|
1123
1135
|
function isNodeError(err) {
|
|
1124
1136
|
return err instanceof Error && "code" in err;
|
|
1125
1137
|
}
|
|
@@ -1267,17 +1279,36 @@ async function initDeployAws(options) {
|
|
|
1267
1279
|
p.note("CDK constructs are available via the canopycms-cdk package.\nSee the deployment plan for CDK stack setup.", "AWS deployment");
|
|
1268
1280
|
p.outro("Done!");
|
|
1269
1281
|
}
|
|
1270
|
-
async function
|
|
1271
|
-
const
|
|
1272
|
-
const cfgPath = path6.join(options.projectDir, "canopycms.config.ts");
|
|
1273
|
-
let mode = "dev";
|
|
1282
|
+
async function detectMode(projectDir) {
|
|
1283
|
+
const cfgPath = path6.join(projectDir, "canopycms.config.ts");
|
|
1274
1284
|
try {
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1285
|
+
await fs5.stat(cfgPath);
|
|
1286
|
+
} catch (err) {
|
|
1287
|
+
if (isNotFoundError(err))
|
|
1288
|
+
return "dev";
|
|
1289
|
+
throw err;
|
|
1290
|
+
}
|
|
1291
|
+
const jiti = createJiti(import.meta.url);
|
|
1292
|
+
let configModule;
|
|
1293
|
+
try {
|
|
1294
|
+
configModule = await jiti.import(cfgPath);
|
|
1295
|
+
} catch (err) {
|
|
1296
|
+
throw new Error(`Failed to load CanopyCMS config at ${cfgPath}: ${getErrorMessage(err)}. Refusing to default to dev mode \u2014 a broken config in a prod deployment would cause the worker-run-once prod-safety guard to silently skip prod tasks.`);
|
|
1297
|
+
}
|
|
1298
|
+
const configExport = configModule.default ?? configModule.config ?? configModule;
|
|
1299
|
+
const serverConfig = typeof configExport === "object" && configExport !== null && "server" in configExport ? configExport.server : configExport;
|
|
1300
|
+
if (!serverConfig || typeof serverConfig !== "object" || !("mode" in serverConfig) || typeof serverConfig.mode !== "string") {
|
|
1301
|
+
throw new Error(`Invalid CanopyCMS config at ${cfgPath}: expected server.mode to be a string. Make sure the config uses defineCanopyConfig() with a valid mode.`);
|
|
1280
1302
|
}
|
|
1303
|
+
const mode = serverConfig.mode;
|
|
1304
|
+
if (mode !== "prod" && mode !== "dev") {
|
|
1305
|
+
throw new Error(`Invalid CanopyCMS config at ${cfgPath}: mode must be 'prod' or 'dev', got '${mode}'.`);
|
|
1306
|
+
}
|
|
1307
|
+
return mode;
|
|
1308
|
+
}
|
|
1309
|
+
async function workerRunOnce(options) {
|
|
1310
|
+
const { getTaskQueueDir: getTaskQueueDir2 } = await Promise.resolve().then(() => (init_task_queue_config(), task_queue_config_exports));
|
|
1311
|
+
const mode = await detectMode(options.projectDir);
|
|
1281
1312
|
const taskDir = getTaskQueueDir2({ mode });
|
|
1282
1313
|
const cachePath = process.env.CANOPY_AUTH_CACHE_PATH ?? path6.join(operatingStrategy(mode).getWorkspaceRoot(options.projectDir), ".cache");
|
|
1283
1314
|
let refreshAuthCache;
|
|
@@ -1299,19 +1330,28 @@ CanopyCMS worker run-once (mode: ${mode}, auth: ${authMode})
|
|
|
1299
1330
|
await refreshAuthCache();
|
|
1300
1331
|
console.log("Auth cache refreshed");
|
|
1301
1332
|
}
|
|
1302
|
-
const { dequeueTask: dequeueTask2, completeTask: completeTask2 } = await Promise.resolve().then(() => (init_task_queue3(), task_queue_exports));
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
await completeTask2(taskDir, task.id, { skipped: true });
|
|
1309
|
-
taskCount++;
|
|
1310
|
-
}
|
|
1311
|
-
if (taskCount > 0) {
|
|
1312
|
-
console.log(`Processed ${taskCount} task(s)`);
|
|
1313
|
-
} else {
|
|
1333
|
+
const { dequeueTask: dequeueTask2, completeTask: completeTask2, listTasks: listTasks2 } = await Promise.resolve().then(() => (init_task_queue3(), task_queue_exports));
|
|
1334
|
+
if (mode === "prod") {
|
|
1335
|
+
const pending = await listTasks2(taskDir, "pending");
|
|
1336
|
+
if (pending.length > 0) {
|
|
1337
|
+
throw new Error(`workerRunOnce found ${pending.length} pending task(s) in prod mode but cannot execute them. Use the full worker daemon to process prod task queues.`);
|
|
1338
|
+
}
|
|
1314
1339
|
console.log("No pending tasks");
|
|
1340
|
+
} else {
|
|
1341
|
+
let taskCount = 0;
|
|
1342
|
+
let task = await dequeueTask2(taskDir);
|
|
1343
|
+
while (task !== null) {
|
|
1344
|
+
console.log(`Processing task: ${task.action} (${task.id})`);
|
|
1345
|
+
console.warn(` WARNING: Task skipped \u2014 GitHub operations require the full worker daemon`);
|
|
1346
|
+
await completeTask2(taskDir, task.id, { skipped: true });
|
|
1347
|
+
taskCount++;
|
|
1348
|
+
task = await dequeueTask2(taskDir);
|
|
1349
|
+
}
|
|
1350
|
+
if (taskCount > 0) {
|
|
1351
|
+
console.log(`Processed ${taskCount} task(s)`);
|
|
1352
|
+
} else {
|
|
1353
|
+
console.log("No pending tasks");
|
|
1354
|
+
}
|
|
1315
1355
|
}
|
|
1316
1356
|
console.log("\nDone");
|
|
1317
1357
|
}
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAA;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
package/dist/content-store.d.ts
CHANGED
|
@@ -21,23 +21,35 @@ export type ContentDocument = (MarkdownDocument | JsonDocument | YamlDocument) &
|
|
|
21
21
|
collectionName: string;
|
|
22
22
|
relativePath: PhysicalPath;
|
|
23
23
|
absolutePath: string;
|
|
24
|
+
/** File mtime in ms at the time of read/write. Used as an OCC version token. */
|
|
25
|
+
version?: number;
|
|
24
26
|
};
|
|
25
27
|
export type WriteInput = {
|
|
26
28
|
format: 'md' | 'mdx';
|
|
27
29
|
data?: Record<string, unknown>;
|
|
28
30
|
body: string;
|
|
31
|
+
expectedVersion?: number;
|
|
29
32
|
} | {
|
|
30
33
|
format: 'json';
|
|
31
34
|
data: Record<string, unknown>;
|
|
35
|
+
expectedVersion?: number;
|
|
32
36
|
} | {
|
|
33
37
|
format: 'yaml';
|
|
34
38
|
data: Record<string, unknown>;
|
|
39
|
+
expectedVersion?: number;
|
|
35
40
|
};
|
|
36
41
|
export type ContentStoreErrorCode = 'NOT_FOUND' | 'NO_SCHEMA_ITEM' | 'FORBIDDEN' | 'VALIDATION';
|
|
37
42
|
export declare class ContentStoreError extends Error {
|
|
38
43
|
code: ContentStoreErrorCode;
|
|
39
44
|
constructor(message: string, code: ContentStoreErrorCode);
|
|
40
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Thrown when `expectedVersion` on a write doesn't match the file's current mtime.
|
|
48
|
+
* Indicates a cross-process concurrent write — the caller should reload and retry.
|
|
49
|
+
*/
|
|
50
|
+
export declare class ContentConflictError extends Error {
|
|
51
|
+
constructor();
|
|
52
|
+
}
|
|
41
53
|
export declare class ContentStore {
|
|
42
54
|
private readonly root;
|
|
43
55
|
private readonly schemaIndex;
|