fluidcad 0.0.33 → 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 +2 -1
- package/lib/dist/common/scene-object.js +3 -2
- package/lib/dist/core/2d/tarc.d.ts +20 -2
- package/lib/dist/core/2d/tarc.js +24 -0
- package/lib/dist/core/interfaces.d.ts +31 -2
- package/lib/dist/core/repeat.js +62 -46
- 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/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/shell.d.ts +4 -1
- package/lib/dist/features/shell.js +14 -3
- package/lib/dist/helpers/clone-transform.d.ts +2 -1
- package/lib/dist/index.d.ts +7 -1
- package/lib/dist/index.js +3 -3
- package/lib/dist/math/lazy-matrix.d.ts +31 -0
- package/lib/dist/math/lazy-matrix.js +66 -0
- 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/mesh.d.ts +9 -4
- package/lib/dist/oc/mesh.js +14 -13
- package/lib/dist/oc/shell-ops.d.ts +2 -1
- package/lib/dist/oc/shell-ops.js +5 -2
- 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 +2 -2
- 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 +3 -0
- package/lib/dist/rendering/render.js +7 -2
- 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/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/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/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-CFi9p7wR.js → index-BdqrMDRu.js} +21 -21
- 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";
|
|
@@ -90,7 +91,7 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
90
91
|
getDependencies(): SceneObject[];
|
|
91
92
|
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
92
93
|
clone(): SceneObject[];
|
|
93
|
-
setTransform(matrix: Matrix4): void;
|
|
94
|
+
setTransform(matrix: Matrix4 | LazyMatrix): void;
|
|
94
95
|
getTransform(): Matrix4 | null;
|
|
95
96
|
setCloneSource(source: SceneObject): void;
|
|
96
97
|
getCloneSource(): SceneObject | null;
|
|
@@ -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 = [];
|
|
@@ -200,10 +201,10 @@ export class SceneObject {
|
|
|
200
201
|
return result;
|
|
201
202
|
}
|
|
202
203
|
setTransform(matrix) {
|
|
203
|
-
this._transform = matrix;
|
|
204
|
+
this._transform = matrix instanceof LazyMatrix ? matrix : LazyMatrix.of(matrix);
|
|
204
205
|
}
|
|
205
206
|
getTransform() {
|
|
206
|
-
return this._transform;
|
|
207
|
+
return this._transform ? this._transform.resolve() : null;
|
|
207
208
|
}
|
|
208
209
|
setCloneSource(source) {
|
|
209
210
|
this._cloneSource = source;
|
|
@@ -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];
|
|
@@ -157,13 +157,27 @@ export interface IArcPoints extends IExtrudableGeometry {
|
|
|
157
157
|
* Positive = CCW, negative = CW.
|
|
158
158
|
* @param value - The bulge radius.
|
|
159
159
|
*/
|
|
160
|
-
radius(value: number):
|
|
160
|
+
radius(value: number): IArcRadius;
|
|
161
161
|
/**
|
|
162
162
|
* Specifies the circle center point for the arc.
|
|
163
163
|
* Mutually exclusive with `.radius()`.
|
|
164
164
|
* @param value - The center point of the arc's circle.
|
|
165
165
|
*/
|
|
166
|
-
center(value: Point2DLike):
|
|
166
|
+
center(value: Point2DLike): IArcCenter;
|
|
167
|
+
}
|
|
168
|
+
export interface IArcRadius extends IExtrudableGeometry {
|
|
169
|
+
/**
|
|
170
|
+
* Switches to the major arc (> 180°).
|
|
171
|
+
* By default, `.radius()` produces the minor arc (< 180°);
|
|
172
|
+
* `.major()` switches to the complementary major arc on the same circle.
|
|
173
|
+
*/
|
|
174
|
+
major(): this;
|
|
175
|
+
}
|
|
176
|
+
export interface IArcCenter extends IExtrudableGeometry {
|
|
177
|
+
/**
|
|
178
|
+
* Sweeps the arc clockwise from start to end instead of the default counter-clockwise.
|
|
179
|
+
*/
|
|
180
|
+
cw(): this;
|
|
167
181
|
}
|
|
168
182
|
export interface IArcAngles extends IExtrudableGeometry {
|
|
169
183
|
/**
|
|
@@ -298,6 +312,14 @@ export interface ITwoObjectsTangentLine extends IGeometry {
|
|
|
298
312
|
*/
|
|
299
313
|
end(index?: number): LazyVertex;
|
|
300
314
|
}
|
|
315
|
+
export interface ITangentArcToObject extends IGeometry {
|
|
316
|
+
/**
|
|
317
|
+
* Flips the arc to the opposite side of the start tangent. By default,
|
|
318
|
+
* the arc curves to the left of the current tangent direction;
|
|
319
|
+
* `.flip()` switches it to the right.
|
|
320
|
+
*/
|
|
321
|
+
flip(): this;
|
|
322
|
+
}
|
|
301
323
|
export interface ITangentArcTwoObjects extends IGeometry {
|
|
302
324
|
/**
|
|
303
325
|
* Returns the start vertex of the tangent arc.
|
|
@@ -771,6 +793,7 @@ export interface IRib extends IBooleanOperation {
|
|
|
771
793
|
*/
|
|
772
794
|
extend(): this;
|
|
773
795
|
}
|
|
796
|
+
export type ShellJoinType = 'arc' | 'intersection' | 'tangent';
|
|
774
797
|
export interface IShell extends ISceneObject {
|
|
775
798
|
/**
|
|
776
799
|
* Selects the inner wall faces created by the shell operation (from thickness removal).
|
|
@@ -783,4 +806,10 @@ export interface IShell extends ISceneObject {
|
|
|
783
806
|
* @param args - Numeric indices or {@link EdgeFilterBuilder} instances to filter the selection.
|
|
784
807
|
*/
|
|
785
808
|
internalEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
809
|
+
/**
|
|
810
|
+
* Sets the join type used at inner-wall corners.
|
|
811
|
+
* @param type - `'arc'` (default) for rounded blends, `'intersection'` for sharp corners,
|
|
812
|
+
* or `'tangent'` for tangent-continuous blends.
|
|
813
|
+
*/
|
|
814
|
+
join(type: ShellJoinType): this;
|
|
786
815
|
}
|