onshape 0.1.1 → 0.1.2

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.
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FeatureStudioManager = void 0;
4
+ exports.loadText = loadText;
5
+ const node_fs_1 = require("node:fs");
6
+ class FeatureStudioManager {
7
+ client;
8
+ constructor(client) {
9
+ this.client = client;
10
+ }
11
+ async create(documentId, workspaceId, name) {
12
+ return this.client.post(`/api/v6/featurestudios/d/${documentId}/w/${workspaceId}`, { name });
13
+ }
14
+ async getContents(documentId, workspaceId, elementId) {
15
+ return this.client.get(`/api/v6/featurestudios/d/${documentId}/w/${workspaceId}/e/${elementId}`);
16
+ }
17
+ async setContents(documentId, workspaceId, elementId, contents) {
18
+ return this.client.post(`/api/v6/featurestudios/d/${documentId}/w/${workspaceId}/e/${elementId}`, { contents });
19
+ }
20
+ async getSpecs(documentId, workspaceId, elementId) {
21
+ return this.client.get(`/api/v6/featurestudios/d/${documentId}/w/${workspaceId}/e/${elementId}/featurespecs`);
22
+ }
23
+ }
24
+ exports.FeatureStudioManager = FeatureStudioManager;
25
+ function loadText(inline, file) {
26
+ const raw = file ? (0, node_fs_1.readFileSync)(file, "utf8") : inline;
27
+ if (!raw)
28
+ throw new Error("Expected text via --contents or --contents-file");
29
+ return raw;
30
+ }
@@ -4,8 +4,11 @@ exports.planeId = planeId;
4
4
  exports.parsePoint2 = parsePoint2;
5
5
  exports.buildCircleSketch = buildCircleSketch;
6
6
  exports.buildCircleAxisSketch = buildCircleAxisSketch;
7
+ exports.buildCandyCanePathSketch = buildCandyCanePathSketch;
7
8
  exports.buildExtrude = buildExtrude;
8
9
  exports.buildRevolve = buildRevolve;
10
+ exports.buildOffsetPlane = buildOffsetPlane;
11
+ exports.buildSweep = buildSweep;
9
12
  exports.buildBooleanUnion = buildBooleanUnion;
10
13
  const INCH_TO_METER = 0.0254;
11
14
  const PLANE_IDS = {
@@ -73,20 +76,47 @@ function lineEntity(id, start, end, isConstruction = false) {
73
76
  isConstruction,
74
77
  };
75
78
  }
