@react-arch/validation 0.1.2 → 0.1.3
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/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -12
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { BuildingDocument } from "@react-arch/core";
|
|
3
2
|
import { Diagnostic, Diagnostic as Diagnostic$1 } from "@react-arch/shared";
|
|
4
3
|
|
|
5
4
|
//#region src/schema.d.ts
|
|
@@ -1316,7 +1315,7 @@ declare const BuildingDocumentSchema: z.ZodObject<{
|
|
|
1316
1315
|
* for shape, then semantic checks (unique ids, references, fit). The studio
|
|
1317
1316
|
* shows these in the diagnostics panel; clicking one selects the entity.
|
|
1318
1317
|
*/
|
|
1319
|
-
declare function validateDocument(doc:
|
|
1318
|
+
declare function validateDocument(doc: unknown): Diagnostic$1[];
|
|
1320
1319
|
//#endregion
|
|
1321
1320
|
export { BuildingDocumentSchema, BuildingObjectSchema, BuildingSchema, type Diagnostic, FloorSchema, MaterialSchema, OpeningSchema, RoomSchema, WallSchema, validateDocument };
|
|
1322
1321
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/schema.ts","../src/validate.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/schema.ts","../src/validate.ts"],"mappings":";;;;cAMa,UAAA,EAAU,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAYV,aAAA,EAAa,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAcb,UAAA,EAAU,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAYV,oBAAA,EAAoB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAWpB,WAAA,EAAW,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAcX,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAMd,cAAA,EAAc,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAWd,sBAAA,EAAsB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAhFnC;;iBCKgB,gBAAA,CAAiB,GAAA,YAAe,YAAU"}
|
package/dist/index.js
CHANGED
|
@@ -107,16 +107,20 @@ const BuildingDocumentSchema = z.object({
|
|
|
107
107
|
function validateDocument(doc) {
|
|
108
108
|
const diags = [];
|
|
109
109
|
const parsed = BuildingDocumentSchema.safeParse(doc);
|
|
110
|
-
if (!parsed.success)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
if (!parsed.success) {
|
|
111
|
+
for (const issue of parsed.error.issues) diags.push({
|
|
112
|
+
severity: "error",
|
|
113
|
+
code: "schema",
|
|
114
|
+
message: issue.message,
|
|
115
|
+
path: issue.path.map(String)
|
|
116
|
+
});
|
|
117
|
+
return diags;
|
|
118
|
+
}
|
|
119
|
+
const checked = parsed.data;
|
|
120
|
+
if (!isCompatibleVersion(checked.version)) diags.push({
|
|
117
121
|
severity: "warning",
|
|
118
122
|
code: "version",
|
|
119
|
-
message: `Document version ${
|
|
123
|
+
message: `Document version ${checked.version} may be incompatible with this build`
|
|
120
124
|
});
|
|
121
125
|
const seen = /* @__PURE__ */ new Map();
|
|
122
126
|
const checkId = (id, kind) => {
|
|
@@ -128,8 +132,11 @@ function validateDocument(doc) {
|
|
|
128
132
|
});
|
|
129
133
|
else seen.set(id, kind);
|
|
130
134
|
};
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
checkId(checked.id, "document");
|
|
136
|
+
for (const building of checked.buildings) checkId(building.id, "building");
|
|
137
|
+
for (const material of checked.materials) checkId(material.id, "material");
|
|
138
|
+
for (const asset of checked.assets) if (typeof asset === "object" && asset && "id" in asset && typeof asset.id === "string") checkId(asset.id, "asset");
|
|
139
|
+
const floors = allFloors(checked);
|
|
133
140
|
for (const floor of floors) {
|
|
134
141
|
checkId(floor.id, "floor");
|
|
135
142
|
const wallIds = new Set(floor.walls.map((w) => w.id));
|
|
@@ -150,15 +157,33 @@ function validateDocument(doc) {
|
|
|
150
157
|
}
|
|
151
158
|
for (const room of floor.rooms) {
|
|
152
159
|
checkId(room.id, "room");
|
|
160
|
+
if (room.floorId !== floor.id) diags.push({
|
|
161
|
+
severity: "error",
|
|
162
|
+
code: "bad-floor-ref",
|
|
163
|
+
message: `Room ${room.id} references wrong floor`,
|
|
164
|
+
entityId: room.id
|
|
165
|
+
});
|
|
153
166
|
if (room.polygon.length < 3) diags.push({
|
|
154
167
|
severity: "error",
|
|
155
168
|
code: "open-room",
|
|
156
169
|
message: `Room ${room.id} boundary is not closed`,
|
|
157
170
|
entityId: room.id
|
|
158
171
|
});
|
|
172
|
+
for (const wallId of room.boundaryWallIds ?? []) if (!wallIds.has(wallId)) diags.push({
|
|
173
|
+
severity: "error",
|
|
174
|
+
code: "bad-wall-ref",
|
|
175
|
+
message: `Room ${room.id} references unknown boundary wall ${wallId}`,
|
|
176
|
+
entityId: room.id
|
|
177
|
+
});
|
|
159
178
|
}
|
|
160
179
|
for (const o of floor.openings) {
|
|
161
180
|
checkId(o.id, "opening");
|
|
181
|
+
if (o.floorId !== floor.id) diags.push({
|
|
182
|
+
severity: "error",
|
|
183
|
+
code: "bad-floor-ref",
|
|
184
|
+
message: `Opening ${o.id} references wrong floor`,
|
|
185
|
+
entityId: o.id
|
|
186
|
+
});
|
|
162
187
|
if (!wallIds.has(o.wallId)) {
|
|
163
188
|
diags.push({
|
|
164
189
|
severity: "error",
|
|
@@ -175,9 +200,17 @@ function validateDocument(doc) {
|
|
|
175
200
|
entityId: o.id
|
|
176
201
|
});
|
|
177
202
|
}
|
|
178
|
-
for (const obj of floor.objects)
|
|
203
|
+
for (const obj of floor.objects) {
|
|
204
|
+
checkId(obj.id, "object");
|
|
205
|
+
if (obj.floorId !== floor.id) diags.push({
|
|
206
|
+
severity: "error",
|
|
207
|
+
code: "bad-floor-ref",
|
|
208
|
+
message: `Object ${obj.id} references wrong floor`,
|
|
209
|
+
entityId: obj.id
|
|
210
|
+
});
|
|
211
|
+
}
|
|
179
212
|
}
|
|
180
|
-
for (const building of
|
|
213
|
+
for (const building of checked.buildings) for (const f of building.floors) if (f.buildingId !== building.id) diags.push({
|
|
181
214
|
severity: "error",
|
|
182
215
|
code: "bad-building-ref",
|
|
183
216
|
message: `Floor ${f.id} references wrong building`,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/schema.ts","../src/validate.ts"],"sourcesContent":["import { z } from \"zod\";\n\nconst finite = z.number().finite();\nconst vec2 = z.tuple([finite, finite]);\nconst vec3 = z.tuple([finite, finite, finite]);\n\nexport const WallSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n start: vec2,\n end: vec2,\n thickness: z.number().positive(),\n height: z.number().positive(),\n materialId: z.string().optional(),\n layerId: z.string().optional(),\n locked: z.boolean().optional(),\n});\n\nexport const OpeningSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n wallId: z.string().min(1),\n type: z.enum([\"door\", \"window\", \"opening\"]),\n offset: finite,\n width: z.number().positive(),\n height: z.number().positive(),\n sillHeight: z.number().min(0),\n swing: z.enum([\"in\", \"out\"]).optional(),\n hinge: z.enum([\"left\", \"right\"]).optional(),\n materialId: z.string().optional(),\n});\n\nexport const RoomSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n name: z.string(),\n polygon: z.array(vec2).min(3),\n boundaryWallIds: z.array(z.string()).optional(),\n floorMaterialId: z.string().optional(),\n ceilingMaterialId: z.string().optional(),\n usageType: z.string().optional(),\n height: z.number().positive().optional(),\n});\n\nexport const BuildingObjectSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n type: z.string(),\n position: vec3,\n rotation: vec3,\n scale: vec3,\n assetId: z.string().optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const FloorSchema = z.object({\n id: z.string().min(1),\n buildingId: z.string().min(1),\n name: z.string(),\n elevation: finite,\n height: z.number().positive(),\n visible: z.boolean(),\n locked: z.boolean(),\n walls: z.array(WallSchema),\n rooms: z.array(RoomSchema),\n openings: z.array(OpeningSchema),\n objects: z.array(BuildingObjectSchema),\n});\n\nexport const BuildingSchema = z.object({\n id: z.string().min(1),\n name: z.string(),\n floors: z.array(FloorSchema),\n});\n\nexport const MaterialSchema = z.object({\n id: z.string().min(1),\n name: z.string(),\n category: z.string(),\n baseColor: z.string(),\n roughness: z.number().optional(),\n metalness: z.number().optional(),\n opacity: z.number().optional(),\n textureUrl: z.string().optional(),\n});\n\nexport const BuildingDocumentSchema = z.object({\n id: z.string().min(1),\n version: z.string(),\n name: z.string(),\n units: z.enum([\"metric\", \"imperial\"]),\n site: z.unknown().optional(),\n buildings: z.array(BuildingSchema),\n materials: z.array(MaterialSchema),\n assets: z.array(z.unknown()),\n metadata: z.record(z.unknown()),\n});\n","import type { Diagnostic } from \"@react-arch/shared\";\nimport { allFloors, type BuildingDocument } from \"@react-arch/core\";\nimport { openingFits, wallLength } from \"@react-arch/geometry\";\nimport { isCompatibleVersion } from \"@react-arch/core\";\nimport { BuildingDocumentSchema } from \"./schema.js\";\n\n/**\n * Validate a document and return structured diagnostics. Runs the Zod schema\n * for shape, then semantic checks (unique ids, references, fit). The studio\n * shows these in the diagnostics panel; clicking one selects the entity.\n */\nexport function validateDocument(doc: BuildingDocument): Diagnostic[] {\n const diags: Diagnostic[] = [];\n\n const parsed = BuildingDocumentSchema.safeParse(doc);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) {\n diags.push({\n severity: \"error\",\n code: \"schema\",\n message: issue.message,\n path: issue.path.map(String),\n });\n }\n }\n\n if (!isCompatibleVersion(doc.version)) {\n diags.push({\n severity: \"warning\",\n code: \"version\",\n message: `Document version ${doc.version} may be incompatible with this build`,\n });\n }\n\n // Unique ids across the whole document.\n const seen = new Map<string, string>();\n const checkId = (id: string, kind: string) => {\n if (seen.has(id)) {\n diags.push({\n severity: \"error\",\n code: \"duplicate-id\",\n message: `Duplicate id \"${id}\" (${seen.get(id)} and ${kind})`,\n entityId: id,\n });\n } else {\n seen.set(id, kind);\n }\n };\n\n const floors = allFloors(doc);\n const floorIds = new Set(floors.map((f) => f.id));\n for (const floor of floors) {\n checkId(floor.id, \"floor\");\n const wallIds = new Set(floor.walls.map((w) => w.id));\n for (const wall of floor.walls) {\n checkId(wall.id, \"wall\");\n if (wall.floorId !== floor.id) {\n diags.push({ severity: \"error\", code: \"bad-floor-ref\", message: `Wall ${wall.id} references wrong floor`, entityId: wall.id });\n }\n if (wallLength(wall) < 1e-3) {\n diags.push({ severity: \"warning\", code: \"zero-length-wall\", message: `Wall ${wall.id} has near-zero length`, entityId: wall.id });\n }\n }\n for (const room of floor.rooms) {\n checkId(room.id, \"room\");\n if (room.polygon.length < 3) {\n diags.push({ severity: \"error\", code: \"open-room\", message: `Room ${room.id} boundary is not closed`, entityId: room.id });\n }\n }\n for (const o of floor.openings) {\n checkId(o.id, \"opening\");\n if (!wallIds.has(o.wallId)) {\n diags.push({ severity: \"error\", code: \"bad-wall-ref\", message: `Opening ${o.id} references unknown wall ${o.wallId}`, entityId: o.id });\n continue;\n }\n const wall = floor.walls.find((w) => w.id === o.wallId)!;\n if (!openingFits(wall, o)) {\n diags.push({ severity: \"warning\", code: \"opening-overflow\", message: `Opening ${o.id} does not fit within its wall`, entityId: o.id });\n }\n }\n for (const obj of floor.objects) checkId(obj.id, \"object\");\n }\n\n // Building → floor references.\n for (const building of doc.buildings) {\n for (const f of building.floors) {\n if (f.buildingId !== building.id) {\n diags.push({ severity: \"error\", code: \"bad-building-ref\", message: `Floor ${f.id} references wrong building`, entityId: f.id });\n }\n }\n }\n void floorIds;\n\n return diags;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/schema.ts","../src/validate.ts"],"sourcesContent":["import { z } from \"zod\";\n\nconst finite = z.number().finite();\nconst vec2 = z.tuple([finite, finite]);\nconst vec3 = z.tuple([finite, finite, finite]);\n\nexport const WallSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n start: vec2,\n end: vec2,\n thickness: z.number().positive(),\n height: z.number().positive(),\n materialId: z.string().optional(),\n layerId: z.string().optional(),\n locked: z.boolean().optional(),\n});\n\nexport const OpeningSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n wallId: z.string().min(1),\n type: z.enum([\"door\", \"window\", \"opening\"]),\n offset: finite,\n width: z.number().positive(),\n height: z.number().positive(),\n sillHeight: z.number().min(0),\n swing: z.enum([\"in\", \"out\"]).optional(),\n hinge: z.enum([\"left\", \"right\"]).optional(),\n materialId: z.string().optional(),\n});\n\nexport const RoomSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n name: z.string(),\n polygon: z.array(vec2).min(3),\n boundaryWallIds: z.array(z.string()).optional(),\n floorMaterialId: z.string().optional(),\n ceilingMaterialId: z.string().optional(),\n usageType: z.string().optional(),\n height: z.number().positive().optional(),\n});\n\nexport const BuildingObjectSchema = z.object({\n id: z.string().min(1),\n floorId: z.string().min(1),\n type: z.string(),\n position: vec3,\n rotation: vec3,\n scale: vec3,\n assetId: z.string().optional(),\n metadata: z.record(z.unknown()).optional(),\n});\n\nexport const FloorSchema = z.object({\n id: z.string().min(1),\n buildingId: z.string().min(1),\n name: z.string(),\n elevation: finite,\n height: z.number().positive(),\n visible: z.boolean(),\n locked: z.boolean(),\n walls: z.array(WallSchema),\n rooms: z.array(RoomSchema),\n openings: z.array(OpeningSchema),\n objects: z.array(BuildingObjectSchema),\n});\n\nexport const BuildingSchema = z.object({\n id: z.string().min(1),\n name: z.string(),\n floors: z.array(FloorSchema),\n});\n\nexport const MaterialSchema = z.object({\n id: z.string().min(1),\n name: z.string(),\n category: z.string(),\n baseColor: z.string(),\n roughness: z.number().optional(),\n metalness: z.number().optional(),\n opacity: z.number().optional(),\n textureUrl: z.string().optional(),\n});\n\nexport const BuildingDocumentSchema = z.object({\n id: z.string().min(1),\n version: z.string(),\n name: z.string(),\n units: z.enum([\"metric\", \"imperial\"]),\n site: z.unknown().optional(),\n buildings: z.array(BuildingSchema),\n materials: z.array(MaterialSchema),\n assets: z.array(z.unknown()),\n metadata: z.record(z.unknown()),\n});\n","import type { Diagnostic } from \"@react-arch/shared\";\nimport { allFloors, type BuildingDocument } from \"@react-arch/core\";\nimport { openingFits, wallLength } from \"@react-arch/geometry\";\nimport { isCompatibleVersion } from \"@react-arch/core\";\nimport { BuildingDocumentSchema } from \"./schema.js\";\n\n/**\n * Validate a document and return structured diagnostics. Runs the Zod schema\n * for shape, then semantic checks (unique ids, references, fit). The studio\n * shows these in the diagnostics panel; clicking one selects the entity.\n */\nexport function validateDocument(doc: unknown): Diagnostic[] {\n const diags: Diagnostic[] = [];\n\n const parsed = BuildingDocumentSchema.safeParse(doc);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) {\n diags.push({\n severity: \"error\",\n code: \"schema\",\n message: issue.message,\n path: issue.path.map(String),\n });\n }\n return diags;\n }\n\n const checked = parsed.data as BuildingDocument;\n\n if (!isCompatibleVersion(checked.version)) {\n diags.push({\n severity: \"warning\",\n code: \"version\",\n message: `Document version ${checked.version} may be incompatible with this build`,\n });\n }\n\n // Unique ids across the whole document.\n const seen = new Map<string, string>();\n const checkId = (id: string, kind: string) => {\n if (seen.has(id)) {\n diags.push({\n severity: \"error\",\n code: \"duplicate-id\",\n message: `Duplicate id \"${id}\" (${seen.get(id)} and ${kind})`,\n entityId: id,\n });\n } else {\n seen.set(id, kind);\n }\n };\n\n checkId(checked.id, \"document\");\n for (const building of checked.buildings) checkId(building.id, \"building\");\n for (const material of checked.materials) checkId(material.id, \"material\");\n for (const asset of checked.assets) {\n if (typeof asset === \"object\" && asset && \"id\" in asset && typeof asset.id === \"string\") {\n checkId(asset.id, \"asset\");\n }\n }\n\n const floors = allFloors(checked);\n for (const floor of floors) {\n checkId(floor.id, \"floor\");\n const wallIds = new Set(floor.walls.map((w) => w.id));\n for (const wall of floor.walls) {\n checkId(wall.id, \"wall\");\n if (wall.floorId !== floor.id) {\n diags.push({ severity: \"error\", code: \"bad-floor-ref\", message: `Wall ${wall.id} references wrong floor`, entityId: wall.id });\n }\n if (wallLength(wall) < 1e-3) {\n diags.push({ severity: \"warning\", code: \"zero-length-wall\", message: `Wall ${wall.id} has near-zero length`, entityId: wall.id });\n }\n }\n for (const room of floor.rooms) {\n checkId(room.id, \"room\");\n if (room.floorId !== floor.id) {\n diags.push({ severity: \"error\", code: \"bad-floor-ref\", message: `Room ${room.id} references wrong floor`, entityId: room.id });\n }\n if (room.polygon.length < 3) {\n diags.push({ severity: \"error\", code: \"open-room\", message: `Room ${room.id} boundary is not closed`, entityId: room.id });\n }\n for (const wallId of room.boundaryWallIds ?? []) {\n if (!wallIds.has(wallId)) {\n diags.push({ severity: \"error\", code: \"bad-wall-ref\", message: `Room ${room.id} references unknown boundary wall ${wallId}`, entityId: room.id });\n }\n }\n }\n for (const o of floor.openings) {\n checkId(o.id, \"opening\");\n if (o.floorId !== floor.id) {\n diags.push({ severity: \"error\", code: \"bad-floor-ref\", message: `Opening ${o.id} references wrong floor`, entityId: o.id });\n }\n if (!wallIds.has(o.wallId)) {\n diags.push({ severity: \"error\", code: \"bad-wall-ref\", message: `Opening ${o.id} references unknown wall ${o.wallId}`, entityId: o.id });\n continue;\n }\n const wall = floor.walls.find((w) => w.id === o.wallId)!;\n if (!openingFits(wall, o)) {\n diags.push({ severity: \"warning\", code: \"opening-overflow\", message: `Opening ${o.id} does not fit within its wall`, entityId: o.id });\n }\n }\n for (const obj of floor.objects) {\n checkId(obj.id, \"object\");\n if (obj.floorId !== floor.id) {\n diags.push({ severity: \"error\", code: \"bad-floor-ref\", message: `Object ${obj.id} references wrong floor`, entityId: obj.id });\n }\n }\n }\n\n // Building → floor references.\n for (const building of checked.buildings) {\n for (const f of building.floors) {\n if (f.buildingId !== building.id) {\n diags.push({ severity: \"error\", code: \"bad-building-ref\", message: `Floor ${f.id} references wrong building`, entityId: f.id });\n }\n }\n }\n\n return diags;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-arch/validation",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"zod": "^3.24.1",
|
|
16
|
-
"@react-arch/core": "0.1.
|
|
17
|
-
"@react-arch/
|
|
18
|
-
"@react-arch/
|
|
16
|
+
"@react-arch/core": "0.1.3",
|
|
17
|
+
"@react-arch/geometry": "0.1.3",
|
|
18
|
+
"@react-arch/shared": "0.1.3"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"typescript": "^5.7.2",
|