@bobfrankston/wallplater 1.0.2 → 1.0.4

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/index.ts DELETED
@@ -1,94 +0,0 @@
1
- #!/usr/bin/env node
2
- /*
3
- * wallplater — JSON-driven wall-plate generator (Decora / duplex / blank).
4
- *
5
- * Reads a small JSON config (deep-merged over defaults.json) and emits an
6
- * STL/3MF. Two engines:
7
- * - manifold (default): builds geometry directly via manifold-3d. No OpenSCAD.
8
- * - scad (-scad or engine:"scad"): writes a .scad and shells out to OpenSCAD.
9
- *
10
- * The 3MF is multi-object (plate + labels as separate, individually colourable
11
- * objects). Run (Node 24+, native TS):
12
- * node index.ts ../KitchenBack.json
13
- * node index.ts ../KitchenBack.json -scad
14
- */
15
-
16
- import { writeFileSync, unlinkSync } from "fs";
17
- import { basename, dirname, join } from "path";
18
- import { loadConfig, type Resolved } from "./config.ts";
19
- import { generateScad, runOpenscad, readStl } from "./scad.ts";
20
- import { buildMeshes } from "./geometry.ts";
21
- import { build3mf, writeBinaryStl, type Mesh } from "./threemf.ts";
22
-
23
- interface ModePart { mode: string; label: string; }
24
-
25
- function partList(cfg: Resolved): ModePart[] {
26
- const parts: ModePart[] = [{ mode: "plate", label: "plate" }];
27
- if (cfg.gangs.some((g) => (g.legend ?? "") !== "")) parts.push({ mode: "legend", label: "legend" });
28
- if (cfg.breaker.switch !== "") parts.push({ mode: "breaker", label: "breaker" });
29
- return parts;
30
- }
31
-
32
- function runScadEngine(cfg: Resolved, dir: string): void {
33
- if (cfg.gangs.some((g) => (g.rockers?.length ?? 0) > 0 || (g.header ?? "") !== ""))
34
- console.warn(" ! rocker/header labels are only rendered by the manifold engine; the -scad engine ignores them.");
35
- const scadPath = join(dir, `${cfg.name}.scad`);
36
- writeFileSync(scadPath, generateScad(cfg));
37
- console.log("wrote", basename(scadPath));
38
- if (cfg.output === "scad") return;
39
-
40
- const parts = partList(cfg);
41
- if (cfg.output === "stl") {
42
- for (const p of parts) runOpenscad(cfg.openscad, scadPath, join(dir, `${cfg.name}_${p.label}.stl`), p.mode);
43
- } else {
44
- const tmp: string[] = [];
45
- const meshes: Mesh[] = parts.map((p) => {
46
- const stl = join(dir, `_${cfg.name}_${p.label}.stl`);
47
- runOpenscad(cfg.openscad, scadPath, stl, p.mode);
48
- tmp.push(stl);
49
- return readStl(stl);
50
- });
51
- writeFileSync(join(dir, `${cfg.name}.3mf`), build3mf(meshes));
52
- for (const t of tmp) unlinkSync(t);
53
- console.log(" wrote", `${cfg.name}.3mf`, `(${meshes.length} objects: ${parts.map((p) => p.label).join(", ")})`);
54
- }
55
- }
56
-
57
- async function runManifoldEngine(cfg: Resolved, dir: string): Promise<void> {
58
- if (cfg.output === "scad") { // scad output always needs the scad engine
59
- runScadEngine(cfg, dir);
60
- return;
61
- }
62
- const meshes = await buildMeshes(cfg);
63
- for (const m of meshes) console.log(" built", m.label, `(${m.mesh.tris.length} tris)`);
64
- if (cfg.output === "stl") {
65
- for (const m of meshes) writeFileSync(join(dir, `${cfg.name}_${m.label}.stl`), writeBinaryStl(m.mesh));
66
- } else {
67
- writeFileSync(join(dir, `${cfg.name}.3mf`), build3mf(meshes.map((m) => m.mesh)));
68
- console.log(" wrote", `${cfg.name}.3mf`, `(${meshes.length} objects: ${meshes.map((m) => m.label).join(", ")})`);
69
- }
70
- }
71
-
72
- async function main(): Promise<void> {
73
- const args = process.argv.slice(2);
74
- const flags = args.filter((a) => a.startsWith("-"));
75
- const positional = args.filter((a) => !a.startsWith("-"));
76
- const isScad = (f: string): boolean => f.toLowerCase() === "-scad" || f.toLowerCase() === "--scad";
77
- const unknown = flags.filter((f) => !isScad(f));
78
- if (unknown.length) {
79
- console.error(`unknown option(s): ${unknown.join(" ")}\nusage: node index.ts <config.json> [-scad]`);
80
- process.exit(2);
81
- }
82
- const useScad = flags.some(isScad);
83
- const cfgPath = positional[0] ?? "wallplate.json";
84
- const cfg = loadConfig(cfgPath);
85
- const dir = dirname(cfgPath);
86
- const engine = useScad || cfg.engine === "scad" ? "scad" : "manifold";
87
- console.log(`engine: ${engine}, output: ${cfg.output}`);
88
-
89
- if (engine === "scad") runScadEngine(cfg, dir);
90
- else await runManifoldEngine(cfg, dir);
91
- console.log("done");
92
- }
93
-
94
- main().catch((e) => { console.error(e); process.exit(1); });
package/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "esnext",
4
- "module": "NodeNext",
5
- "moduleResolution": "nodenext",
6
- "allowImportingTsExtensions": true,
7
- "noEmit": true,
8
- "esModuleInterop": true,
9
- "allowSyntheticDefaultImports": true,
10
- "strict": true,
11
- "strictNullChecks": false,
12
- "noImplicitAny": true,
13
- "skipLibCheck": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "types": ["node"],
16
- "newLine": "lf"
17
- },
18
- "include": ["*.ts"],
19
- "exclude": ["node_modules", "cruft", ".git", "tests", "prev"]
20
- }