onshape 0.1.0 → 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.
- package/dist/api/featurestudio.js +30 -0
- package/dist/api/partstudio.js +31 -0
- package/dist/builders/modeling.js +338 -0
- package/dist/cli.js +177 -5
- package/package.json +1 -1
|
@@ -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
|
+
}
|
package/dist/api/partstudio.js
CHANGED
|
@@ -47,6 +47,34 @@ class PartStudioManager {
|
|
|
47
47
|
rollbackIndex: index,
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
+
async validateFeature(documentId, workspaceId, elementId, featureId) {
|
|
51
|
+
const features = await this.getFeatures(documentId, workspaceId, elementId);
|
|
52
|
+
const states = isRecord(features) && isRecord(features.featureStates) ? features.featureStates : {};
|
|
53
|
+
const state = isRecord(states[featureId]) ? states[featureId] : {};
|
|
54
|
+
const status = typeof state.featureStatus === "string" ? state.featureStatus : null;
|
|
55
|
+
if (status === "ERROR") {
|
|
56
|
+
throw new Error(`Feature ${featureId} regenerated with status ERROR.`);
|
|
57
|
+
}
|
|
58
|
+
return { featureId, featureStatus: status };
|
|
59
|
+
}
|
|
60
|
+
async validatePartStudio(documentId, workspaceId, elementId, expectations = {}) {
|
|
61
|
+
const partsRaw = await this.getParts(documentId, workspaceId, elementId);
|
|
62
|
+
const parts = Array.isArray(partsRaw) ? partsRaw : [];
|
|
63
|
+
const massRaw = await this.client.get(`/api/v6/partstudios/d/${documentId}/w/${workspaceId}/e/${elementId}/massproperties`);
|
|
64
|
+
const bodiesRecord = isRecord(massRaw) && isRecord(massRaw.bodies) ? massRaw.bodies : {};
|
|
65
|
+
const bodyCount = Object.keys(bodiesRecord).length;
|
|
66
|
+
if (expectations.parts !== undefined && parts.length !== expectations.parts) {
|
|
67
|
+
throw new Error(`Expected ${expectations.parts} part(s), found ${parts.length}.`);
|
|
68
|
+
}
|
|
69
|
+
if (expectations.bodies !== undefined && bodyCount !== expectations.bodies) {
|
|
70
|
+
throw new Error(`Expected ${expectations.bodies} bod(y/ies), found ${bodyCount}.`);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
parts: parts.length,
|
|
74
|
+
bodies: bodyCount,
|
|
75
|
+
partIds: parts.map((part) => (isRecord(part) ? part.partId : undefined)).filter(Boolean),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
50
78
|
}
|
|
51
79
|
exports.PartStudioManager = PartStudioManager;
|
|
52
80
|
function loadJson(inline, file) {
|
|
@@ -55,3 +83,6 @@ function loadJson(inline, file) {
|
|
|
55
83
|
throw new Error("Expected JSON via --json or --json-file");
|
|
56
84
|
return JSON.parse(raw);
|
|
57
85
|
}
|
|
86
|
+
function isRecord(value) {
|
|
87
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
88
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.planeId = planeId;
|
|
4
|
+
exports.parsePoint2 = parsePoint2;
|
|
5
|
+
exports.buildCircleSketch = buildCircleSketch;
|
|
6
|
+
exports.buildCircleAxisSketch = buildCircleAxisSketch;
|
|
7
|
+
exports.buildCandyCanePathSketch = buildCandyCanePathSketch;
|
|
8
|
+
exports.buildExtrude = buildExtrude;
|
|
9
|
+
exports.buildRevolve = buildRevolve;
|
|
10
|
+
exports.buildOffsetPlane = buildOffsetPlane;
|
|
11
|
+
exports.buildSweep = buildSweep;
|
|
12
|
+
exports.buildBooleanUnion = buildBooleanUnion;
|
|
13
|
+
const INCH_TO_METER = 0.0254;
|
|
14
|
+
const PLANE_IDS = {
|
|
15
|
+
front: "JCC",
|
|
16
|
+
top: "JDC",
|
|
17
|
+
right: "JEC",
|
|
18
|
+
};
|
|
19
|
+
function planeId(name) {
|
|
20
|
+
const value = PLANE_IDS[name.toLowerCase()];
|
|
21
|
+
if (!value)
|
|
22
|
+
throw new Error(`Unknown plane '${name}'. Use Front, Top, or Right.`);
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function parsePoint2(value) {
|
|
26
|
+
const parts = value.split(",").map((part) => Number(part.trim()));
|
|
27
|
+
if (parts.length !== 2 || parts.some((part) => !Number.isFinite(part))) {
|
|
28
|
+
throw new Error(`Expected a 2D point as x,y; got '${value}'.`);
|
|
29
|
+
}
|
|
30
|
+
return [parts[0], parts[1]];
|
|
31
|
+
}
|
|
32
|
+
function toMeters(value) {
|
|
33
|
+
return value * INCH_TO_METER;
|
|
34
|
+
}
|
|
35
|
+
function circleEntity(id, center, radius) {
|
|
36
|
+
return {
|
|
37
|
+
btType: "BTMSketchCurve-4",
|
|
38
|
+
entityId: id,
|
|
39
|
+
centerId: `${id}.center`,
|
|
40
|
+
geometry: {
|
|
41
|
+
btType: "BTCurveGeometryCircle-115",
|
|
42
|
+
radius: toMeters(radius),
|
|
43
|
+
xCenter: toMeters(center[0]),
|
|
44
|
+
yCenter: toMeters(center[1]),
|
|
45
|
+
xDir: 1,
|
|
46
|
+
yDir: 0,
|
|
47
|
+
clockwise: false,
|
|
48
|
+
},
|
|
49
|
+
isConstruction: false,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function lineEntity(id, start, end, isConstruction = false) {
|
|
53
|
+
const x1 = toMeters(start[0]);
|
|
54
|
+
const y1 = toMeters(start[1]);
|
|
55
|
+
const x2 = toMeters(end[0]);
|
|
56
|
+
const y2 = toMeters(end[1]);
|
|
57
|
+
const dx = x2 - x1;
|
|
58
|
+
const dy = y2 - y1;
|
|
59
|
+
const length = Math.hypot(dx, dy);
|
|
60
|
+
if (length === 0)
|
|
61
|
+
throw new Error("Line start and end must be different.");
|
|
62
|
+
return {
|
|
63
|
+
btType: "BTMSketchCurveSegment-155",
|
|
64
|
+
entityId: id,
|
|
65
|
+
startPointId: `${id}.start`,
|
|
66
|
+
endPointId: `${id}.end`,
|
|
67
|
+
startParam: 0,
|
|
68
|
+
endParam: length,
|
|
69
|
+
geometry: {
|
|
70
|
+
btType: "BTCurveGeometryLine-117",
|
|
71
|
+
pntX: x1,
|
|
72
|
+
pntY: y1,
|
|
73
|
+
dirX: dx / length,
|
|
74
|
+
dirY: dy / length,
|
|
75
|
+
},
|
|
76
|
+
isConstruction,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
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) {
|
|
113
|
+
return {
|
|
114
|
+
feature: {
|
|
115
|
+
btType: "BTMSketch-151",
|
|
116
|
+
featureType: "newSketch",
|
|
117
|
+
name,
|
|
118
|
+
suppressed: false,
|
|
119
|
+
parameters: [sketchPlaneParameter(sketchPlaneId, featureId)],
|
|
120
|
+
entities,
|
|
121
|
+
constraints: [],
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function pEnum(parameterId, enumName, value) {
|
|
126
|
+
return {
|
|
127
|
+
btType: "BTMParameterEnum-145",
|
|
128
|
+
namespace: "",
|
|
129
|
+
enumName,
|
|
130
|
+
value,
|
|
131
|
+
parameterId,
|
|
132
|
+
parameterName: "",
|
|
133
|
+
libraryRelationType: "NONE",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function pBool(parameterId, value) {
|
|
137
|
+
return {
|
|
138
|
+
btType: "BTMParameterBoolean-144",
|
|
139
|
+
value,
|
|
140
|
+
parameterId,
|
|
141
|
+
parameterName: "",
|
|
142
|
+
libraryRelationType: "NONE",
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function pQuantity(parameterId, value, units) {
|
|
146
|
+
return {
|
|
147
|
+
btType: "BTMParameterQuantity-147",
|
|
148
|
+
isInteger: false,
|
|
149
|
+
value,
|
|
150
|
+
units: "",
|
|
151
|
+
expression: `${value} ${units}`,
|
|
152
|
+
parameterId,
|
|
153
|
+
parameterName: "",
|
|
154
|
+
libraryRelationType: "NONE",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function pQuery(parameterId, queryString, featureId) {
|
|
158
|
+
return {
|
|
159
|
+
btType: "BTMParameterQueryList-148",
|
|
160
|
+
queries: [
|
|
161
|
+
{
|
|
162
|
+
btType: "BTMIndividualQuery-138",
|
|
163
|
+
queryStatement: null,
|
|
164
|
+
queryString,
|
|
165
|
+
...(featureId ? { featureId } : {}),
|
|
166
|
+
deterministicIds: [],
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
parameterId,
|
|
170
|
+
parameterName: "",
|
|
171
|
+
libraryRelationType: "NONE",
|
|
172
|
+
};
|
|
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
|
+
}
|
|
188
|
+
function sketchRegion(parameterId, sketchFeatureId) {
|
|
189
|
+
return {
|
|
190
|
+
btType: "BTMParameterQueryList-148",
|
|
191
|
+
queries: [
|
|
192
|
+
{
|
|
193
|
+
btType: "BTMIndividualSketchRegionQuery-140",
|
|
194
|
+
queryStatement: null,
|
|
195
|
+
filterInnerLoops: true,
|
|
196
|
+
queryString: `query = qSketchRegion(id + "${sketchFeatureId}", true);`,
|
|
197
|
+
featureId: sketchFeatureId,
|
|
198
|
+
deterministicIds: [],
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
parameterId,
|
|
202
|
+
parameterName: "",
|
|
203
|
+
libraryRelationType: "NONE",
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function sketchEdges(parameterId, sketchFeatureId) {
|
|
207
|
+
return pQuery(parameterId, `query = qCreatedBy(makeId("${sketchFeatureId}"), EntityType.EDGE);`, sketchFeatureId);
|
|
208
|
+
}
|
|
209
|
+
function buildCircleSketch(input) {
|
|
210
|
+
return sketch(input.name, planeId(input.plane), [circleEntity("circle.1", input.center, input.radius)], input.planeFeatureId);
|
|
211
|
+
}
|
|
212
|
+
function buildCircleAxisSketch(input) {
|
|
213
|
+
return sketch(input.name, planeId(input.plane), [
|
|
214
|
+
circleEntity("profile.circle", input.center, input.radius),
|
|
215
|
+
lineEntity("axis.1", input.axisStart, input.axisEnd, true),
|
|
216
|
+
]);
|
|
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
|
+
}
|
|
239
|
+
function buildExtrude(input) {
|
|
240
|
+
return {
|
|
241
|
+
btType: "BTFeatureDefinitionCall-1406",
|
|
242
|
+
feature: {
|
|
243
|
+
btType: "BTMFeature-134",
|
|
244
|
+
featureType: "extrude",
|
|
245
|
+
name: input.name,
|
|
246
|
+
suppressed: false,
|
|
247
|
+
namespace: "",
|
|
248
|
+
parameters: [
|
|
249
|
+
sketchRegion("entities", input.sketchFeatureId),
|
|
250
|
+
pEnum("operationType", "NewBodyOperationType", input.operationType),
|
|
251
|
+
pQuantity("depth", input.depth, "in"),
|
|
252
|
+
pBool("oppositeDirection", false),
|
|
253
|
+
pBool("defaultScope", true),
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function buildRevolve(input) {
|
|
259
|
+
return {
|
|
260
|
+
btType: "BTFeatureDefinitionCall-1406",
|
|
261
|
+
feature: {
|
|
262
|
+
btType: "BTMFeature-134",
|
|
263
|
+
featureType: "revolve",
|
|
264
|
+
name: input.name,
|
|
265
|
+
suppressed: false,
|
|
266
|
+
namespace: "",
|
|
267
|
+
parameters: [
|
|
268
|
+
pEnum("bodyType", "ExtendedToolBodyType", "SOLID"),
|
|
269
|
+
pEnum("operationType", "NewBodyOperationType", input.operationType),
|
|
270
|
+
sketchRegion("entities", input.sketchFeatureId),
|
|
271
|
+
pQuery("axis", `query = qConstructionFilter(qCreatedBy(makeId("${input.sketchFeatureId}"), EntityType.EDGE), ConstructionObject.YES);`, input.sketchFeatureId),
|
|
272
|
+
pBool("fullRevolve", false),
|
|
273
|
+
pEnum("endBound", "RevolveBoundingType", "BLIND"),
|
|
274
|
+
pQuantity("angle", input.angle, "deg"),
|
|
275
|
+
pBool("defaultScope", true),
|
|
276
|
+
],
|
|
277
|
+
},
|
|
278
|
+
};
|
|
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
|
+
}
|
|
321
|
+
function buildBooleanUnion() {
|
|
322
|
+
return {
|
|
323
|
+
btType: "BTFeatureDefinitionCall-1406",
|
|
324
|
+
feature: {
|
|
325
|
+
btType: "BTMFeature-134",
|
|
326
|
+
featureType: "booleanBodies",
|
|
327
|
+
name: "Union bodies",
|
|
328
|
+
suppressed: false,
|
|
329
|
+
namespace: "",
|
|
330
|
+
parameters: [
|
|
331
|
+
pEnum("operationType", "BooleanOperationType", "UNION"),
|
|
332
|
+
pBool("defaultScope", false),
|
|
333
|
+
pQuery("tools", "query = qAllModifiableSolidBodies();"),
|
|
334
|
+
pBool("toolsExplicit", true),
|
|
335
|
+
],
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -40,7 +40,9 @@ 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");
|
|
45
|
+
const modeling_1 = require("./builders/modeling");
|
|
44
46
|
const output_1 = require("./output");
|
|
45
47
|
async function main(argv) {
|
|
46
48
|
try {
|
|
@@ -101,9 +103,22 @@ async function run(argv) {
|
|
|
101
103
|
case "create-part-studio":
|
|
102
104
|
case "delete-feature":
|
|
103
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":
|
|
104
110
|
case "add-feature":
|
|
105
111
|
case "update-feature":
|
|
106
112
|
case "rollback":
|
|
113
|
+
case "sketch-circle":
|
|
114
|
+
case "sketch-circle-axis":
|
|
115
|
+
case "sketch-candy-cane-path":
|
|
116
|
+
case "extrude":
|
|
117
|
+
case "revolve":
|
|
118
|
+
case "sweep":
|
|
119
|
+
case "offset-plane":
|
|
120
|
+
case "boolean-union":
|
|
121
|
+
case "validate-partstudio":
|
|
107
122
|
case "get-edges":
|
|
108
123
|
case "find-circular-edges":
|
|
109
124
|
case "find-edges-by-feature":
|
|
@@ -127,7 +142,7 @@ function parseArgs(argv) {
|
|
|
127
142
|
if (eq !== -1) {
|
|
128
143
|
options[key] = item.slice(eq + 1);
|
|
129
144
|
}
|
|
130
|
-
else if (argv[index + 1] && !argv[index + 1].startsWith("-")) {
|
|
145
|
+
else if (argv[index + 1] && (!argv[index + 1].startsWith("-") || isNegativeValue(argv[index + 1]))) {
|
|
131
146
|
options[key] = argv[index + 1];
|
|
132
147
|
index += 1;
|
|
133
148
|
}
|
|
@@ -147,6 +162,9 @@ function parseArgs(argv) {
|
|
|
147
162
|
}
|
|
148
163
|
return { command, positionals, options };
|
|
149
164
|
}
|
|
165
|
+
function isNegativeValue(value) {
|
|
166
|
+
return /^-\d/.test(value) || /^-\.\d/.test(value);
|
|
167
|
+
}
|
|
150
168
|
async function handleConfig(parsed) {
|
|
151
169
|
const action = parsed.positionals[0];
|
|
152
170
|
const store = new credentials_1.CredentialStore();
|
|
@@ -229,6 +247,7 @@ async function handleReadCommand(parsed) {
|
|
|
229
247
|
const client = new client_1.OnshapeClient(creds);
|
|
230
248
|
const docs = new documents_1.DocumentManager(client);
|
|
231
249
|
const partstudios = new partstudio_1.PartStudioManager(client);
|
|
250
|
+
const featurestudios = new featurestudio_1.FeatureStudioManager(client);
|
|
232
251
|
const edges = new edges_1.EdgeQuery(client);
|
|
233
252
|
switch (parsed.command) {
|
|
234
253
|
case "list-documents": {
|
|
@@ -321,10 +340,36 @@ async function handleReadCommand(parsed) {
|
|
|
321
340
|
(0, output_1.emit)(await client.delete(`/api/v9/elements/d/${doc}/w/${ws}/e/${elem}`));
|
|
322
341
|
return;
|
|
323
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
|
+
}
|
|
324
369
|
case "add-feature": {
|
|
325
370
|
const { doc, ws, elem } = dwe(parsed.options);
|
|
326
371
|
const feature = requiredJson(parsed.options);
|
|
327
|
-
(0, output_1.emit)(await
|
|
372
|
+
(0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, feature, !parsed.options.noValidate));
|
|
328
373
|
return;
|
|
329
374
|
}
|
|
330
375
|
case "update-feature": {
|
|
@@ -338,6 +383,101 @@ async function handleReadCommand(parsed) {
|
|
|
338
383
|
(0, output_1.emit)(await partstudios.rollback(doc, ws, elem, requiredNumberOption(parsed.options, "index")));
|
|
339
384
|
return;
|
|
340
385
|
}
|
|
386
|
+
case "sketch-circle": {
|
|
387
|
+
const { doc, ws, elem } = dwe(parsed.options);
|
|
388
|
+
(0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildCircleSketch)({
|
|
389
|
+
name: stringOption(parsed.options, "name") ?? "Sketch circle",
|
|
390
|
+
plane: stringOption(parsed.options, "plane") ?? "Front",
|
|
391
|
+
planeFeatureId: stringOption(parsed.options, "planeFeature"),
|
|
392
|
+
center: parsePointOption(parsed.options, "center"),
|
|
393
|
+
radius: requiredNumberOption(parsed.options, "radius"),
|
|
394
|
+
}), !parsed.options.noValidate));
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
case "sketch-circle-axis": {
|
|
398
|
+
const { doc, ws, elem } = dwe(parsed.options);
|
|
399
|
+
(0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildCircleAxisSketch)({
|
|
400
|
+
name: stringOption(parsed.options, "name") ?? "Sketch circle and axis",
|
|
401
|
+
plane: stringOption(parsed.options, "plane") ?? "Front",
|
|
402
|
+
center: parsePointOption(parsed.options, "center"),
|
|
403
|
+
radius: requiredNumberOption(parsed.options, "radius"),
|
|
404
|
+
axisStart: parsePointOption(parsed.options, "axisStart"),
|
|
405
|
+
axisEnd: parsePointOption(parsed.options, "axisEnd"),
|
|
406
|
+
}), !parsed.options.noValidate));
|
|
407
|
+
return;
|
|
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
|
+
}
|
|
423
|
+
case "extrude": {
|
|
424
|
+
const { doc, ws, elem } = dwe(parsed.options);
|
|
425
|
+
(0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildExtrude)({
|
|
426
|
+
name: stringOption(parsed.options, "name") ?? "Extrude",
|
|
427
|
+
sketchFeatureId: requiredOption(parsed.options, "sketch"),
|
|
428
|
+
depth: requiredNumberOption(parsed.options, "depth"),
|
|
429
|
+
operationType: stringOption(parsed.options, "op") ?? "NEW",
|
|
430
|
+
}), !parsed.options.noValidate));
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
case "revolve": {
|
|
434
|
+
const { doc, ws, elem } = dwe(parsed.options);
|
|
435
|
+
(0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildRevolve)({
|
|
436
|
+
name: stringOption(parsed.options, "name") ?? "Revolve",
|
|
437
|
+
sketchFeatureId: requiredOption(parsed.options, "sketch"),
|
|
438
|
+
angle: numberOption(parsed.options, "angle", 360),
|
|
439
|
+
operationType: stringOption(parsed.options, "op") ?? "NEW",
|
|
440
|
+
}), !parsed.options.noValidate));
|
|
441
|
+
return;
|
|
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
|
+
}
|
|
462
|
+
case "boolean-union": {
|
|
463
|
+
const { doc, ws, elem } = dwe(parsed.options);
|
|
464
|
+
(0, output_1.emit)(await addFeatureResult(partstudios, doc, ws, elem, (0, modeling_1.buildBooleanUnion)(), !parsed.options.noValidate));
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
case "validate-partstudio": {
|
|
468
|
+
const { doc, ws, elem } = dwe(parsed.options);
|
|
469
|
+
try {
|
|
470
|
+
(0, output_1.emit)(await partstudios.validatePartStudio(doc, ws, elem, {
|
|
471
|
+
parts: optionalNumberOption(parsed.options, "expectParts"),
|
|
472
|
+
bodies: optionalNumberOption(parsed.options, "expectBodies"),
|
|
473
|
+
}));
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
477
|
+
throw new output_1.CliError(message, null, 1);
|
|
478
|
+
}
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
341
481
|
case "get-edges": {
|
|
342
482
|
const { doc, ws, elem } = dwe(parsed.options);
|
|
343
483
|
(0, output_1.emit)(await edges.getEdges(doc, ws, elem));
|
|
@@ -362,10 +502,20 @@ async function handleReadCommand(parsed) {
|
|
|
362
502
|
}
|
|
363
503
|
}
|
|
364
504
|
}
|
|
365
|
-
async function
|
|
366
|
-
const response = await
|
|
505
|
+
async function addFeatureResult(partstudios, doc, ws, elem, feature, validate) {
|
|
506
|
+
const response = await partstudios.addFeature(doc, ws, elem, feature);
|
|
367
507
|
const featureId = isRecord(response) && isRecord(response.feature) ? response.feature.featureId ?? null : null;
|
|
368
|
-
|
|
508
|
+
const result = { featureId, response };
|
|
509
|
+
if (validate && typeof featureId === "string") {
|
|
510
|
+
try {
|
|
511
|
+
result.validation = await partstudios.validateFeature(doc, ws, elem, featureId);
|
|
512
|
+
}
|
|
513
|
+
catch (error) {
|
|
514
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
515
|
+
throw new output_1.CliError(message, { featureId, response }, 1);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return result;
|
|
369
519
|
}
|
|
370
520
|
function isRecord(value) {
|
|
371
521
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -419,6 +569,15 @@ function requiredNumberOption(options, key) {
|
|
|
419
569
|
function requiredOption(options, key) {
|
|
420
570
|
return stringOption(options, key) ?? missing(key);
|
|
421
571
|
}
|
|
572
|
+
function parsePointOption(options, key) {
|
|
573
|
+
try {
|
|
574
|
+
return (0, modeling_1.parsePoint2)(requiredOption(options, key));
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
578
|
+
throw new output_1.CliError(message, null, 2);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
422
581
|
function requiredJson(options) {
|
|
423
582
|
try {
|
|
424
583
|
return (0, partstudio_1.loadJson)(stringOption(options, "json"), stringOption(options, "jsonFile"));
|
|
@@ -467,9 +626,22 @@ Commands:
|
|
|
467
626
|
create-part-studio
|
|
468
627
|
delete-feature
|
|
469
628
|
delete-element
|
|
629
|
+
create-feature-studio
|
|
630
|
+
get-feature-studio
|
|
631
|
+
set-feature-studio
|
|
632
|
+
get-feature-studio-specs
|
|
470
633
|
add-feature
|
|
471
634
|
update-feature
|
|
472
635
|
rollback
|
|
636
|
+
sketch-circle
|
|
637
|
+
sketch-circle-axis
|
|
638
|
+
sketch-candy-cane-path
|
|
639
|
+
extrude
|
|
640
|
+
revolve
|
|
641
|
+
sweep
|
|
642
|
+
offset-plane
|
|
643
|
+
boolean-union
|
|
644
|
+
validate-partstudio
|
|
473
645
|
get-edges
|
|
474
646
|
find-circular-edges
|
|
475
647
|
find-edges-by-feature
|