cyclecad 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API-BUILD-MANIFEST.txt +339 -0
- package/API-SERVER.md +535 -0
- package/Architecture-Deck.pptx +0 -0
- package/CLAUDE.md +172 -11
- package/CLI-BUILD-SUMMARY.md +504 -0
- package/CLI-INDEX.md +356 -0
- package/CLI-README.md +466 -0
- package/COLLABORATION-INTEGRATION-GUIDE.md +325 -0
- package/CONNECTED_FABS_GUIDE.md +612 -0
- package/CONNECTED_FABS_README.md +310 -0
- package/DELIVERABLES.md +343 -0
- package/DFM-ANALYZER-INTEGRATION.md +368 -0
- package/DFM-QUICK-START.js +253 -0
- package/Dockerfile +69 -0
- package/IMPLEMENTATION.md +327 -0
- package/LICENSE +31 -0
- package/MARKETPLACE_QUICK_REFERENCE.txt +294 -0
- package/MCP-INDEX.md +264 -0
- package/QUICKSTART-API.md +388 -0
- package/QUICKSTART-CLI.md +211 -0
- package/QUICKSTART-MCP.md +196 -0
- package/README-MCP.md +208 -0
- package/TEST-TOKEN-ENGINE.md +319 -0
- package/TOKEN-ENGINE-SUMMARY.md +266 -0
- package/TOKENS-README.md +263 -0
- package/TOOLS-REFERENCE.md +254 -0
- package/app/index.html +168 -3
- package/app/js/TOKEN-INTEGRATION.md +391 -0
- package/app/js/agent-api.js +3 -3
- package/app/js/ai-copilot.js +1435 -0
- package/app/js/cam-pipeline.js +840 -0
- package/app/js/collaboration-ui.js +995 -0
- package/app/js/collaboration.js +1116 -0
- package/app/js/connected-fabs-example.js +404 -0
- package/app/js/connected-fabs.js +1449 -0
- package/app/js/dfm-analyzer.js +1760 -0
- package/app/js/marketplace.js +1994 -0
- package/app/js/material-library.js +2115 -0
- package/app/js/token-dashboard.js +563 -0
- package/app/js/token-engine.js +743 -0
- package/app/test-agent.html +1801 -0
- package/bin/cyclecad-cli.js +662 -0
- package/bin/cyclecad-mcp +2 -0
- package/bin/server.js +242 -0
- package/cycleCAD-Architecture.pptx +0 -0
- package/cycleCAD-Investor-Deck.pptx +0 -0
- package/demo-mcp.sh +60 -0
- package/docs/API-SERVER-SUMMARY.md +375 -0
- package/docs/API-SERVER.md +667 -0
- package/docs/CAM-EXAMPLES.md +344 -0
- package/docs/CAM-INTEGRATION.md +612 -0
- package/docs/CAM-QUICK-REFERENCE.md +199 -0
- package/docs/CLI-INTEGRATION.md +510 -0
- package/docs/CLI.md +872 -0
- package/docs/MARKETPLACE-API-SCHEMA.json +564 -0
- package/docs/MARKETPLACE-INTEGRATION.md +467 -0
- package/docs/MARKETPLACE-SETUP.html +439 -0
- package/docs/MCP-SERVER.md +403 -0
- package/examples/api-client-example.js +488 -0
- package/examples/api-client-example.py +359 -0
- package/examples/batch-manufacturing.txt +28 -0
- package/examples/batch-simple.txt +26 -0
- package/model-marketplace.html +1273 -0
- package/package.json +14 -3
- package/server/api-server.js +1120 -0
- package/server/mcp-server.js +1161 -0
- package/test-api-server.js +432 -0
- package/test-mcp.js +198 -0
- package/~$cycleCAD-Investor-Deck.pptx +0 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cycleCAD API Client Example (JavaScript/Node.js)
|
|
3
|
+
*
|
|
4
|
+
* Simple client for the cycleCAD REST API with both HTTP and WebSocket support.
|
|
5
|
+
*
|
|
6
|
+
* Usage (Node.js):
|
|
7
|
+
* node api-client-example.js
|
|
8
|
+
* node api-client-example.js --host localhost --port 3000
|
|
9
|
+
*
|
|
10
|
+
* Usage (Browser):
|
|
11
|
+
* Include <script src="api-client-example.js"></script>
|
|
12
|
+
* const client = new CycleCADClient('http://localhost:3000');
|
|
13
|
+
* client.execute('sketch.start', {plane: 'XY'}).then(r => console.log(r));
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// CycleCAD HTTP Client
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
class CycleCADClient {
|
|
21
|
+
constructor(baseUrl = 'http://localhost:3000', apiKey = null) {
|
|
22
|
+
this.baseUrl = baseUrl;
|
|
23
|
+
this.apiKey = apiKey;
|
|
24
|
+
this.isNode = typeof window === 'undefined';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Make HTTP request (works in Node.js and browser)
|
|
29
|
+
*/
|
|
30
|
+
async _request(method, endpoint, data = null) {
|
|
31
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
32
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
33
|
+
|
|
34
|
+
if (this.apiKey) {
|
|
35
|
+
headers['X-API-Key'] = this.apiKey;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const options = { method, headers };
|
|
39
|
+
if (data) options.body = JSON.stringify(data);
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
let response;
|
|
43
|
+
|
|
44
|
+
// Use native fetch if available (browser or Node 18+)
|
|
45
|
+
if (typeof fetch !== 'undefined') {
|
|
46
|
+
response = await fetch(url, options);
|
|
47
|
+
} else {
|
|
48
|
+
// Fallback for older Node.js versions
|
|
49
|
+
const http = require('http');
|
|
50
|
+
response = await this._nodeRequest(url, options);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const error = await response.json();
|
|
55
|
+
throw new Error(`API Error (${response.status}): ${error.error || response.statusText}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return await response.json();
|
|
59
|
+
} catch (e) {
|
|
60
|
+
throw new Error(`Request failed: ${e.message}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Node.js HTTP request fallback
|
|
66
|
+
*/
|
|
67
|
+
_nodeRequest(url, options) {
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
const urlObj = new URL(url);
|
|
70
|
+
const http = require(urlObj.protocol === 'https:' ? 'https' : 'http');
|
|
71
|
+
const isHttps = urlObj.protocol === 'https:';
|
|
72
|
+
|
|
73
|
+
const opts = {
|
|
74
|
+
hostname: urlObj.hostname,
|
|
75
|
+
port: urlObj.port || (isHttps ? 443 : 80),
|
|
76
|
+
path: urlObj.pathname + urlObj.search,
|
|
77
|
+
method: options.method,
|
|
78
|
+
headers: options.headers
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const req = http.request(opts, (res) => {
|
|
82
|
+
let data = '';
|
|
83
|
+
res.on('data', chunk => data += chunk);
|
|
84
|
+
res.on('end', () => {
|
|
85
|
+
resolve({
|
|
86
|
+
ok: res.statusCode < 400,
|
|
87
|
+
status: res.statusCode,
|
|
88
|
+
json: () => Promise.resolve(JSON.parse(data))
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
req.on('error', reject);
|
|
94
|
+
if (options.body) req.write(options.body);
|
|
95
|
+
req.end();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Execute single command
|
|
101
|
+
*/
|
|
102
|
+
async execute(method, params = {}) {
|
|
103
|
+
return this._request('POST', '/api/execute', { method, params });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Execute batch of commands
|
|
108
|
+
*/
|
|
109
|
+
async batch(commands) {
|
|
110
|
+
return this._request('POST', '/api/batch', { commands });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get API schema
|
|
115
|
+
*/
|
|
116
|
+
async getSchema() {
|
|
117
|
+
return this._request('GET', '/api/schema');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get server health
|
|
122
|
+
*/
|
|
123
|
+
async getHealth() {
|
|
124
|
+
return this._request('GET', '/api/health');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get command history
|
|
129
|
+
*/
|
|
130
|
+
async getHistory(count = 20) {
|
|
131
|
+
return this._request('GET', `/api/history?count=${count}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get all models
|
|
136
|
+
*/
|
|
137
|
+
async getModels() {
|
|
138
|
+
return this._request('GET', '/api/models');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get specific model
|
|
143
|
+
*/
|
|
144
|
+
async getModel(modelId) {
|
|
145
|
+
return this._request('GET', `/api/models/${modelId}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Delete model
|
|
150
|
+
*/
|
|
151
|
+
async deleteModel(modelId) {
|
|
152
|
+
return this._request('DELETE', `/api/models/${modelId}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Connect WebSocket
|
|
157
|
+
*/
|
|
158
|
+
connectWebSocket() {
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
const wsUrl = this.baseUrl.replace(/^http/, 'ws') + '/api/ws';
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const ws = new (this.isNode ? require('ws') : WebSocket)(wsUrl);
|
|
164
|
+
|
|
165
|
+
ws.onopen = () => {
|
|
166
|
+
console.log('✓ WebSocket connected');
|
|
167
|
+
resolve(new CycleCADWebSocket(ws));
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
ws.onerror = (e) => {
|
|
171
|
+
reject(new Error(`WebSocket error: ${e.message}`));
|
|
172
|
+
};
|
|
173
|
+
} catch (e) {
|
|
174
|
+
reject(e);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// CycleCAD WebSocket Client
|
|
182
|
+
// ============================================================================
|
|
183
|
+
|
|
184
|
+
class CycleCADWebSocket {
|
|
185
|
+
constructor(ws) {
|
|
186
|
+
this.ws = ws;
|
|
187
|
+
this.listeners = {};
|
|
188
|
+
this.pendingRequests = new Map();
|
|
189
|
+
this.requestId = 0;
|
|
190
|
+
|
|
191
|
+
ws.onmessage = (event) => {
|
|
192
|
+
const data = typeof event.data === 'string'
|
|
193
|
+
? JSON.parse(event.data)
|
|
194
|
+
: JSON.parse(event.data.toString());
|
|
195
|
+
|
|
196
|
+
// Emit events
|
|
197
|
+
if (data.type) {
|
|
198
|
+
this._emit(data.type, data);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Resolve pending requests
|
|
202
|
+
if (data.requestId && this.pendingRequests.has(data.requestId)) {
|
|
203
|
+
const { resolve } = this.pendingRequests.get(data.requestId);
|
|
204
|
+
this.pendingRequests.delete(data.requestId);
|
|
205
|
+
resolve(data);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
ws.onerror = (e) => this._emit('error', e);
|
|
210
|
+
ws.onclose = () => this._emit('close');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Execute command via WebSocket
|
|
215
|
+
*/
|
|
216
|
+
async execute(method, params = {}) {
|
|
217
|
+
const requestId = ++this.requestId;
|
|
218
|
+
const message = { requestId, method, params };
|
|
219
|
+
|
|
220
|
+
return new Promise((resolve) => {
|
|
221
|
+
this.pendingRequests.set(requestId, { resolve });
|
|
222
|
+
this.ws.send(JSON.stringify(message));
|
|
223
|
+
|
|
224
|
+
// Timeout after 30s
|
|
225
|
+
setTimeout(() => {
|
|
226
|
+
if (this.pendingRequests.has(requestId)) {
|
|
227
|
+
this.pendingRequests.delete(requestId);
|
|
228
|
+
resolve({ ok: false, error: 'Request timeout' });
|
|
229
|
+
}
|
|
230
|
+
}, 30000);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Listen for events
|
|
236
|
+
*/
|
|
237
|
+
on(event, callback) {
|
|
238
|
+
if (!this.listeners[event]) this.listeners[event] = [];
|
|
239
|
+
this.listeners[event].push(callback);
|
|
240
|
+
return () => {
|
|
241
|
+
this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Emit event
|
|
247
|
+
*/
|
|
248
|
+
_emit(event, data) {
|
|
249
|
+
if (this.listeners[event]) {
|
|
250
|
+
this.listeners[event].forEach(cb => {
|
|
251
|
+
try { cb(data); } catch (e) { console.error(`Event listener error: ${e.message}`); }
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Close connection
|
|
258
|
+
*/
|
|
259
|
+
close() {
|
|
260
|
+
this.ws.close();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ============================================================================
|
|
265
|
+
// EXAMPLES
|
|
266
|
+
// ============================================================================
|
|
267
|
+
|
|
268
|
+
async function example1_simplePartHTTP(client) {
|
|
269
|
+
console.log('\n' + '='.repeat(60));
|
|
270
|
+
console.log('EXAMPLE 1: Simple Part (HTTP)');
|
|
271
|
+
console.log('='.repeat(60) + '\n');
|
|
272
|
+
|
|
273
|
+
// Start sketch
|
|
274
|
+
console.log('1. Starting sketch...');
|
|
275
|
+
let r = await client.execute('sketch.start', { plane: 'XY' });
|
|
276
|
+
console.log(` ✓ ${r.result.message}`);
|
|
277
|
+
|
|
278
|
+
// Draw circle
|
|
279
|
+
console.log('2. Drawing circle (r=25mm)...');
|
|
280
|
+
r = await client.execute('sketch.circle', { cx: 0, cy: 0, radius: 25 });
|
|
281
|
+
console.log(` ✓ Circle: ${r.result.entityId}`);
|
|
282
|
+
|
|
283
|
+
// End sketch
|
|
284
|
+
console.log('3. Ending sketch...');
|
|
285
|
+
r = await client.execute('sketch.end', {});
|
|
286
|
+
|
|
287
|
+
// Extrude
|
|
288
|
+
console.log('4. Extruding 50mm...');
|
|
289
|
+
r = await client.execute('ops.extrude', {
|
|
290
|
+
height: 50,
|
|
291
|
+
symmetric: false,
|
|
292
|
+
material: 'steel'
|
|
293
|
+
});
|
|
294
|
+
console.log(` ✓ Extrusion: ${r.result.featureId}`);
|
|
295
|
+
console.log(` Volume: ${r.result.volume} mm³`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
async function example2_batchOperations(client) {
|
|
299
|
+
console.log('\n' + '='.repeat(60));
|
|
300
|
+
console.log('EXAMPLE 2: Batch Operations');
|
|
301
|
+
console.log('='.repeat(60) + '\n');
|
|
302
|
+
|
|
303
|
+
const commands = [
|
|
304
|
+
{ method: 'sketch.start', params: { plane: 'XY' } },
|
|
305
|
+
{ method: 'sketch.rect', params: { x: 0, y: 0, width: 60, height: 40 } },
|
|
306
|
+
{ method: 'sketch.end', params: {} },
|
|
307
|
+
{ method: 'ops.extrude', params: { height: 30, material: 'aluminum' } }
|
|
308
|
+
];
|
|
309
|
+
|
|
310
|
+
console.log('Executing 4 commands in batch...');
|
|
311
|
+
const r = await client.batch(commands);
|
|
312
|
+
|
|
313
|
+
if (r.ok) {
|
|
314
|
+
console.log(`✓ All ${r.executed} commands succeeded (${r.elapsed}ms)`);
|
|
315
|
+
r.results.forEach((res, i) => {
|
|
316
|
+
console.log(` [${i + 1}] ${commands[i].method}: ${res.elapsed}ms`);
|
|
317
|
+
});
|
|
318
|
+
} else {
|
|
319
|
+
console.log(`✗ Failed with ${r.errors.length} errors`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async function example3_queryValidation(client) {
|
|
324
|
+
console.log('\n' + '='.repeat(60));
|
|
325
|
+
console.log('EXAMPLE 3: Query & Validation');
|
|
326
|
+
console.log('='.repeat(60) + '\n');
|
|
327
|
+
|
|
328
|
+
console.log('1. Available materials:');
|
|
329
|
+
let r = await client.execute('query.materials', {});
|
|
330
|
+
r.result.materials.forEach(m => console.log(` • ${m}`));
|
|
331
|
+
|
|
332
|
+
console.log('\n2. Validate mass:');
|
|
333
|
+
r = await client.execute('validate.mass', {
|
|
334
|
+
target: 'extrude_1234',
|
|
335
|
+
material: 'steel'
|
|
336
|
+
});
|
|
337
|
+
console.log(` Mass: ${r.result.mass} kg`);
|
|
338
|
+
|
|
339
|
+
console.log('\n3. Estimate cost:');
|
|
340
|
+
r = await client.execute('validate.cost', {
|
|
341
|
+
target: 'extrude_1234',
|
|
342
|
+
process: 'FDM',
|
|
343
|
+
material: 'PLA'
|
|
344
|
+
});
|
|
345
|
+
console.log(` Cost: $${r.result.estimatedCost} USD`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async function example4_serverInfo(client) {
|
|
349
|
+
console.log('\n' + '='.repeat(60));
|
|
350
|
+
console.log('EXAMPLE 4: Server Information');
|
|
351
|
+
console.log('='.repeat(60) + '\n');
|
|
352
|
+
|
|
353
|
+
console.log('1. Health check:');
|
|
354
|
+
const health = await client.getHealth();
|
|
355
|
+
console.log(` Status: ${health.status}`);
|
|
356
|
+
console.log(` Version: ${health.version}`);
|
|
357
|
+
console.log(` Uptime: ${health.uptime}s`);
|
|
358
|
+
console.log(` Commands available: ${health.commands}`);
|
|
359
|
+
console.log(` Commands executed: ${health.commandsExecuted}`);
|
|
360
|
+
|
|
361
|
+
console.log('\n2. Command history (last 5):');
|
|
362
|
+
const history = await client.getHistory(5);
|
|
363
|
+
console.log(` Total: ${history.total}`);
|
|
364
|
+
history.recent.forEach(entry => {
|
|
365
|
+
const status = entry.ok ? '✓' : '✗';
|
|
366
|
+
console.log(` [${status}] ${entry.method} (${entry.elapsed}ms)`);
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async function example5_websocket(client) {
|
|
371
|
+
console.log('\n' + '='.repeat(60));
|
|
372
|
+
console.log('EXAMPLE 5: WebSocket Real-Time Connection');
|
|
373
|
+
console.log('='.repeat(60) + '\n');
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
console.log('Connecting to WebSocket...');
|
|
377
|
+
const ws = await client.connectWebSocket();
|
|
378
|
+
|
|
379
|
+
// Listen for events
|
|
380
|
+
ws.on('ping', (data) => {
|
|
381
|
+
console.log(` ← ping (${new Date(data.timestamp).toLocaleTimeString()})`);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
ws.on('error', (e) => {
|
|
385
|
+
console.log(` ✗ Error: ${e.message}`);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
ws.on('close', () => {
|
|
389
|
+
console.log(' ✗ Connection closed');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// Send commands
|
|
393
|
+
console.log('\n1. Sending commands via WebSocket:');
|
|
394
|
+
|
|
395
|
+
console.log(' → sketch.start');
|
|
396
|
+
let r = await ws.execute('sketch.start', { plane: 'XY' });
|
|
397
|
+
console.log(` ← ${r.result.message}`);
|
|
398
|
+
|
|
399
|
+
console.log(' → sketch.circle');
|
|
400
|
+
r = await ws.execute('sketch.circle', { cx: 0, cy: 0, radius: 30 });
|
|
401
|
+
console.log(` ← Circle: ${r.result.entityId}`);
|
|
402
|
+
|
|
403
|
+
console.log(' → sketch.end');
|
|
404
|
+
r = await ws.execute('sketch.end', {});
|
|
405
|
+
console.log(` ← ${r.result.message}`);
|
|
406
|
+
|
|
407
|
+
// Keep connection open for 3 seconds to see pings
|
|
408
|
+
console.log('\n2. Listening for pings (3s)...');
|
|
409
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
410
|
+
|
|
411
|
+
console.log('\n3. Closing connection...');
|
|
412
|
+
ws.close();
|
|
413
|
+
} catch (e) {
|
|
414
|
+
console.log(` ✗ WebSocket error: ${e.message}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// ============================================================================
|
|
419
|
+
// MAIN
|
|
420
|
+
// ============================================================================
|
|
421
|
+
|
|
422
|
+
async function main() {
|
|
423
|
+
const args = require('minimist')(process.argv.slice(2));
|
|
424
|
+
const host = args.host || 'localhost';
|
|
425
|
+
const port = args.port || 3000;
|
|
426
|
+
const example = args.example || 'all';
|
|
427
|
+
|
|
428
|
+
console.log('\n' + '█'.repeat(60));
|
|
429
|
+
console.log('█ cycleCAD API Client — Example Usage');
|
|
430
|
+
console.log('█'.repeat(60));
|
|
431
|
+
console.log(`\nConnecting to ${host}:${port}...`);
|
|
432
|
+
|
|
433
|
+
try {
|
|
434
|
+
const client = new CycleCADClient(`http://${host}:${port}`, args['api-key']);
|
|
435
|
+
|
|
436
|
+
// Test connection
|
|
437
|
+
const health = await client.getHealth();
|
|
438
|
+
console.log(`✓ Connected to cycleCAD v${health.version}\n`);
|
|
439
|
+
|
|
440
|
+
// Run examples
|
|
441
|
+
const examples = {
|
|
442
|
+
all: [
|
|
443
|
+
example4_serverInfo,
|
|
444
|
+
example1_simplePartHTTP,
|
|
445
|
+
example2_batchOperations,
|
|
446
|
+
example3_queryValidation,
|
|
447
|
+
example5_websocket
|
|
448
|
+
],
|
|
449
|
+
simple: [example1_simplePartHTTP],
|
|
450
|
+
batch: [example2_batchOperations],
|
|
451
|
+
query: [example3_queryValidation],
|
|
452
|
+
server: [example4_serverInfo],
|
|
453
|
+
websocket: [example5_websocket]
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const exampleFns = examples[example] || examples.all;
|
|
457
|
+
|
|
458
|
+
for (const fn of exampleFns) {
|
|
459
|
+
try {
|
|
460
|
+
await fn(client);
|
|
461
|
+
} catch (e) {
|
|
462
|
+
console.log(`\n✗ Example failed: ${e.message}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
console.log('\n' + '█'.repeat(60));
|
|
467
|
+
console.log('█ Examples completed!');
|
|
468
|
+
console.log('█'.repeat(60) + '\n');
|
|
469
|
+
} catch (e) {
|
|
470
|
+
console.log(`\n✗ Connection failed: ${e.message}`);
|
|
471
|
+
console.log('\nMake sure the API server is running:');
|
|
472
|
+
console.log(` npm run server`);
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Export for use as module
|
|
478
|
+
if (typeof module !== 'undefined') {
|
|
479
|
+
module.exports = { CycleCADClient, CycleCADWebSocket };
|
|
480
|
+
|
|
481
|
+
// Run examples if called directly
|
|
482
|
+
if (require.main === module) {
|
|
483
|
+
main().catch(e => {
|
|
484
|
+
console.error(e);
|
|
485
|
+
process.exit(1);
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
}
|