@conradsix/c4m-schema 0.0.0-stage → 0.1.0-preview.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/LICENSE +21 -0
- package/README.md +14 -2
- package/dist/defineBlock.d.ts +25 -0
- package/dist/defineBlock.d.ts.map +1 -0
- package/dist/defineBlock.js +71 -0
- package/dist/defineBlock.js.map +1 -0
- package/dist/defineCatalogue.d.ts +42 -0
- package/dist/defineCatalogue.d.ts.map +1 -0
- package/dist/defineCatalogue.js +52 -0
- package/dist/defineCatalogue.js.map +1 -0
- package/dist/descriptor.d.ts +8 -0
- package/dist/descriptor.d.ts.map +1 -0
- package/dist/descriptor.js +2 -0
- package/dist/descriptor.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/isJsonEqual.d.ts +3 -0
- package/dist/isJsonEqual.d.ts.map +1 -0
- package/dist/isJsonEqual.js +26 -0
- package/dist/isJsonEqual.js.map +1 -0
- package/dist/markdownPageRef.d.ts +5 -0
- package/dist/markdownPageRef.d.ts.map +1 -0
- package/dist/markdownPageRef.js +28 -0
- package/dist/markdownPageRef.js.map +1 -0
- package/dist/menuActions.d.ts +61 -0
- package/dist/menuActions.d.ts.map +1 -0
- package/dist/menuActions.js +32 -0
- package/dist/menuActions.js.map +1 -0
- package/dist/pageSeo.d.ts +19 -0
- package/dist/pageSeo.d.ts.map +1 -0
- package/dist/pageSeo.js +18 -0
- package/dist/pageSeo.js.map +1 -0
- package/dist/references.d.ts +22 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +12 -0
- package/dist/references.js.map +1 -0
- package/dist/syncSchemas.d.ts +28 -0
- package/dist/syncSchemas.d.ts.map +1 -0
- package/dist/syncSchemas.js +50 -0
- package/dist/syncSchemas.js.map +1 -0
- package/package.json +45 -3
- package/src/defineBlock.ts +153 -0
- package/src/defineCatalogue.ts +118 -0
- package/src/descriptor.ts +10 -0
- package/src/index.ts +24 -0
- package/src/isJsonEqual.ts +26 -0
- package/src/markdownPageRef.ts +30 -0
- package/src/menuActions.ts +50 -0
- package/src/pageSeo.ts +23 -0
- package/src/references.ts +21 -0
- package/src/syncSchemas.ts +84 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { CmsSchemaDescriptor } from "./descriptor.js";
|
|
2
|
+
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { isJsonEqual } from "./isJsonEqual.js";
|
|
6
|
+
|
|
7
|
+
type RegisteredSchema = {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly version: number;
|
|
10
|
+
readonly jsonSchema: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Where the CMS keeps the schemas it checks stored data against: its block types, or its menu action types.
|
|
14
|
+
type SchemaRegistry = {
|
|
15
|
+
list(): Promise<readonly RegisteredSchema[]>;
|
|
16
|
+
create(schema: RegisteredSchema): Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type SyncResult = {
|
|
20
|
+
readonly created: Array<{ name: string; version: number }>;
|
|
21
|
+
readonly validated: Array<{ name: string; version: number }>;
|
|
22
|
+
readonly errors: Array<{ type: "mismatch" | "orphaned" | "creation"; details: string }>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const keyOf = (schema: { readonly name: string; readonly version: number }): string =>
|
|
26
|
+
`${schema.name}:${schema.version}`;
|
|
27
|
+
|
|
28
|
+
// Registers the schemas the registry lacks and checks the rest are unchanged. A registered schema never changes, so
|
|
29
|
+
// a different one, or one the host no longer has, fails the sync.
|
|
30
|
+
const syncSchemas = async (
|
|
31
|
+
descriptors: readonly CmsSchemaDescriptor[],
|
|
32
|
+
registry: SchemaRegistry,
|
|
33
|
+
): Promise<SyncResult> => {
|
|
34
|
+
if (descriptors.length === 0) throw new Error("No local schemas to sync");
|
|
35
|
+
|
|
36
|
+
const local = new Map(
|
|
37
|
+
descriptors.map((descriptor) => [
|
|
38
|
+
keyOf(descriptor),
|
|
39
|
+
{ ...descriptor, jsonSchema: JSON.stringify(z.toJSONSchema(descriptor.schema)) },
|
|
40
|
+
]),
|
|
41
|
+
);
|
|
42
|
+
const registered = new Map((await registry.list()).map((schema) => [keyOf(schema), schema]));
|
|
43
|
+
const result: SyncResult = { created: [], validated: [], errors: [] };
|
|
44
|
+
|
|
45
|
+
for (const [key, schema] of registered)
|
|
46
|
+
if (!local.has(key))
|
|
47
|
+
result.errors.push({
|
|
48
|
+
type: "orphaned",
|
|
49
|
+
details: `The CMS has '${schema.name}' version ${schema.version}, which doesn't exist locally`,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
for (const [key, schema] of local) {
|
|
53
|
+
const existing = registered.get(key);
|
|
54
|
+
const entry = { name: schema.name, version: schema.version };
|
|
55
|
+
if (existing) {
|
|
56
|
+
if (isJsonEqual(schema.jsonSchema, existing.jsonSchema)) result.validated.push(entry);
|
|
57
|
+
else
|
|
58
|
+
result.errors.push({
|
|
59
|
+
type: "mismatch",
|
|
60
|
+
details: `Schema mismatch for '${schema.name}' version ${schema.version}: local and CMS schemas differ`,
|
|
61
|
+
});
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await registry.create({ ...entry, jsonSchema: schema.jsonSchema });
|
|
67
|
+
result.created.push(entry);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
result.errors.push({
|
|
70
|
+
type: "creation",
|
|
71
|
+
details: `Failed to create '${schema.name}' version ${schema.version}: ${String(error)}`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (result.errors.length > 0)
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Schema sync failed:\n${result.errors.map((error) => `${error.type.toUpperCase()}: ${error.details}`).join("\n")}`,
|
|
79
|
+
);
|
|
80
|
+
return result;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export { syncSchemas };
|
|
84
|
+
export type { RegisteredSchema, SchemaRegistry, SyncResult };
|