diff --git a/package.json b/package.json index cca21d33..c424e7db 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,6 @@ }, "engines": { "node": ">=20.13.1", - "pnpm": ">=9.1.2" + "pnpm": ">=9.1.0" } -} \ No newline at end of file +} diff --git a/packages/cadmium/package.json b/packages/cadmium/package.json index 26954e5e..9a592dba 100644 --- a/packages/cadmium/package.json +++ b/packages/cadmium/package.json @@ -3,10 +3,11 @@ "scripts": { "dev": "onchange 'src/**/*.rs' -- pnpm run build:dev", "build:dev": "cargo check && pnpm run build:wasm", - "build:wasm": "wasm-pack build --target web && ./patchpackage.cjs", + "build:wasm": "wasm-pack build --target web && ./patchpackage.cjs && ts-auto-guard pkg/cadmium.d.ts --export-all", "test": "cargo test" }, "devDependencies": { - "onchange": "^7.1.0" + "onchange": "^7.1.0", + "ts-auto-guard": "^4.2.0" } -} \ No newline at end of file +} diff --git a/packages/cadmium/tsconfig.json b/packages/cadmium/tsconfig.json new file mode 100644 index 00000000..2302c65c --- /dev/null +++ b/packages/cadmium/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } +} diff --git a/packages/shared/package.json b/packages/shared/package.json index 582802f2..13da692c 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "cadmium": "workspace:*", - "svelte": "^4.2.12", - "three": "^0.162.0" + "svelte": "^4.2.12", + "three": "^0.162.0" } -} \ No newline at end of file +} diff --git a/packages/shared/projectUtils.ts b/packages/shared/projectUtils.ts index 8dfac5e1..f1ad5ace 100644 --- a/packages/shared/projectUtils.ts +++ b/packages/shared/projectUtils.ts @@ -17,7 +17,6 @@ import type { Entity, ExtrusionHistoryStep, HistoryStep, - Message, MessageHistory, PlaneHistoryStep, PointHistoryStep, @@ -26,23 +25,8 @@ import type { WithTarget, WorkBench } from "./types" -import type { Realization as WasmRealization } from "cadmium" -import { - isDeleteArcs, - isDeleteCircles, - isDeleteLines, - isNewCircleBetweenPoints, - isNewExtrusion, - isNewLineOnSketch, - isNewPointOnSketch2, - isNewRectangleBetweenPoints, - isNewSketchOnPlane, - isRenameStep, - isRenameWorkbench, - isSetSketchPlane, - isUpdateExtrusion -} from "./typeGuards" -// import { _isDevelopment } from "../+layout" +import type { Realization as WasmRealization, Message } from "cadmium" +import { isMessage } from "cadmium/cadmium.guard" // prettier-ignore const log = (function () { const context = "[projectUtils.ts]"; const color = "aqua"; return Function.prototype.bind.call(console.log, console, `%c${context}`, `font-weight:bold;color:${color};`) })() @@ -71,6 +55,11 @@ export function arraysEqual(a: any[], b: any[]) { } function sendWasmMessage(message: Message) { + if (!isMessage(message)) { + log("[sendWasmMessage][isMessage] message is not valid:", message) + return + } + let wp = get(wasmProject) const messageStr = JSON.stringify(message) log("[sendWasmMessage] sending message:", message) @@ -98,24 +87,24 @@ export function updateExtrusion(extrusionId: string, sketchId: string, length: n extrusion_id: extrusionId } } - const isValid = checkWasmMessage(message) + const isValid = isMessage(message) const hasFaceIds = notEmpty(message.UpdateExtrusion.face_ids) if (isValid) { sendWasmMessage(message) workbenchIsStale.set(true) if (hasFaceIds) { - log("[updateExtrusion]", "[checkWasmMessage]", "is valid,", "sending message...", message) + log("[updateExtrusion]", "[isMessage]", "is valid,", "sending message...", message) // sendWasmMessage(message) } else log( "[updateExtrusion]", - "[checkWasmMessage]", + "[isMessage]", "is valid,", "but face_ids is empty,", "NOT sending message:", message ) - } else log("[updateExtrusion]", "[checkWasmMessage]", "is bogus,", "abort message send!", message) + } else log("[updateExtrusion]", "[isMessage]", "is bogus,", "abort message send!", message) // sendWasmMessage(message) @@ -131,7 +120,6 @@ export function setSketchPlane(sketchId: string, planeId: string) { plane_id: planeId } } - checkWasmMessage(message) sendWasmMessage(message) workbenchIsStale.set(true) } @@ -144,7 +132,6 @@ export function newSketchOnPlane() { sketch_name: "" // a sensible name will be generated by the rust code } } - checkWasmMessage(message) sendWasmMessage(message) workbenchIsStale.set(true) } @@ -154,7 +141,7 @@ export function newExtrusion() { // log("[newExtrusion] workbench:", workbench) // log("[newExtrusion] bench:", bench) - let sketchId = null + let sketchId = "" for (let step of bench.history) { if (step.data.type === "Sketch") { sketchId = step.unique_id @@ -180,7 +167,6 @@ export function newExtrusion() { // we check for face_ids: [] to contain numbers but we send an empty array // todo: maybe change isNewExtrusion? although with the rust api it is possible to send an array of faceids so we ought to check them... // probably best to alter isNewExtrusion to allow an empty array or a number[] - checkWasmMessage(message) sendWasmMessage(message) workbenchIsStale.set(true) } @@ -223,7 +209,6 @@ function deleteLines(workbenchIdx: number, sketchIdx: string, lineIds: number[]) line_ids: lineIds } } - checkWasmMessage(message) sendWasmMessage(message) } @@ -235,7 +220,6 @@ function deleteArcs(workbenchIdx: number, sketchIdx: string, arcIds: number[]) { arc_ids: arcIds } } - checkWasmMessage(message) sendWasmMessage(message) } @@ -247,7 +231,6 @@ function deleteCircles(workbenchIdx: number, sketchIdx: string, circleIds: numbe circle_ids: circleIds } } - checkWasmMessage(message) sendWasmMessage(message) } @@ -261,7 +244,6 @@ export function addRectangleBetweenPoints(sketchIdx: string, point1: number, poi end_id: point2 } } - checkWasmMessage(message) sendWasmMessage(message) workbenchIsStale.set(true) } @@ -286,7 +268,6 @@ export function addCircleBetweenPoints(sketchIdx: string, point1: string, point2 edge_id: parseInt(point2, 10) } } - checkWasmMessage(message) sendWasmMessage(message) workbenchIsStale.set(true) } @@ -300,7 +281,6 @@ export function addLineToSketch(sketchIdx: string, point1: number, point2: numbe end_point_id: point2 } } - checkWasmMessage(message) sendWasmMessage(message) workbenchIsStale.set(true) } @@ -316,7 +296,6 @@ export function addPointToSketch(sketchIdx: string, point: Vector2Like, hidden: hidden: hidden } } - checkWasmMessage(message) const reply = sendWasmMessage(message) // log("[addPointToSketch sendWasmMessage]", "message:", message, "reply:", reply) @@ -351,7 +330,6 @@ export function renameStep(stepIdx: number, newName: string): void { new_name: newName } } - checkWasmMessage(message) sendWasmMessage(message) } @@ -363,7 +341,6 @@ export function renameWorkbench(newName: string): void { new_name: newName } } - checkWasmMessage(message) sendWasmMessage(message) } @@ -522,117 +499,3 @@ function reduceToInts(data: string[], errorCallback: (id: any) => void): number[ function notEmpty(array: unknown[]): boolean { return array && Array.isArray(array) && array.length > 0 } - -function checkWasmMessage(message: Message, abort = true, logError = true): boolean { - const key = Object.keys(message)[0] - const command = message[key as keyof Message] - if (!command) { - console.error("[projectUtils.ts] [checkWasmMessage]", "messageType not found:", key, message) - return false - } - log("[checkWasmMessage]", "checking...", key, message) - - switch (key) { - case "UpdateExtrusion": - if (!isUpdateExtrusion(command)) { - logOrAbort() - return false - } - return true - - case "SetSketchPlane": - if (!isSetSketchPlane(command)) { - logOrAbort() - return false - } - return true - - case "NewSketchOnPlane": - if (!isNewSketchOnPlane(command)) { - logOrAbort() - return false - } - return true - - case "NewExtrusion": - if (!isNewExtrusion(command)) { - logOrAbort() - return false - } - return true - - case "DeleteLines": - if (!isDeleteLines(command)) { - logOrAbort() - return false - } - return true - - case "DeleteArcs": - if (!isDeleteArcs(command)) { - logOrAbort() - return false - } - return true - - case "DeleteCircles": - if (!isDeleteCircles(command)) { - logOrAbort() - return false - } - return true - - case "NewRectangleBetweenPoints": - if (!isNewRectangleBetweenPoints(command)) { - logOrAbort() - return false - } - return true - - case "NewCircleBetweenPoints": - if (!isNewCircleBetweenPoints(command)) { - logOrAbort() - return false - } - return true - - case "NewLineOnSketch": - if (!isNewLineOnSketch(command)) { - logOrAbort() - return false - } - return true - - case "NewPointOnSketch2": - if (!isNewPointOnSketch2(command)) { - logOrAbort() - return false - } - return true - - case "RenameStep": - if (!isRenameStep(command)) { - logOrAbort() - return false - } - return true - - case "RenameWorkbench": - if (!isRenameWorkbench(command)) { - logOrAbort() - return false - } - return true - - default: - console.error("[projectUtils.ts] [checkWasmMessage]", "messageType typeGuard not implemented:", key) - return false - } - - function logOrAbort() { - const error = `[${key}] message failed typecheck:` - if (logError) console.error("[projectUtils.ts]", error, message) - // if (abort && _isDevelopment()) throw new Error(`"[projectUtils.ts]" ${error}`) - return false - } -} diff --git a/packages/shared/typeGuards.ts b/packages/shared/typeGuards.ts index 7d41f704..bde4d4a8 100644 --- a/packages/shared/typeGuards.ts +++ b/packages/shared/typeGuards.ts @@ -17,10 +17,7 @@ import type { PreviewGeometry, Plane, Point, - PointById, SketchPoint, - PointById, - Vector2Vector3PointById, PointLikeById, PointsById, PointsLikeById, @@ -68,22 +65,9 @@ import type { TruckSolid, SolidRealized, ExtrusionSketchData, - UpdateExtrusion, - SetSketchPlane, - NewSketchOnPlane, - NewExtrusion, - DeleteLines, - DeleteArcs, - DeleteCircles, - NewRectangleBetweenPoints, - NewCircleBetweenPoints, - NewLineOnSketch, - NewPointOnSketch2, - RenameStep, - Message, MessageHistory, - RenameWorkbench } from "./types" +import { isMessage } from "cadmium/cadmium.guard" import { Vector2 } from "three" import { Vector3 } from "three" @@ -986,170 +970,6 @@ export function isUpdateExtrusion(obj: unknown): obj is UpdateExtrusion { ) } -export function isSetSketchPlane(obj: unknown): obj is SetSketchPlane { - const typedObj = obj as SetSketchPlane - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - typeof typedObj["plane_id"] === "string" - ) -} - -export function isNewSketchOnPlane(obj: unknown): obj is NewSketchOnPlane { - const typedObj = obj as NewSketchOnPlane - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["plane_id"] === "string" && - typeof typedObj["sketch_name"] === "string" - ) -} - -export function isNewExtrusion(obj: unknown): obj is NewExtrusion { - const typedObj = obj as NewExtrusion - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - Array.isArray(typedObj["face_ids"]) && - typedObj["face_ids"].every((e: any) => typeof e === "number") && - typeof typedObj["length"] === "number" && - typeof typedObj["offset"] === "number" && - typeof typedObj["extrusion_name"] === "string" && - typeof typedObj["direction"] === "string" - ) -} - -export function isDeleteLines(obj: unknown): obj is DeleteLines { - const typedObj = obj as DeleteLines - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - Array.isArray(typedObj["line_ids"]) && - typedObj["line_ids"].every((e: any) => typeof e === "number") - ) -} - -export function isDeleteArcs(obj: unknown): obj is DeleteArcs { - const typedObj = obj as DeleteArcs - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - Array.isArray(typedObj["arc_ids"]) && - typedObj["arc_ids"].every((e: any) => typeof e === "number") - ) -} - -export function isDeleteCircles(obj: unknown): obj is DeleteCircles { - const typedObj = obj as DeleteCircles - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - Array.isArray(typedObj["circle_ids"]) && - typedObj["circle_ids"].every((e: any) => typeof e === "number") - ) -} - -export function isNewRectangleBetweenPoints(obj: unknown): obj is NewRectangleBetweenPoints { - const typedObj = obj as NewRectangleBetweenPoints - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - typeof typedObj["start_id"] === "number" && - typeof typedObj["end_id"] === "number" - ) -} - -export function isNewCircleBetweenPoints(obj: unknown): obj is NewCircleBetweenPoints { - const typedObj = obj as NewCircleBetweenPoints - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - typeof typedObj["center_id"] === "number" && - typeof typedObj["edge_id"] === "number" - ) -} - -export function isNewLineOnSketch(obj: unknown): obj is NewLineOnSketch { - const typedObj = obj as NewLineOnSketch - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - typeof typedObj["start_point_id"] === "number" && - typeof typedObj["end_point_id"] === "number" - ) -} - -export function isNewPointOnSketch2(obj: unknown): obj is NewPointOnSketch2 { - const typedObj = obj as NewPointOnSketch2 - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["sketch_id"] === "string" && - typeof typedObj["x"] === "number" && - typeof typedObj["y"] === "number" && - typeof typedObj["hidden"] === "boolean" - ) -} - -export function isRenameStep(obj: unknown): obj is RenameStep { - const typedObj = obj as RenameStep - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["step_id"] === "number" && - typeof typedObj["new_name"] === "string" - ) -} - -export function isRenameWorkbench(obj: unknown): obj is RenameWorkbench { - const typedObj = obj as RenameWorkbench - return ( - ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - typeof typedObj["workbench_id"] === "number" && - typeof typedObj["new_name"] === "string" - ) -} - -export function isMessage(obj: unknown): obj is Message { - const typedObj = obj as Message - return ( - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isUpdateExtrusion(typedObj["UpdateExtrusion"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isSetSketchPlane(typedObj["SetSketchPlane"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isNewSketchOnPlane(typedObj["NewSketchOnPlane"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isNewExtrusion(typedObj["NewExtrusion"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isDeleteLines(typedObj["DeleteLines"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isDeleteArcs(typedObj["DeleteArcs"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isDeleteCircles(typedObj["DeleteCircles"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isNewRectangleBetweenPoints(typedObj["NewRectangleBetweenPoints"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isNewCircleBetweenPoints(typedObj["NewCircleBetweenPoints"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isNewLineOnSketch(typedObj["NewLineOnSketch"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isNewPointOnSketch2(typedObj["NewPointOnSketch2"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isRenameStep(typedObj["RenameStep"]) as boolean)) || - (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && - (isRenameWorkbench(typedObj["RenameWorkbench"]) as boolean)) - ) -} - export function isMessageHistory(obj: unknown): obj is MessageHistory { const typedObj = obj as MessageHistory return ( diff --git a/packages/shared/types.d.ts b/packages/shared/types.d.ts index b496584a..9bcb6d13 100644 --- a/packages/shared/types.d.ts +++ b/packages/shared/types.d.ts @@ -1,4 +1,5 @@ import type { Vector2, Vector3, Vector2Like, Vector3Like } from "three" +import { Line2, Arc2, Circle2, Point2, Constraint, Message } from "cadmium"; interface IDictionary { [id: string]: TValue @@ -220,135 +221,6 @@ interface PlaneRealized { plane: Plane } -// ========= io messages sent to rust ========= -interface UpdateExtrusion { - workbench_id: number - sketch_id: string - face_ids: number[] - length: number - offset: number - extrusion_name: string - direction: string - extrusion_id: string -} - -interface SetSketchPlane { - workbench_id: number - sketch_id: string - plane_id: string -} - -interface NewSketchOnPlane { - workbench_id: number - plane_id: string - sketch_name: string -} - -interface NewExtrusion { - workbench_id: number - sketch_id: string - face_ids: number[] - length: number - offset: number - extrusion_name: string - direction: string -} - -interface DeleteLines { - workbench_id: number - sketch_id: string - line_ids: number[] -} - -interface DeleteArcs { - workbench_id: number - sketch_id: string - arc_ids: number[] -} - -interface DeleteCircles { - workbench_id: number - sketch_id: string - circle_ids: number[] -} - -interface NewRectangleBetweenPoints { - workbench_id: number - sketch_id: string - start_id: number - end_id: number -} - -interface NewCircleBetweenPoints { - workbench_id: number - sketch_id: string - center_id: number - edge_id: number -} - -interface NewLineOnSketch { - workbench_id: number - sketch_id: string - start_point_id: number - end_point_id: number -} - -interface NewPointOnSketch2 { - workbench_id: number - sketch_id: string - x: Vector2["x"] - y: Vector2["y"] - hidden: boolean -} - -interface RenameStep { - workbench_id: number - step_id: number - new_name: string -} - -interface RenameWorkbench { - workbench_id: number - new_name: string -} - -export type Message_GeneratedFromRust = - | { RenameWorkbench: { workbench_id: number; new_name: string } } - | { RenameStep: { workbench_id: number; step_id: number; new_name: string } } - | { RenameProject: { new_name: string } } - | { DeleteLines: { workbench_id: number; sketch_id: string; line_ids: number[] } } - | { DeleteArcs: { workbench_id: number; sketch_id: string; arc_ids: number[] } } - | { DeleteCircles: { workbench_id: number; sketch_id: string; circle_ids: number[] } } - | { NewPointOnSketch: { workbench_id: number; sketch_id: string; point_id: number; x: number; y: number } } - | { NewPointOnSketch2: { workbench_id: number; sketch_id: string; x: number; y: number; hidden: boolean } } - | { NewCircleBetweenPoints: { workbench_id: number; sketch_id: string; center_id: number; edge_id: number } } - | { NewRectangleBetweenPoints: { workbench_id: number; sketch_id: string; start_id: number; end_id: number } } - | { NewLineOnSketch: { workbench_id: number; sketch_id: string; start_point_id: number; end_point_id: number } } - | { DeleteLineSegment: { workbench_id: number; sketch_name: string; line_segment_id: number } } - | { StepSketch: { workbench_id: number; sketch_name: string; steps: number } } - | { SolveSketch: { workbench_id: number; sketch_name: string; max_steps: number } } - | { NewSketchOnPlane: { workbench_id: number; sketch_name: string; plane_id: string } } - | { SetSketchPlane: { workbench_id: number; sketch_id: string; plane_id: string } } - | { DeleteSketch: { workbench_id: number; sketch_name: string } } - | { NewExtrusion: { workbench_id: number; extrusion_name: string; sketch_id: string; face_ids: number[]; length: number; offset: number; direction: Direction } } - | { UpdateExtrusion: { workbench_id: number; extrusion_name: string; extrusion_id: string; sketch_id: string; face_ids: number[]; length: number; offset: number; direction: Direction } } - | { UpdateExtrusionLength: { workbench_id: number; extrusion_name: string; length: number } } - -type Message = - | { UpdateExtrusion: UpdateExtrusion } - | { SetSketchPlane: SetSketchPlane } - | { NewSketchOnPlane: NewSketchOnPlane } - | { NewExtrusion: NewExtrusion } - | { DeleteLines: DeleteLines } - | { DeleteArcs: DeleteArcs } - | { DeleteCircles: DeleteCircles } - | { NewRectangleBetweenPoints: NewRectangleBetweenPoints } - | { NewCircleBetweenPoints: NewCircleBetweenPoints } - | { NewLineOnSketch: NewLineOnSketch } - | { NewPointOnSketch2: NewPointOnSketch2 } - | { RenameStep: RenameStep } - | { RenameWorkbench: RenameWorkbench } - interface MessageHistory { message: Message result: any