76
- function sketch(name, sketchPlaneId, entities) {
79
+ function arcEntity(id, center, radius, startAngle, endAngle) {
80
+ if (radius <= 0)
81
+ throw new Error("Arc radius must be positive.");
82
+ return {
83
+ btType: "BTMSketchCurveSegment-155",
84
+ entityId: id,
85
+ startPointId: `${id}.start`,
86
+ endPointId: `${id}.end`,
87
+ centerId: `${id}.center`,
88
+ startParam: (startAngle * Math.PI) / 180,
89
+ endParam: (endAngle * Math.PI) / 180,
90
+ geometry: {
91
+ btType: "BTCurveGeometryCircle-115",
92
+ radius: toMeters(radius),
93
+ xCenter: toMeters(center[0]),
94
+ yCenter: toMeters(center[1]),
95
+ xDir: 1,
96
+ yDir: 0,
97
+ clockwise: false,
98
+ },
99
+ isConstruction: false,
100
+ };
101
+ }
102
+ function sketchPlaneParameter(sketchPlaneId, featureId) {
103
+ if (featureId) {
104
+ return pQuery("sketchPlane", `query = qCreatedBy(makeId("${featureId}"), EntityType.FACE);`, featureId);
105
+ }
106
+ return {
107
+ btType: "BTMParameterQueryList-148",
108
+ queries: [{ btType: "BTMIndividualQuery-138", deterministicIds: [sketchPlaneId] }],
109
+ parameterId: "sketchPlane",
110
+ };
111
+ }
112
+ function sketch(name, sketchPlaneId, entities, featureId) {
77
113
  return {
78
114
  feature: {
79
115
  btType: "BTMSketch-151",
80
116
  featureType: "newSketch",
81
117
  name,
82
118
  suppressed: false,
83
- parameters: [
84
- {
85
- btType: "BTMParameterQueryList-148",
86
- queries: [{ btType: "BTMIndividualQuery-138", deterministicIds: [sketchPlaneId] }],
87
- parameterId: "sketchPlane",
88
- },
89
- ],
119
+ parameters: [sketchPlaneParameter(sketchPlaneId, featureId)],
90
120
  entities,
91
121
  constraints: [],
92
122
  },
@@ -141,6 +171,20 @@ function pQuery(parameterId, queryString, featureId) {
141
171
  libraryRelationType: "NONE",
142
172
  };
143
173
  }
174
+ function pDeterministicQuery(parameterId, deterministicIds) {
175
+ return {
176
+ btType: "BTMParameterQueryList-148",
177
+ queries: [
178
+ {
179
+ btType: "BTMIndividualQuery-138",
180
+ deterministicIds,
181
+ },
182
+ ],
183
+ parameterId,
184
+ parameterName: "",
185
+ libraryRelationType: "NONE",
186
+ };
187
+ }
144
188
  function sketchRegion(parameterId, sketchFeatureId) {
145
189
  return {
146
190
  btType: "BTMParameterQueryList-148",
@@ -159,8 +203,11 @@ function sketchRegion(parameterId, sketchFeatureId) {
159
203
  libraryRelationType: "NONE",
160
204
  };
161
205
  }
206
+ function sketchEdges(parameterId, sketchFeatureId) {
207
+ return pQuery(parameterId, `query = qCreatedBy(makeId("${sketchFeatureId}"), EntityType.EDGE);`, sketchFeatureId);
208
+ }
162
209
  function buildCircleSketch(input) {
163
- return sketch(input.name, planeId(input.plane), [circleEntity("circle.1", input.center, input.radius)]);
210
+ return sketch(input.name, planeId(input.plane), [circleEntity("circle.1", input.center, input.radius)], input.planeFeatureId);
164
211
  }
165
212
  function buildCircleAxisSketch(input) {
166
213
  return sketch(input.name, planeId(input.plane), [
@@ -168,6 +215,27 @@ function buildCircleAxisSketch(input) {
168
215
  lineEntity("axis.1", input.axisStart, input.axisEnd, true),
169
216
  ]);
170
217
  }
218
+ function buildCandyCanePathSketch(input) {
219
+ const top = input.bottom + input.straightHeight;
220
+ const center = [input.x - input.hookRadius, top];
221
+ const totalSegments = Math.max(2, Math.floor(input.segments));
222
+ const arcLength = input.hookRadius * Math.abs((input.hookAngle * Math.PI) / 180);
223
+ const straightShare = input.straightHeight / (input.straightHeight + arcLength);
224
+ const straightSegments = Math.max(1, Math.round(totalSegments * straightShare));
225
+ const arcSegments = Math.max(1, totalSegments - straightSegments);
226
+ const entities = [];
227
+ for (let index = 0; index < straightSegments; index += 1) {
228
+ const y1 = input.bottom + (input.straightHeight * index) / straightSegments;
229
+ const y2 = input.bottom + (input.straightHeight * (index + 1)) / straightSegments;
230
+ entities.push(lineEntity(`path.stem.${index + 1}`, [input.x, y1], [input.x, y2]));
231
+ }
232
+ for (let index = 0; index < arcSegments; index += 1) {
233
+ const start = (input.hookAngle * index) / arcSegments;
234
+ const end = (input.hookAngle * (index + 1)) / arcSegments;
235
+ entities.push(arcEntity(`path.hook.${index + 1}`, center, input.hookRadius, start, end));
236
+ }
237
+ return sketch(input.name, planeId(input.plane), entities);
238
+ }
171
239
  function buildExtrude(input) {
172
240
  return {
173
241
  btType: "BTFeatureDefinitionCall-1406",
@@ -209,6 +277,47 @@ function buildRevolve(input) {
209
277
  },
210
278
  };
211
279
  }
280
+ function buildOffsetPlane(input) {
281
+ return {
282
+ btType: "BTFeatureDefinitionCall-1406",
283
+ feature: {
284
+ btType: "BTMFeature-134",
285
+ featureType: "cPlane",
286
+ name: input.name,
287
+ suppressed: false,
288
+ namespace: "",
289
+ parameters: [
290
+ pEnum("cplaneType", "CPlaneType", "OFFSET"),
291
+ pDeterministicQuery("entities", [planeId(input.basePlane)]),
292
+ pQuantity("offset", input.offset, "in"),
293
+ pBool("oppositeDirection", false),
294
+ ],
295
+ },
296
+ };
297
+ }
298
+ function buildSweep(input) {
299
+ return {
300
+ btType: "BTFeatureDefinitionCall-1406",
301
+ feature: {
302
+ btType: "BTMFeature-134",
303
+ featureType: "sweep",
304
+ name: input.name,
305
+ suppressed: false,
306
+ namespace: "",
307
+ parameters: [
308
+ pEnum("bodyType", "ExtendedToolBodyType", "SOLID"),
309
+ pEnum("operationType", "NewBodyOperationType", input.operationType),
310
+ sketchRegion("profiles", input.profileSketchFeatureId),
311
+ sketchEdges("path", input.pathSketchFeatureId),
312
+ pEnum("profileControl", "ProfileControlMode", "NONE"),
313
+ pBool("hasTwist", false),
314
+ pBool("hasScale", false),
315
+ pBool("trimEnds", true),
316
+ pBool("defaultScope", true),
317
+ ],
318
+ },
319
+ };
320
+ }
212
321
  function buildBooleanUnion() {
213
322
  return {
214
323
  btType: "BTFeatureDefinitionCall-1406",
package/dist/cli.js CHANGED
@@ -40,6 +40,7 @@ const credentials_1 = require("./credentials");
40
40
  const client_1 = require("./api/client");
41
41
  const documents_1 = require("./api/documents");
42
42
  const edges_1 = require("./api/edges");
43
+ const featurestudio_1 = require("./api/featurestudio");
43
44
  const partstudio_1 = require("./api/partstudio");
44
45
  const modeling_1 = require("./builders/modeling");
45
46
  const output_1 = require("./output");
@@ -102,13 +103,20 @@ async function run(argv) {
102
103
  case "create-part-studio":
103
104
  case "delete-feature":
104
105
  case "delete-element":
106
+ case "create-feature-studio":
107
+ case "get-feature-studio":
108
+ case "set-feature-studio":
109
+ case "get-feature-studio-specs":
105
110
  case "add-feature":
106
111
  case "update-feature":
107
112
  case "rollback":
108
113
  case "sketch-circle":
109
114
  case "sketch-circle-axis":
115
+ case "sketch-candy-cane-path":
110
116
  case "extrude":
111
117
  case "revolve":
118
+ case "sweep":
119
+ case "offset-plane":
112
120
  case "boolean-union":
113
121
  case "validate-partstudio":
114
122
  case "get-edges":
@@ -239,6 +247,7 @@ async function handleReadCommand(parsed) {
239
247
  const client = new client_1.OnshapeClient(creds);
240
248
  const docs = new documents_1.DocumentManager(client);
241
249
  const partstudios = new partstudio_1.PartStudioManager(client);
250
+ const featurestudios = new featurestudio_1.FeatureStudioManager(client);
242
251
  const edges = new edges_1.EdgeQuery(client);
243
252
  switch (parsed.command) {
244
253
  case "list-documents": {
@@ -331,6 +340,32 @@ async function handleReadCommand(parsed) {
331
340
  (0, output_1.emit)(await client.delete(`/api/v9/elements/d/${doc}/w/${ws}/e/${elem}`));
332
341
  return;
333
342
  }
343
+ case "create-feature-studio": {
344
+ const { doc, ws } = docWorkspace(parsed.options);
345
+ (0, output_1.emit)(await featurestudios.create(doc, ws, requiredOption(parsed.options, "name")));
346
+ return;
347
+ }
348
+ case "get-feature-studio": {
349
+ const { doc, ws, elem } = dwe(parsed.options);
350
+ (0, output_1.emit)(await featurestudios.getContents(doc, ws, elem));
351
+ return;
352
+ }
353
+ case "set-feature-studio": {
354
+ const { doc, ws, elem } = dwe(parsed.options);
355
+ try {
356
+ (0, output_1.emit)(await featurestudios.setContents(doc, ws, elem, (0, featurestudio_1.loadText)(stringOption(parsed.options, "contents"), stringOption(parsed.options, "contentsFile"))));
357
+ }
358
+ catch (error) {
359
+ const message = error instanceof Error ? error.message : String(error);
360
+ throw new output_1.CliError(message, null, 2);
361
+ }
362
+ return;
363
+ }
364
+ case "get-feature-studio-specs": {
365
+ const { doc, ws, elem } = dwe(parsed.options);
366
+ (0, output_1.emit)(await featurestudios.getSpecs(doc, ws, elem));
367
+ return;
368
+ }
334
369
  case "add-feature": {
335
370
  const { doc, ws, elem } = dwe(parsed.options);
336
371
  const feature = requiredJson(parsed.options);
@@ -353,6 +388,7 @@ async function handleReadCommand(parsed) {
353
388
  (0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildCircleSketch)({
354
389
  name: stringOption(parsed.options, "name") ?? "Sketch circle",
355
390
  plane: stringOption(parsed.options, "plane") ?? "Front",
391
+ planeFeatureId: stringOption(parsed.options, "planeFeature"),
356
392
  center: parsePointOption(parsed.options, "center"),
357
393
  radius: requiredNumberOption(parsed.options, "radius"),
358
394
  }), !parsed.options.noValidate));
@@ -370,6 +406,20 @@ async function handleReadCommand(parsed) {
370
406
  }), !parsed.options.noValidate));
371
407
  return;
372
408
  }
409
+ case "sketch-candy-cane-path": {
410
+ const { doc, ws, elem } = dwe(parsed.options);
411
+ (0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildCandyCanePathSketch)({
412
+ name: stringOption(parsed.options, "name") ?? "Candy cane centerline",
413
+ plane: stringOption(parsed.options, "plane") ?? "Front",
414
+ x: numberOption(parsed.options, "x", 0),
415
+ bottom: numberOption(parsed.options, "bottom", 0),
416
+ straightHeight: requiredNumberOption(parsed.options, "straightHeight"),
417
+ hookRadius: requiredNumberOption(parsed.options, "hookRadius"),
418
+ hookAngle: numberOption(parsed.options, "hookAngle", 210),
419
+ segments: numberOption(parsed.options, "segments", 24),
420
+ }), !parsed.options.noValidate));
421
+ return;
422
+ }
373
423
  case "extrude": {
374
424
  const { doc, ws, elem } = dwe(parsed.options);
375
425
  (0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildExtrude)({
@@ -390,6 +440,25 @@ async function handleReadCommand(parsed) {
390
440
  }), !parsed.options.noValidate));
391
441
  return;
392
442
  }
443
+ case "sweep": {
444
+ const { doc, ws, elem } = dwe(parsed.options);
445
+ (0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildSweep)({
446
+ name: stringOption(parsed.options, "name") ?? "Sweep",
447
+ profileSketchFeatureId: requiredOption(parsed.options, "profile"),
448
+ pathSketchFeatureId: requiredOption(parsed.options, "path"),
449
+ operationType: stringOption(parsed.options, "op") ?? "NEW",
450
+ }), !parsed.options.noValidate));
451
+ return;
452
+ }
453
+ case "offset-plane": {
454
+ const { doc, ws, elem } = dwe(parsed.options);
455
+ (0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildOffsetPlane)({
456
+ name: stringOption(parsed.options, "name") ?? "Offset plane",
457
+ basePlane: stringOption(parsed.options, "basePlane") ?? "Top",
458
+ offset: requiredNumberOption(parsed.options, "offset"),
459
+ }), !parsed.options.noValidate));
460
+ return;
461
+ }
393
462
  case "boolean-union": {
394
463
  const { doc, ws, elem } = dwe(parsed.options);
395
464
  (0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildBooleanUnion)(), !parsed.options.noValidate));
@@ -557,13 +626,20 @@ Commands:
557
626
  create-part-studio
558
627
  delete-feature
559
628
  delete-element
629
+ create-feature-studio
630
+ get-feature-studio
631
+ set-feature-studio
632
+ get-feature-studio-specs
560
633
  add-feature
561
634
  update-feature
562
635
  rollback
563
636
  sketch-circle
564
637
  sketch-circle-axis
638
+ sketch-candy-cane-path
565
639
  extrude
566
640
  revolve
641
+ sweep
642
+ offset-plane
567
643
  boolean-union
568
644
  validate-partstudio
569
645
  get-edges
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "onshape",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Node.js CLI for Onshape CAD automation with the same JSON contract as onshape-cli.",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",