feat: release design system engine, studio and component contracts

This commit is contained in:
Clintchiz committed 2026-10-19 13:09:03 +05:30
1 parent ff1065fb27
commit 3943b946d6
693 files changed
+175546 -3894

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/blocks",
"version": "0.1.3",
"version": "0.1.4",
"type": "module",
"description": "Pure dynamic block document engine for WRNexus builders.",
"exports": {
+35 -8
View File
@@ -161,7 +161,10 @@ export function applyCommand(
).length;
root = insert(
remove(root, new Set(command.intent.nodeIds)),
{ ...command.intent.to, index: Math.max(0, command.intent.to.index - removedBeforeDestination) },
{
...command.intent.to,
index: Math.max(0, command.intent.to.index - removedBeforeDestination),
},
moving as BlockNode[],
);
affected = command.intent.nodeIds;
@@ -180,19 +183,43 @@ export function applyCommand(
const originals = command.nodeIds.map((id) => findBlock(root, id));
const locations = command.nodeIds.map((id) => locationOf(root, id));
if (originals.some((node) => !node) || locations.some((location) => !location))
return { ok: false, errors: [{ code: "command.missing", message: "A duplicated block does not exist.", severity: "error" }] };
return {
ok: false,
errors: [
{
code: "command.missing",
message: "A duplicated block does not exist.",
severity: "error",
},
],
};
const countNodes = (node: BlockNode): number =>
1 + Object.values(node.slots).flat().reduce((total, child) => total + countNodes(child), 0);
1 +
Object.values(node.slots)
.flat()
.reduce((total, child) => total + countNodes(child), 0);
const requiredIds = (originals as BlockNode[]).reduce(
(total, node) => total + countNodes(node),
0,
);
if (command.ids.length !== requiredIds || new Set(command.ids).size !== command.ids.length)
return { ok: false, errors: [{ code: "command.ids", message: "Duplicate requires one unique id for every copied node.", severity: "error" }] };
const copies = duplicateNodes(originals as BlockNode[], (() => {
let index = 0;
return () => command.ids[index++]!;
})());
return {
ok: false,
errors: [
{
code: "command.ids",
message: "Duplicate requires one unique id for every copied node.",
severity: "error",
},
],
};
const copies = duplicateNodes(
originals as BlockNode[],
(() => {
let index = 0;
return () => command.ids[index++]!;
})(),
);
const commands = copies.map((node, index) => ({
type: "insert" as const,
location: { ...locations[index]!, index: locations[index]!.index + 1 },
+32 -5
View File
@@ -31,13 +31,27 @@ export function resolveDocumentVariables(
): Result<BlockDocument> {
const diagnostics: Diagnostic[] = [];
if (options.preserveTokens && options.requireValues)
return { ok: false, errors: [{ code: "variable.mode", message: "Template tokens cannot be preserved when resolved values are required.", severity: "error" }] };
return {
ok: false,
errors: [
{
code: "variable.mode",
message: "Template tokens cannot be preserved when resolved values are required.",
severity: "error",
},
],
};
const visit = (value: JsonValue, path: string): JsonValue => {
if (typeof value === "string")
return value.replace(TOKEN, (raw, key: string, fallback: string | undefined) => {
const type = catalog[key];
if (!type) {
diagnostics.push({ code: "variable.unknown", message: `Unknown variable ${key}.`, severity: "error", path });
diagnostics.push({
code: "variable.unknown",
message: `Unknown variable ${key}.`,
severity: "error",
path,
});
return raw;
}
if (options.preserveTokens) return raw;
@@ -45,11 +59,21 @@ export function resolveDocumentVariables(
if (supplied === undefined || supplied === null || supplied === "") {
if (fallback !== undefined) return fallback.trim();
if (options.requireValues)
diagnostics.push({ code: "variable.missing", message: `Variable ${key} is required.`, severity: "error", path });
diagnostics.push({
code: "variable.missing",
message: `Variable ${key} is required.`,
severity: "error",
path,
});
return raw;
}
if (!validType(supplied, type)) {
diagnostics.push({ code: "variable.type", message: `Variable ${key} must be ${type}.`, severity: "error", path });
diagnostics.push({
code: "variable.type",
message: `Variable ${key} must be ${type}.`,
severity: "error",
path,
});
return raw;
}
return supplied instanceof Date ? supplied.toISOString() : String(supplied);
@@ -61,6 +85,9 @@ export function resolveDocumentVariables(
);
return value;
};
const resolved = visit(structuredClone(document) as unknown as JsonValue, "document") as unknown as BlockDocument;
const resolved = visit(
structuredClone(document) as unknown as JsonValue,
"document",
) as unknown as BlockDocument;
return diagnostics.length ? { ok: false, errors: diagnostics } : { ok: true, value: resolved };
}
+28 -16
View File
@@ -146,30 +146,42 @@ describe("dynamic blocks engine", () => {
...text.create({ id: () => nodeId }),
props: { text: nodeId },
}));
const moved = applyCommand(document, {
type: "move",
intent: {
nodeIds: ["a"],
from: [{ parentId: "root", slot: "content", index: 0 }],
to: { parentId: "root", slot: "content", index: 3 },
const moved = applyCommand(
document,
{
type: "move",
intent: {
nodeIds: ["a"],
from: [{ parentId: "root", slot: "content", index: 0 }],
to: { parentId: "root", slot: "content", index: 3 },
},
},
}, kind, registry);
kind,
registry,
);
expect(moved.ok && moved.value.document.root.slots.content.map((node) => node.id)).toEqual([
"b", "c", "a",
"b",
"c",
"a",
]);
});
test("duplicates blocks with deterministic injected ids", () => {
const document = doc();
document.root.slots.content = [{ ...text.create({ id: () => "a" }), props: { text: "A" } }];
const duplicated = applyCommand(document, {
type: "duplicate",
nodeIds: ["a"],
ids: ["a-copy"],
}, kind, registry);
expect(duplicated.ok && duplicated.value.document.root.slots.content.map((node) => node.id)).toEqual([
"a", "a-copy",
]);
const duplicated = applyCommand(
document,
{
type: "duplicate",
nodeIds: ["a"],
ids: ["a-copy"],
},
kind,
registry,
);
expect(
duplicated.ok && duplicated.value.document.root.slots.content.map((node) => node.id),
).toEqual(["a", "a-copy"]);
});
test("validates and resolves typed personalization tokens", () => {