fluidcad 0.0.32 → 0.0.34
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/README.md +3 -2
- package/bin/commands/init.js +55 -0
- package/bin/commands/mcp.js +33 -0
- package/bin/commands/serve.js +77 -0
- package/bin/fluidcad.js +15 -107
- package/lib/dist/common/scene-object.d.ts +4 -1
- package/lib/dist/common/scene-object.js +9 -2
- package/lib/dist/common/solid.d.ts +4 -1
- package/lib/dist/common/solid.js +13 -0
- package/lib/dist/core/2d/tarc.d.ts +20 -2
- package/lib/dist/core/2d/tarc.js +24 -0
- package/lib/dist/core/index.d.ts +2 -1
- package/lib/dist/core/index.js +1 -0
- package/lib/dist/core/interfaces.d.ts +107 -2
- package/lib/dist/core/load.d.ts +2 -2
- package/lib/dist/core/repeat.js +62 -46
- package/lib/dist/core/rib.d.ts +18 -0
- package/lib/dist/core/rib.js +37 -0
- package/lib/dist/features/2d/arc.d.ts +8 -2
- package/lib/dist/features/2d/arc.js +94 -17
- package/lib/dist/features/2d/back.js +3 -2
- package/lib/dist/features/2d/sketch.d.ts +4 -0
- package/lib/dist/features/2d/sketch.js +21 -0
- package/lib/dist/features/2d/tarc-constrained.d.ts +2 -0
- package/lib/dist/features/2d/tarc-constrained.js +8 -0
- package/lib/dist/features/2d/tarc-radius-to-object.d.ts +16 -0
- package/lib/dist/features/2d/tarc-radius-to-object.js +58 -0
- package/lib/dist/features/2d/tarc-to-object.d.ts +18 -0
- package/lib/dist/features/2d/tarc-to-object.js +66 -0
- package/lib/dist/features/2d/tarc-to-point-tangent.d.ts +2 -0
- package/lib/dist/features/2d/tarc-to-point-tangent.js +3 -0
- package/lib/dist/features/2d/tarc-to-point.d.ts +2 -0
- package/lib/dist/features/2d/tarc-to-point.js +3 -0
- package/lib/dist/features/2d/tarc-with-tangent.d.ts +2 -0
- package/lib/dist/features/2d/tarc-with-tangent.js +3 -0
- package/lib/dist/features/2d/tarc.d.ts +2 -0
- package/lib/dist/features/2d/tarc.js +3 -0
- package/lib/dist/features/extrude-base.d.ts +9 -0
- package/lib/dist/features/extrude-base.js +22 -0
- package/lib/dist/features/extrude-to-face.js +1 -5
- package/lib/dist/features/extrude-two-distances.js +1 -2
- package/lib/dist/features/extrude.js +1 -2
- package/lib/dist/features/load.d.ts +6 -0
- package/lib/dist/features/load.js +53 -1
- package/lib/dist/features/mirror-feature.d.ts +3 -2
- package/lib/dist/features/mirror-feature.js +1 -1
- package/lib/dist/features/repeat-circular.d.ts +3 -3
- package/lib/dist/features/repeat-circular.js +8 -1
- package/lib/dist/features/repeat-linear.d.ts +4 -2
- package/lib/dist/features/repeat-linear.js +10 -1
- package/lib/dist/features/repeat-matrix.d.ts +3 -1
- package/lib/dist/features/repeat-matrix.js +7 -2
- package/lib/dist/features/rib.d.ts +31 -0
- package/lib/dist/features/rib.js +321 -0
- package/lib/dist/features/select.d.ts +1 -0
- package/lib/dist/features/select.js +81 -10
- package/lib/dist/features/shell.d.ts +4 -1
- package/lib/dist/features/shell.js +14 -3
- package/lib/dist/filters/edge/belongs-to-face.d.ts +12 -9
- package/lib/dist/filters/edge/belongs-to-face.js +64 -15
- package/lib/dist/filters/filter-builder-base.d.ts +25 -0
- package/lib/dist/filters/filter-builder-base.js +47 -0
- package/lib/dist/filters/filter.js +39 -14
- package/lib/dist/filters/from-object.d.ts +4 -0
- package/lib/dist/filters/from-object.js +10 -0
- package/lib/dist/helpers/clone-transform.d.ts +2 -1
- package/lib/dist/helpers/scene-helpers.d.ts +1 -1
- package/lib/dist/helpers/scene-helpers.js +146 -12
- package/lib/dist/index.d.ts +7 -1
- package/lib/dist/index.js +3 -3
- package/lib/dist/io/file-import.d.ts +5 -1
- package/lib/dist/io/file-import.js +29 -18
- package/lib/dist/math/lazy-matrix.d.ts +31 -0
- package/lib/dist/math/lazy-matrix.js +66 -0
- package/lib/dist/oc/color-transfer.d.ts +19 -8
- package/lib/dist/oc/color-transfer.js +70 -12
- package/lib/dist/oc/constraints/constraint-solver-adaptor.d.ts +5 -0
- package/lib/dist/oc/constraints/constraint-solver-adaptor.js +16 -0
- package/lib/dist/oc/constraints/constraint-solver.d.ts +4 -0
- package/lib/dist/oc/constraints/curve/curve-constraint-solver.d.ts +4 -0
- package/lib/dist/oc/constraints/curve/curve-constraint-solver.js +3 -0
- package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.d.ts +6 -1
- package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.js +4 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.d.ts +8 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.js +111 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.d.ts +8 -0
- package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.js +161 -0
- package/lib/dist/oc/extrude-ops.d.ts +2 -1
- package/lib/dist/oc/extrude-ops.js +51 -2
- package/lib/dist/oc/mesh.d.ts +9 -4
- package/lib/dist/oc/mesh.js +14 -13
- package/lib/dist/oc/rib-ops.d.ts +35 -0
- package/lib/dist/oc/rib-ops.js +619 -0
- package/lib/dist/oc/shell-ops.d.ts +2 -1
- package/lib/dist/oc/shell-ops.js +5 -2
- package/lib/dist/oc/topology-index.d.ts +6 -0
- package/lib/dist/oc/topology-index.js +36 -0
- package/lib/dist/rendering/mesh-builder.d.ts +3 -0
- package/lib/dist/rendering/mesh-builder.js +8 -4
- package/lib/dist/rendering/render-edge.d.ts +2 -1
- package/lib/dist/rendering/render-edge.js +2 -2
- package/lib/dist/rendering/render-face.d.ts +2 -1
- package/lib/dist/rendering/render-face.js +2 -2
- package/lib/dist/rendering/render-solid.d.ts +2 -1
- package/lib/dist/rendering/render-solid.js +3 -5
- package/lib/dist/rendering/render-wire.d.ts +2 -1
- package/lib/dist/rendering/render-wire.js +2 -2
- package/lib/dist/rendering/render.d.ts +4 -0
- package/lib/dist/rendering/render.js +50 -2
- package/lib/dist/rendering/scene-compare.js +3 -0
- package/lib/dist/rendering/scene.d.ts +1 -0
- package/lib/dist/rendering/scene.js +4 -0
- package/lib/dist/scene-manager.d.ts +4 -2
- package/lib/dist/scene-manager.js +12 -4
- package/lib/dist/tests/features/2d/arc.test.js +64 -0
- package/lib/dist/tests/features/2d/back.test.js +17 -1
- package/lib/dist/tests/features/2d/tarc.test.js +157 -0
- package/lib/dist/tests/features/color-lineage.test.js +18 -0
- package/lib/dist/tests/features/filter-positional.test.d.ts +1 -0
- package/lib/dist/tests/features/filter-positional.test.js +129 -0
- package/lib/dist/tests/features/repeat-user-repro.test.d.ts +1 -0
- package/lib/dist/tests/features/repeat-user-repro.test.js +60 -0
- package/lib/dist/tests/features/rib.test.d.ts +1 -0
- package/lib/dist/tests/features/rib.test.js +598 -0
- package/lib/dist/tests/features/shell.test.js +36 -0
- package/lib/dist/tests/global-setup.js +2 -1
- package/lib/dist/tests/helpers/extract-blocks.d.ts +9 -0
- package/lib/dist/tests/helpers/extract-blocks.js +56 -0
- package/lib/dist/tests/llm-docs-examples.test.d.ts +1 -0
- package/lib/dist/tests/llm-docs-examples.test.js +62 -0
- package/lib/dist/tests/scene-compare.test.d.ts +1 -0
- package/lib/dist/tests/scene-compare.test.js +77 -0
- package/lib/dist/tests/setup.js +2 -1
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/llm-docs/.coverage-allowlist.txt +9 -0
- package/llm-docs/api/arc.md +48 -0
- package/llm-docs/api/axis.md +42 -0
- package/llm-docs/api/bezier.md +42 -0
- package/llm-docs/api/booleans.md +44 -0
- package/llm-docs/api/chamfer.md +40 -0
- package/llm-docs/api/circle.md +36 -0
- package/llm-docs/api/color.md +34 -0
- package/llm-docs/api/connect.md +41 -0
- package/llm-docs/api/constraint-qualifiers.md +48 -0
- package/llm-docs/api/copy.md +63 -0
- package/llm-docs/api/cursor-lines.md +50 -0
- package/llm-docs/api/cursor-move.md +61 -0
- package/llm-docs/api/cut.md +55 -0
- package/llm-docs/api/draft.md +36 -0
- package/llm-docs/api/edge-filter.md +57 -0
- package/llm-docs/api/ellipse.md +34 -0
- package/llm-docs/api/extrude.md +74 -0
- package/llm-docs/api/face-filter.md +61 -0
- package/llm-docs/api/fillet.md +51 -0
- package/llm-docs/api/index.json +139 -0
- package/llm-docs/api/line.md +42 -0
- package/llm-docs/api/load.md +37 -0
- package/llm-docs/api/local.md +38 -0
- package/llm-docs/api/loft.md +37 -0
- package/llm-docs/api/mirror.md +44 -0
- package/llm-docs/api/offset.md +36 -0
- package/llm-docs/api/part.md +40 -0
- package/llm-docs/api/plane.md +44 -0
- package/llm-docs/api/polygon.md +37 -0
- package/llm-docs/api/primitive-solids.md +39 -0
- package/llm-docs/api/project-intersect.md +48 -0
- package/llm-docs/api/rect.md +48 -0
- package/llm-docs/api/remove.md +32 -0
- package/llm-docs/api/repeat.md +79 -0
- package/llm-docs/api/revolve.md +38 -0
- package/llm-docs/api/rib.md +40 -0
- package/llm-docs/api/rotate.md +37 -0
- package/llm-docs/api/select.md +41 -0
- package/llm-docs/api/shell.md +41 -0
- package/llm-docs/api/sketch.md +76 -0
- package/llm-docs/api/slot.md +36 -0
- package/llm-docs/api/split-trim.md +42 -0
- package/llm-docs/api/sweep.md +43 -0
- package/llm-docs/api/tarc.md +45 -0
- package/llm-docs/api/tcircle.md +38 -0
- package/llm-docs/api/tline.md +42 -0
- package/llm-docs/api/translate.md +40 -0
- package/llm-docs/api/types/aline.md +35 -0
- package/llm-docs/api/types/arc-angles.md +29 -0
- package/llm-docs/api/types/arc-points.md +48 -0
- package/llm-docs/api/types/axis-like.md +38 -0
- package/llm-docs/api/types/axis.md +21 -0
- package/llm-docs/api/types/boolean-operation.md +50 -0
- package/llm-docs/api/types/circular-repeat-options.md +31 -0
- package/llm-docs/api/types/common.md +32 -0
- package/llm-docs/api/types/cut.md +125 -0
- package/llm-docs/api/types/draft.md +21 -0
- package/llm-docs/api/types/extrudable-geometry.md +23 -0
- package/llm-docs/api/types/extrude.md +194 -0
- package/llm-docs/api/types/geometry.md +51 -0
- package/llm-docs/api/types/hline.md +35 -0
- package/llm-docs/api/types/linear-repeat-options.md +31 -0
- package/llm-docs/api/types/loft.md +154 -0
- package/llm-docs/api/types/mirror.md +35 -0
- package/llm-docs/api/types/offset.md +31 -0
- package/llm-docs/api/types/plane-like.md +35 -0
- package/llm-docs/api/types/plane-transform-options.md +29 -0
- package/llm-docs/api/types/plane.md +21 -0
- package/llm-docs/api/types/point-like.md +22 -0
- package/llm-docs/api/types/point2dlike.md +26 -0
- package/llm-docs/api/types/polygon.md +46 -0
- package/llm-docs/api/types/rect.md +128 -0
- package/llm-docs/api/types/revolve.md +102 -0
- package/llm-docs/api/types/rib.md +133 -0
- package/llm-docs/api/types/scene-object.md +33 -0
- package/llm-docs/api/types/select.md +21 -0
- package/llm-docs/api/types/shell.md +54 -0
- package/llm-docs/api/types/slot.md +43 -0
- package/llm-docs/api/types/sweep.md +189 -0
- package/llm-docs/api/types/tangent-arc-two-objects.md +46 -0
- package/llm-docs/api/types/transformable.md +93 -0
- package/llm-docs/api/types/trim.md +27 -0
- package/llm-docs/api/types/two-objects-tangent-line.md +46 -0
- package/llm-docs/api/types/vertex.md +17 -0
- package/llm-docs/api/types/vline.md +35 -0
- package/llm-docs/concepts/coordinate-system.md +45 -0
- package/llm-docs/concepts/history-and-rollback.md +40 -0
- package/llm-docs/concepts/last-selection.md +49 -0
- package/llm-docs/concepts/scene-graph.md +37 -0
- package/llm-docs/index.json +1750 -0
- package/mcp/dist/client.d.ts +64 -0
- package/mcp/dist/client.js +248 -0
- package/mcp/dist/discovery.d.ts +11 -0
- package/mcp/dist/discovery.js +78 -0
- package/mcp/dist/docs-index.d.ts +81 -0
- package/mcp/dist/docs-index.js +261 -0
- package/mcp/dist/resources.d.ts +4 -0
- package/mcp/dist/resources.js +115 -0
- package/mcp/dist/server.d.ts +12 -0
- package/mcp/dist/server.js +489 -0
- package/mcp/dist/tools/coordination.d.ts +9 -0
- package/mcp/dist/tools/coordination.js +46 -0
- package/mcp/dist/tools/docs.d.ts +66 -0
- package/mcp/dist/tools/docs.js +122 -0
- package/mcp/dist/tools/engine.d.ts +56 -0
- package/mcp/dist/tools/engine.js +145 -0
- package/mcp/dist/tools/inspection.d.ts +75 -0
- package/mcp/dist/tools/inspection.js +121 -0
- package/mcp/dist/tools/screenshot.d.ts +63 -0
- package/mcp/dist/tools/screenshot.js +263 -0
- package/mcp/dist/tools/source.d.ts +84 -0
- package/mcp/dist/tools/source.js +434 -0
- package/mcp/dist/tools/workspaces.d.ts +13 -0
- package/mcp/dist/tools/workspaces.js +33 -0
- package/mcp/dist/types.d.ts +18 -0
- package/mcp/dist/types.js +11 -0
- package/package.json +19 -5
- package/server/dist/code-editor.d.ts +36 -0
- package/server/dist/code-editor.js +8 -0
- package/server/dist/fluidcad-server.d.ts +50 -0
- package/server/dist/fluidcad-server.js +153 -1
- package/server/dist/global-registry.d.ts +30 -0
- package/server/dist/global-registry.js +126 -0
- package/server/dist/index.js +171 -26
- package/server/dist/instance-file.d.ts +31 -0
- package/server/dist/instance-file.js +73 -0
- package/server/dist/lint-fluid-js.d.ts +15 -0
- package/server/dist/lint-fluid-js.js +271 -0
- package/server/dist/routes/editor.d.ts +24 -0
- package/server/dist/routes/editor.js +44 -0
- package/server/dist/routes/export.d.ts +1 -1
- package/server/dist/routes/export.js +45 -8
- package/server/dist/routes/health.d.ts +7 -0
- package/server/dist/routes/health.js +14 -0
- package/server/dist/routes/lint.d.ts +10 -0
- package/server/dist/routes/lint.js +28 -0
- package/server/dist/routes/render.d.ts +33 -0
- package/server/dist/routes/render.js +34 -0
- package/server/dist/routes/scene.d.ts +5 -0
- package/server/dist/routes/scene.js +48 -0
- package/server/dist/routes/screenshot.js +68 -1
- package/server/dist/ws-protocol.d.ts +56 -2
- package/ui/dist/assets/{index-DMw0OYCF.js → index-BdqrMDRu.js} +30 -30
- package/ui/dist/index.html +1 -1
package/README.md
CHANGED
|
@@ -216,10 +216,10 @@ See the full list of commands in the [Neovim plugin README](extension/neovim/REA
|
|
|
216
216
|
<details>
|
|
217
217
|
<summary><strong>Any Other Editor</strong></summary>
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
From your project directory, run the FluidCAD server directly:
|
|
220
220
|
|
|
221
221
|
```bash
|
|
222
|
-
npx fluidcad
|
|
222
|
+
npx fluidcad serve
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
This starts a local server and opens a 3D viewport in your browser. Edit your `.fluid.js` files in any editor -- the viewport updates on save.
|
|
@@ -230,6 +230,7 @@ This starts a local server and opens a 3D viewport in your browser. Edit your `.
|
|
|
230
230
|
|------|-------------|---------|
|
|
231
231
|
| `-w, --workspace <path>` | Path to your project | Current directory |
|
|
232
232
|
| `-p, --port <port>` | Server port | `3100` |
|
|
233
|
+
| `--open` | Open the viewport in your default browser when ready | _off_ |
|
|
233
234
|
|
|
234
235
|
</details>
|
|
235
236
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { writeFileSync, existsSync } from 'fs';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
|
|
4
|
+
const INIT_JS = `import { init } from 'fluidcad'\n\nexport default await init()\n`;
|
|
5
|
+
|
|
6
|
+
const TEST_FLUID_JS = `import { extrude, fillet, rect, shell, sketch } from "fluidcad/core";
|
|
7
|
+
|
|
8
|
+
sketch("xy", () => {
|
|
9
|
+
rect(100, 50).radius(10).centered();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const e = extrude(30);
|
|
13
|
+
|
|
14
|
+
fillet(4, e.startEdges());
|
|
15
|
+
|
|
16
|
+
shell(-2, e.endFaces());
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const JSCONFIG = JSON.stringify({
|
|
20
|
+
compilerOptions: {
|
|
21
|
+
checkJs: true,
|
|
22
|
+
module: 'node20',
|
|
23
|
+
},
|
|
24
|
+
}, null, 2) + '\n';
|
|
25
|
+
|
|
26
|
+
function runInit() {
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
|
|
29
|
+
const initPath = resolve(cwd, 'init.js');
|
|
30
|
+
if (existsSync(initPath)) {
|
|
31
|
+
console.error('init.js already exists in this directory.');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
writeFileSync(initPath, INIT_JS);
|
|
36
|
+
|
|
37
|
+
const testPath = resolve(cwd, 'test.fluid.js');
|
|
38
|
+
if (!existsSync(testPath)) {
|
|
39
|
+
writeFileSync(testPath, TEST_FLUID_JS);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const jsconfigPath = resolve(cwd, 'jsconfig.json');
|
|
43
|
+
if (!existsSync(jsconfigPath)) {
|
|
44
|
+
writeFileSync(jsconfigPath, JSCONFIG);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log('FluidCAD initialized.');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function registerInitCommand(program) {
|
|
51
|
+
program
|
|
52
|
+
.command('init')
|
|
53
|
+
.description('Scaffold init.js, test.fluid.js, and jsconfig.json in the current directory')
|
|
54
|
+
.action(runInit);
|
|
55
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { resolve, dirname } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
const mcpEntry = resolve(__dirname, '..', '..', 'mcp', 'dist', 'server.js');
|
|
6
|
+
|
|
7
|
+
async function runMcp() {
|
|
8
|
+
// stdout is reserved for the MCP protocol. Any incidental console.log from
|
|
9
|
+
// FluidCAD internals would corrupt the stream — route everything to stderr.
|
|
10
|
+
console.log = (...args) => console.error(...args);
|
|
11
|
+
console.info = (...args) => console.error(...args);
|
|
12
|
+
|
|
13
|
+
const mod = await import(mcpEntry);
|
|
14
|
+
if (typeof mod.runStdio !== 'function') {
|
|
15
|
+
console.error('mcp/dist/server.js does not export runStdio.');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
await mod.runStdio();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function registerMcpCommand(program) {
|
|
22
|
+
program
|
|
23
|
+
.command('mcp')
|
|
24
|
+
.description('Run the FluidCAD MCP server over stdio (for Claude Desktop, Claude Code, Cursor, ...)')
|
|
25
|
+
.action(async () => {
|
|
26
|
+
try {
|
|
27
|
+
await runMcp();
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error(err?.stack || err?.message || String(err));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { fork } from 'child_process';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import { createFileWatcher, findFluidFiles } from '../watcher.js';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const serverEntry = resolve(__dirname, '..', '..', 'server', 'dist', 'index.js');
|
|
9
|
+
|
|
10
|
+
function runServe(opts) {
|
|
11
|
+
const workspacePath = resolve(opts.workspace);
|
|
12
|
+
const port = String(opts.port);
|
|
13
|
+
|
|
14
|
+
const server = fork(serverEntry, [], {
|
|
15
|
+
env: {
|
|
16
|
+
...process.env,
|
|
17
|
+
FLUIDCAD_SERVER_PORT: port,
|
|
18
|
+
FLUIDCAD_WORKSPACE_PATH: workspacePath,
|
|
19
|
+
},
|
|
20
|
+
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
server.stdout.on('data', (data) => { process.stdout.write(data); });
|
|
24
|
+
server.stderr.on('data', (data) => { process.stderr.write(data); });
|
|
25
|
+
|
|
26
|
+
let watcher;
|
|
27
|
+
|
|
28
|
+
server.on('message', (msg) => {
|
|
29
|
+
if (msg.type === 'ready') {
|
|
30
|
+
console.log(`FluidCAD server ready at ${msg.url}`);
|
|
31
|
+
if (opts.open) {
|
|
32
|
+
open(msg.url).catch((err) => {
|
|
33
|
+
console.error(`Failed to open browser: ${err.message}`);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (msg.type === 'init-complete') {
|
|
38
|
+
if (msg.success) {
|
|
39
|
+
console.log('FluidCAD initialized successfully.');
|
|
40
|
+
watcher = createFileWatcher(workspacePath, server);
|
|
41
|
+
|
|
42
|
+
const files = findFluidFiles(workspacePath);
|
|
43
|
+
if (files.length > 0) {
|
|
44
|
+
server.send({ type: 'process-file', filePath: files[0] });
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
console.error(`FluidCAD initialization failed: ${msg.error}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
server.on('exit', (code) => {
|
|
54
|
+
if (watcher) { watcher.close(); }
|
|
55
|
+
process.exit(code || 0);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
process.on('SIGINT', () => {
|
|
59
|
+
if (watcher) { watcher.close(); }
|
|
60
|
+
server.kill('SIGINT');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
process.on('SIGTERM', () => {
|
|
64
|
+
if (watcher) { watcher.close(); }
|
|
65
|
+
server.kill('SIGTERM');
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function registerServeCommand(program) {
|
|
70
|
+
program
|
|
71
|
+
.command('serve')
|
|
72
|
+
.description('Start the FluidCAD server and watch .fluid.js files')
|
|
73
|
+
.option('-w, --workspace <path>', 'workspace directory', process.cwd())
|
|
74
|
+
.option('-p, --port <port>', 'server port', '3100')
|
|
75
|
+
.option('--open', 'open the UI in the default browser when ready', false)
|
|
76
|
+
.action(runServe);
|
|
77
|
+
}
|
package/bin/fluidcad.js
CHANGED
|
@@ -1,115 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { readFileSync } from 'fs';
|
|
5
|
+
import { dirname, resolve } from 'path';
|
|
5
6
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { registerInitCommand } from './commands/init.js';
|
|
8
|
+
import { registerServeCommand } from './commands/serve.js';
|
|
9
|
+
import { registerMcpCommand } from './commands/mcp.js';
|
|
9
10
|
|
|
10
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf8'));
|
|
11
13
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
allowPositionals: true,
|
|
18
|
-
});
|
|
14
|
+
const program = new Command()
|
|
15
|
+
.name('fluidcad')
|
|
16
|
+
.description('FluidCAD CLI')
|
|
17
|
+
.version(pkg.version);
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
registerInitCommand(program);
|
|
20
|
+
registerServeCommand(program);
|
|
21
|
+
registerMcpCommand(program);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
if (existsSync(initPath)) {
|
|
25
|
-
console.error('init.js already exists in this directory.');
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
writeFileSync(initPath, `import { init } from 'fluidcad'\n\nexport default await init()\n`);
|
|
30
|
-
|
|
31
|
-
const testPath = resolve(cwd, 'test.fluid.js');
|
|
32
|
-
if (!existsSync(testPath)) {
|
|
33
|
-
writeFileSync(testPath, `import { extrude, fillet, rect, shell, sketch } from "fluidcad/core";
|
|
34
|
-
|
|
35
|
-
sketch("xy", () => {
|
|
36
|
-
rect(100, 50).radius(10).centered();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const e = extrude(30);
|
|
40
|
-
|
|
41
|
-
fillet(4, e.startEdges());
|
|
42
|
-
|
|
43
|
-
shell(-2, e.endFaces());
|
|
44
|
-
`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const jsconfigPath = resolve(cwd, 'jsconfig.json');
|
|
48
|
-
if (!existsSync(jsconfigPath)) {
|
|
49
|
-
writeFileSync(jsconfigPath, JSON.stringify({
|
|
50
|
-
compilerOptions: {
|
|
51
|
-
checkJs: true,
|
|
52
|
-
module: 'node20',
|
|
53
|
-
},
|
|
54
|
-
}, null, 2) + '\n');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
console.log('FluidCAD initialized.');
|
|
58
|
-
process.exit(0);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const serverEntry = resolve(__dirname, '..', 'server', 'dist', 'index.js');
|
|
62
|
-
|
|
63
|
-
const server = fork(serverEntry, [], {
|
|
64
|
-
env: {
|
|
65
|
-
...process.env,
|
|
66
|
-
FLUIDCAD_SERVER_PORT: values.port,
|
|
67
|
-
FLUIDCAD_WORKSPACE_PATH: resolve(values.workspace),
|
|
68
|
-
},
|
|
69
|
-
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
server.stdout.on('data', (data) => {
|
|
73
|
-
process.stdout.write(data);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
server.stderr.on('data', (data) => {
|
|
77
|
-
process.stderr.write(data);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const workspacePath = resolve(values.workspace);
|
|
81
|
-
let watcher;
|
|
82
|
-
|
|
83
|
-
server.on('message', (msg) => {
|
|
84
|
-
if (msg.type === 'ready') {
|
|
85
|
-
console.log(`FluidCAD server ready at ${msg.url}`);
|
|
86
|
-
}
|
|
87
|
-
if (msg.type === 'init-complete') {
|
|
88
|
-
if (msg.success) {
|
|
89
|
-
console.log('FluidCAD initialized successfully.');
|
|
90
|
-
watcher = createFileWatcher(workspacePath, server);
|
|
91
|
-
|
|
92
|
-
const files = findFluidFiles(workspacePath);
|
|
93
|
-
if (files.length > 0) {
|
|
94
|
-
server.send({ type: 'process-file', filePath: files[0] });
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
console.error(`FluidCAD initialization failed: ${msg.error}`);
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
server.on('exit', (code) => {
|
|
104
|
-
process.exit(code || 0);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
process.on('SIGINT', () => {
|
|
108
|
-
if (watcher) { watcher.close(); }
|
|
109
|
-
server.kill('SIGINT');
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
process.on('SIGTERM', () => {
|
|
113
|
-
if (watcher) { watcher.close(); }
|
|
114
|
-
server.kill('SIGTERM');
|
|
115
|
-
});
|
|
23
|
+
program.parseAsync(process.argv);
|
|
@@ -2,6 +2,7 @@ import { Shape, ShapeFilter } from "./shape.js";
|
|
|
2
2
|
import { Face } from "./face.js";
|
|
3
3
|
import { Edge } from "./edge.js";
|
|
4
4
|
import { Matrix4 } from "../math/matrix4.js";
|
|
5
|
+
import { LazyMatrix } from "../math/lazy-matrix.js";
|
|
5
6
|
import { ISceneObject } from "../core/interfaces.js";
|
|
6
7
|
import { FusionScope, OperationMode } from "../features/extrude-options.js";
|
|
7
8
|
import { ShapeType } from "./shape-type.js";
|
|
@@ -59,6 +60,7 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
59
60
|
constructor();
|
|
60
61
|
get id(): string;
|
|
61
62
|
get parentId(): string | null;
|
|
63
|
+
inheritIdentityFrom(other: SceneObject): void;
|
|
62
64
|
private setParent;
|
|
63
65
|
protected setAlwaysVisible(): void;
|
|
64
66
|
isAlwaysVisible(): boolean;
|
|
@@ -89,7 +91,7 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
89
91
|
getDependencies(): SceneObject[];
|
|
90
92
|
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
91
93
|
clone(): SceneObject[];
|
|
92
|
-
setTransform(matrix: Matrix4): void;
|
|
94
|
+
setTransform(matrix: Matrix4 | LazyMatrix): void;
|
|
93
95
|
getTransform(): Matrix4 | null;
|
|
94
96
|
setCloneSource(source: SceneObject): void;
|
|
95
97
|
getCloneSource(): SceneObject | null;
|
|
@@ -150,6 +152,7 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
150
152
|
setOrder(order: number): void;
|
|
151
153
|
getOrder(): number;
|
|
152
154
|
getName(): string;
|
|
155
|
+
hasCustomName(): boolean;
|
|
153
156
|
name(value: string): this;
|
|
154
157
|
guide(): this;
|
|
155
158
|
reusable(): this;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
+
import { LazyMatrix } from "../math/lazy-matrix.js";
|
|
2
3
|
export class SceneObject {
|
|
3
4
|
state;
|
|
4
5
|
children = [];
|
|
@@ -36,6 +37,9 @@ export class SceneObject {
|
|
|
36
37
|
get parentId() {
|
|
37
38
|
return this._parent?.id || null;
|
|
38
39
|
}
|
|
40
|
+
inheritIdentityFrom(other) {
|
|
41
|
+
this._id = other._id;
|
|
42
|
+
}
|
|
39
43
|
setParent(parent) {
|
|
40
44
|
this._parent = parent;
|
|
41
45
|
}
|
|
@@ -197,10 +201,10 @@ export class SceneObject {
|
|
|
197
201
|
return result;
|
|
198
202
|
}
|
|
199
203
|
setTransform(matrix) {
|
|
200
|
-
this._transform = matrix;
|
|
204
|
+
this._transform = matrix instanceof LazyMatrix ? matrix : LazyMatrix.of(matrix);
|
|
201
205
|
}
|
|
202
206
|
getTransform() {
|
|
203
|
-
return this._transform;
|
|
207
|
+
return this._transform ? this._transform.resolve() : null;
|
|
204
208
|
}
|
|
205
209
|
setCloneSource(source) {
|
|
206
210
|
this._cloneSource = source;
|
|
@@ -452,6 +456,9 @@ export class SceneObject {
|
|
|
452
456
|
getName() {
|
|
453
457
|
return this._name ?? this.getType();
|
|
454
458
|
}
|
|
459
|
+
hasCustomName() {
|
|
460
|
+
return this._name !== null;
|
|
461
|
+
}
|
|
455
462
|
name(value) {
|
|
456
463
|
this._name = value;
|
|
457
464
|
return this;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TopoDS_Edge, TopoDS_Face, TopoDS_Solid } from "occjs-wrapper";
|
|
1
|
+
import type { TopoDS_Edge, TopoDS_Face, TopoDS_Solid, TopTools_IndexedDataMapOfShapeListOfShape } from "occjs-wrapper";
|
|
2
2
|
import { ShapeType } from "./shape-type.js";
|
|
3
3
|
import { Shape } from "./shape.js";
|
|
4
4
|
import { Face } from "./face.js";
|
|
@@ -6,6 +6,7 @@ import { Edge } from "./edge.js";
|
|
|
6
6
|
export declare class Solid extends Shape<TopoDS_Solid> {
|
|
7
7
|
private faces;
|
|
8
8
|
private edges;
|
|
9
|
+
private edgeToFacesIndex;
|
|
9
10
|
constructor(solid: TopoDS_Solid);
|
|
10
11
|
getType(): ShapeType;
|
|
11
12
|
isSolid(): boolean;
|
|
@@ -15,6 +16,8 @@ export declare class Solid extends Shape<TopoDS_Solid> {
|
|
|
15
16
|
getFace(face: TopoDS_Face): Face | null;
|
|
16
17
|
hasFace(face: TopoDS_Face): boolean;
|
|
17
18
|
hasEdge(edge: TopoDS_Edge): TopoDS_Edge;
|
|
19
|
+
getEdgeToFacesIndex(): TopTools_IndexedDataMapOfShapeListOfShape;
|
|
20
|
+
dispose(): void;
|
|
18
21
|
copy(): Shape;
|
|
19
22
|
static fromTopoDSSolid(solid: TopoDS_Solid): Solid;
|
|
20
23
|
}
|
package/lib/dist/common/solid.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Explorer } from "../oc/explorer.js";
|
|
2
|
+
import { TopologyIndex } from "../oc/topology-index.js";
|
|
2
3
|
import { Shape } from "./shape.js";
|
|
3
4
|
export class Solid extends Shape {
|
|
4
5
|
faces = null;
|
|
5
6
|
edges = null;
|
|
7
|
+
edgeToFacesIndex = null;
|
|
6
8
|
constructor(solid) {
|
|
7
9
|
super(solid);
|
|
8
10
|
}
|
|
@@ -59,6 +61,17 @@ export class Solid extends Shape {
|
|
|
59
61
|
}
|
|
60
62
|
return null;
|
|
61
63
|
}
|
|
64
|
+
getEdgeToFacesIndex() {
|
|
65
|
+
if (!this.edgeToFacesIndex) {
|
|
66
|
+
this.edgeToFacesIndex = TopologyIndex.buildEdgeToFaces(this.getShape());
|
|
67
|
+
}
|
|
68
|
+
return this.edgeToFacesIndex;
|
|
69
|
+
}
|
|
70
|
+
dispose() {
|
|
71
|
+
this.edgeToFacesIndex?.delete();
|
|
72
|
+
this.edgeToFacesIndex = null;
|
|
73
|
+
super.dispose();
|
|
74
|
+
}
|
|
62
75
|
copy() {
|
|
63
76
|
const copied = new Solid(this.getShape());
|
|
64
77
|
for (const entry of this.colorMap) {
|
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import { Point2DLike } from "../../math/point.js";
|
|
2
2
|
import { QualifiedSceneObject } from "../../features/2d/constraints/qualified-geometry.js";
|
|
3
|
-
import { IGeometry, ISceneObject, ITangentArcTwoObjects } from "../interfaces.js";
|
|
3
|
+
import { IGeometry, ISceneObject, ITangentArcToObject, ITangentArcTwoObjects } from "../interfaces.js";
|
|
4
4
|
interface TArcFunction {
|
|
5
|
+
/**
|
|
6
|
+
* Draws a tangent arc from the current position using the current tangent
|
|
7
|
+
* direction, ending tangent to a target line. The radius is solved
|
|
8
|
+
* automatically; the arc must be tangent to the target but does not need
|
|
9
|
+
* to touch its finite extent. By default the arc curves to the left of
|
|
10
|
+
* the start tangent — chain `.flip()` to curve to the right instead.
|
|
11
|
+
* @param target - The target line (or a qualified line)
|
|
12
|
+
*/
|
|
13
|
+
(target: ISceneObject | QualifiedSceneObject): ITangentArcToObject;
|
|
14
|
+
/**
|
|
15
|
+
* Draws a tangent arc from the current position using the current tangent
|
|
16
|
+
* direction, with the given radius, ending at the first intersection with
|
|
17
|
+
* the target geometry along the arc's sweep direction. A negative radius
|
|
18
|
+
* flips the sweep direction. Supported targets: lines, circles, and arcs.
|
|
19
|
+
* @param radius - The arc radius. A negative value flips the sweep direction.
|
|
20
|
+
* @param target - The target geometry to intersect with
|
|
21
|
+
*/
|
|
22
|
+
(radius: number, target: ISceneObject | QualifiedSceneObject): IGeometry;
|
|
5
23
|
/**
|
|
6
24
|
* Draws a tangent arc with a given radius and end angle.
|
|
7
25
|
* @param radius - The arc radius (defaults to 100). A negative value flips the sweep direction.
|
|
@@ -34,7 +52,7 @@ interface TArcFunction {
|
|
|
34
52
|
*/
|
|
35
53
|
(startPoint: Point2DLike, endPoint: Point2DLike, tangent: Point2DLike): IGeometry;
|
|
36
54
|
/**
|
|
37
|
-
* Draws
|
|
55
|
+
* Draws all possible tangent arcs between two geometry objects.
|
|
38
56
|
* @param c1 - The first geometry object
|
|
39
57
|
* @param c2 - The second geometry object
|
|
40
58
|
* @param radius - The arc radius
|
package/lib/dist/core/2d/tarc.js
CHANGED
|
@@ -3,13 +3,37 @@ import { TangentArc } from "../../features/2d/tarc.js";
|
|
|
3
3
|
import { TangentArcToPoint } from "../../features/2d/tarc-to-point.js";
|
|
4
4
|
import { TangentArcToPointTangent } from "../../features/2d/tarc-to-point-tangent.js";
|
|
5
5
|
import { TangentArcWithTangent } from "../../features/2d/tarc-with-tangent.js";
|
|
6
|
+
import { TangentArcToObject } from "../../features/2d/tarc-to-object.js";
|
|
7
|
+
import { TangentArcRadiusToObject } from "../../features/2d/tarc-radius-to-object.js";
|
|
6
8
|
import { Move } from "../../features/2d/move.js";
|
|
7
9
|
import { normalizePoint2D } from "../../helpers/normalize.js";
|
|
8
10
|
import { registerBuilder } from "../../index.js";
|
|
9
11
|
import { QualifiedSceneObject } from "../../features/2d/constraints/qualified-geometry.js";
|
|
10
12
|
import { TangentArcTwoObjects } from "../../features/2d/tarc-constrained.js";
|
|
13
|
+
import { SceneObject } from "../../common/scene-object.js";
|
|
11
14
|
function build(context) {
|
|
12
15
|
return function tarc() {
|
|
16
|
+
// tArc(target): single scene-object target, radius solved automatically.
|
|
17
|
+
// LazyVertex extends SceneObject but represents a point — fall through to the
|
|
18
|
+
// Point2DLike branch below so tArc(lazyVertex) becomes tArc(endPoint).
|
|
19
|
+
if (arguments.length === 1 &&
|
|
20
|
+
((arguments[0] instanceof SceneObject && !isPoint2DLike(arguments[0])) ||
|
|
21
|
+
arguments[0] instanceof QualifiedSceneObject)) {
|
|
22
|
+
const target = QualifiedSceneObject.from(arguments[0]);
|
|
23
|
+
const arc = new TangentArcToObject(target);
|
|
24
|
+
context.addSceneObject(arc);
|
|
25
|
+
return arc;
|
|
26
|
+
}
|
|
27
|
+
// tArc(radius, target): explicit radius, end at first intersection with target
|
|
28
|
+
if (arguments.length === 2 &&
|
|
29
|
+
typeof arguments[0] === 'number' &&
|
|
30
|
+
(arguments[1] instanceof SceneObject || arguments[1] instanceof QualifiedSceneObject)) {
|
|
31
|
+
const radius = arguments[0];
|
|
32
|
+
const target = QualifiedSceneObject.from(arguments[1]);
|
|
33
|
+
const arc = new TangentArcRadiusToObject(radius, target);
|
|
34
|
+
context.addSceneObject(arc);
|
|
35
|
+
return arc;
|
|
36
|
+
}
|
|
13
37
|
// tarc(c1, c2, radius): fillet arc tangent to two circles/points
|
|
14
38
|
if ((arguments.length === 3 || arguments.length === 4) && typeof arguments[2] === 'number') {
|
|
15
39
|
const o1 = isPoint2DLike(arguments[0]) ? normalizePoint2D(arguments[0]) : arguments[0];
|
package/lib/dist/core/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ISceneObject, ITransformable, IBooleanOperation, IPlane, IAxis, ISelect, IGeometry, IExtrudableGeometry, IRect, ISlot, IPolygon, ITwoObjectsTangentLine, ITangentArcTwoObjects, IExtrude, ICut, ICommon, ISweep, ILoft, IRevolve, IDraft } from "./interfaces.js";
|
|
1
|
+
export type { ISceneObject, ITransformable, IBooleanOperation, IPlane, IAxis, ISelect, IGeometry, IExtrudableGeometry, IRect, ISlot, IPolygon, ITwoObjectsTangentLine, ITangentArcTwoObjects, IExtrude, ICut, ICommon, ISweep, ILoft, IRevolve, IDraft, IRib } from "./interfaces.js";
|
|
2
2
|
export { default as axis } from "./axis.js";
|
|
3
3
|
export { default as local } from "./local.js";
|
|
4
4
|
export { default as plane } from "./plane.js";
|
|
@@ -23,6 +23,7 @@ export { default as repeat } from "./repeat.js";
|
|
|
23
23
|
export { default as load } from "./load.js";
|
|
24
24
|
export { default as loft } from "./loft.js";
|
|
25
25
|
export { default as sweep } from "./sweep.js";
|
|
26
|
+
export { default as rib } from "./rib.js";
|
|
26
27
|
export { default as color } from "./color.js";
|
|
27
28
|
export { default as draft } from "./draft.js";
|
|
28
29
|
export { default as remove } from "./remove.js";
|
package/lib/dist/core/index.js
CHANGED
|
@@ -22,6 +22,7 @@ export { default as repeat } from "./repeat.js";
|
|
|
22
22
|
export { default as load } from "./load.js";
|
|
23
23
|
export { default as loft } from "./loft.js";
|
|
24
24
|
export { default as sweep } from "./sweep.js";
|
|
25
|
+
export { default as rib } from "./rib.js";
|
|
25
26
|
export { default as color } from "./color.js";
|
|
26
27
|
export { default as draft } from "./draft.js";
|
|
27
28
|
export { default as remove } from "./remove.js";
|