solidworks-mcp-server 2.2.0 → 3.0.0
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 +33 -10
- package/dist/application/services/command-bus.d.ts +39 -0
- package/dist/application/services/command-bus.d.ts.map +1 -0
- package/dist/application/services/command-bus.js +88 -0
- package/dist/application/services/command-bus.js.map +1 -0
- package/dist/application/services/event-bus.d.ts +31 -0
- package/dist/application/services/event-bus.d.ts.map +1 -0
- package/dist/application/services/event-bus.js +83 -0
- package/dist/application/services/event-bus.js.map +1 -0
- package/dist/application/services/query-bus.d.ts +30 -0
- package/dist/application/services/query-bus.d.ts.map +1 -0
- package/dist/application/services/query-bus.js +59 -0
- package/dist/application/services/query-bus.js.map +1 -0
- package/dist/application/services/tool-registry.d.ts +53 -0
- package/dist/application/services/tool-registry.d.ts.map +1 -0
- package/dist/application/services/tool-registry.js +81 -0
- package/dist/application/services/tool-registry.js.map +1 -0
- package/dist/application/use-cases/analysis/index.d.ts +13 -0
- package/dist/application/use-cases/analysis/index.d.ts.map +1 -0
- package/dist/application/use-cases/analysis/index.js +17 -0
- package/dist/application/use-cases/analysis/index.js.map +1 -0
- package/dist/application/use-cases/drawing/index.d.ts +13 -0
- package/dist/application/use-cases/drawing/index.d.ts.map +1 -0
- package/dist/application/use-cases/drawing/index.js +17 -0
- package/dist/application/use-cases/drawing/index.js.map +1 -0
- package/dist/application/use-cases/export/index.d.ts +13 -0
- package/dist/application/use-cases/export/index.d.ts.map +1 -0
- package/dist/application/use-cases/export/index.js +17 -0
- package/dist/application/use-cases/export/index.js.map +1 -0
- package/dist/application/use-cases/macro/index.d.ts +13 -0
- package/dist/application/use-cases/macro/index.d.ts.map +1 -0
- package/dist/application/use-cases/macro/index.js +17 -0
- package/dist/application/use-cases/macro/index.js.map +1 -0
- package/dist/application/use-cases/modeling/index.d.ts +56 -0
- package/dist/application/use-cases/modeling/index.d.ts.map +1 -0
- package/dist/application/use-cases/modeling/index.js +385 -0
- package/dist/application/use-cases/modeling/index.js.map +1 -0
- package/dist/core/interfaces/core-abstractions.d.ts +289 -0
- package/dist/core/interfaces/core-abstractions.d.ts.map +1 -0
- package/dist/core/interfaces/core-abstractions.js +121 -0
- package/dist/core/interfaces/core-abstractions.js.map +1 -0
- package/dist/index.refactored.d.ts +7 -0
- package/dist/index.refactored.d.ts.map +1 -0
- package/dist/index.refactored.js +254 -0
- package/dist/index.refactored.js.map +1 -0
- package/dist/infrastructure/config/configuration-manager.d.ts +381 -0
- package/dist/infrastructure/config/configuration-manager.d.ts.map +1 -0
- package/dist/infrastructure/config/configuration-manager.js +566 -0
- package/dist/infrastructure/config/configuration-manager.js.map +1 -0
- package/dist/infrastructure/container/service-locator.d.ts +14 -0
- package/dist/infrastructure/container/service-locator.d.ts.map +1 -0
- package/dist/infrastructure/container/service-locator.js +38 -0
- package/dist/infrastructure/container/service-locator.js.map +1 -0
- package/dist/infrastructure/logging/logger.d.ts +24 -0
- package/dist/infrastructure/logging/logger.d.ts.map +1 -0
- package/dist/infrastructure/logging/logger.js +65 -0
- package/dist/infrastructure/logging/logger.js.map +1 -0
- package/dist/infrastructure/solidworks/solidworks-adapter.d.ts +43 -0
- package/dist/infrastructure/solidworks/solidworks-adapter.d.ts.map +1 -0
- package/dist/infrastructure/solidworks/solidworks-adapter.js +527 -0
- package/dist/infrastructure/solidworks/solidworks-adapter.js.map +1 -0
- package/dist/presentation/mcp/request-handler.d.ts +41 -0
- package/dist/presentation/mcp/request-handler.d.ts.map +1 -0
- package/dist/presentation/mcp/request-handler.js +100 -0
- package/dist/presentation/mcp/request-handler.js.map +1 -0
- package/dist/presentation/transformers/error-transformer.d.ts +16 -0
- package/dist/presentation/transformers/error-transformer.d.ts.map +1 -0
- package/dist/presentation/transformers/error-transformer.js +44 -0
- package/dist/presentation/transformers/error-transformer.js.map +1 -0
- package/dist/presentation/transformers/response-transformer.d.ts +24 -0
- package/dist/presentation/transformers/response-transformer.d.ts.map +1 -0
- package/dist/presentation/transformers/response-transformer.js +102 -0
- package/dist/presentation/transformers/response-transformer.js.map +1 -0
- package/dist/resources/design-table.d.ts +28 -28
- package/dist/resources/pdm.d.ts +70 -70
- package/dist/shared/constants/solidworks-constants.d.ts +302 -0
- package/dist/shared/constants/solidworks-constants.d.ts.map +1 -0
- package/dist/shared/constants/solidworks-constants.js +471 -0
- package/dist/shared/constants/solidworks-constants.js.map +1 -0
- package/dist/tools/diagnostics.d.ts +21 -0
- package/dist/tools/diagnostics.d.ts.map +1 -0
- package/dist/tools/diagnostics.js +120 -0
- package/dist/tools/diagnostics.js.map +1 -0
- package/dist/tools/drawing-analysis.d.ts +9 -0
- package/dist/tools/drawing-analysis.d.ts.map +1 -0
- package/dist/tools/drawing-analysis.js +239 -0
- package/dist/tools/drawing-analysis.js.map +1 -0
- package/dist/tools/drawing.d.ts +4 -4
- package/dist/tools/enhanced-drawing.d.ts +51 -0
- package/dist/tools/enhanced-drawing.d.ts.map +1 -0
- package/dist/tools/enhanced-drawing.js +193 -0
- package/dist/tools/enhanced-drawing.js.map +1 -0
- package/dist/tools/export.d.ts +6 -6
- package/dist/tools/macro-security.d.ts +9 -0
- package/dist/tools/macro-security.d.ts.map +1 -0
- package/dist/tools/macro-security.js +86 -0
- package/dist/tools/macro-security.js.map +1 -0
- package/dist/tools/vba-advanced.d.ts +12 -12
- package/dist/tools/vba-assembly.d.ts +8 -8
- package/dist/tools/vba-drawing.d.ts +14 -14
- package/dist/tools/vba-file-management.d.ts +16 -16
- package/dist/tools/vba-part.d.ts +10 -10
- package/dist/tools/vba.d.ts +67 -67
- package/package.json +12 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/logging/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,4CAA4C,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,MAAO,YAAW,OAAO;IACpC,OAAO,CAAC,OAAO,CAAiB;gBAEpB,MAAM,GAAE,YAAiB;IAsCrC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAW9E,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAW/E"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger Implementation
|
|
3
|
+
* Production-ready logging with multiple transports
|
|
4
|
+
*/
|
|
5
|
+
import winston from 'winston';
|
|
6
|
+
export class Logger {
|
|
7
|
+
winston;
|
|
8
|
+
constructor(config = {}) {
|
|
9
|
+
const transports = [];
|
|
10
|
+
// Console transport
|
|
11
|
+
if (config.console !== false) {
|
|
12
|
+
transports.push(new winston.transports.Console({
|
|
13
|
+
format: winston.format.combine(winston.format.colorize(), winston.format.timestamp(), winston.format.printf(({ timestamp, level, message, ...meta }) => {
|
|
14
|
+
const metaStr = Object.keys(meta).length ? JSON.stringify(meta, null, 2) : '';
|
|
15
|
+
return `${timestamp} [${level}]: ${message} ${metaStr}`;
|
|
16
|
+
}))
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
// File transport
|
|
20
|
+
if (config.file && config.filePath) {
|
|
21
|
+
transports.push(new winston.transports.File({
|
|
22
|
+
filename: config.filePath,
|
|
23
|
+
format: winston.format.json(),
|
|
24
|
+
maxsize: config.maxFileSize || 10485760, // 10MB
|
|
25
|
+
maxFiles: config.maxFiles || 5
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
this.winston = winston.createLogger({
|
|
29
|
+
level: config.level || 'info',
|
|
30
|
+
format: winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json()),
|
|
31
|
+
transports
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
debug(message, context) {
|
|
35
|
+
this.winston.debug(message, context);
|
|
36
|
+
}
|
|
37
|
+
info(message, context) {
|
|
38
|
+
this.winston.info(message, context);
|
|
39
|
+
}
|
|
40
|
+
warn(message, context) {
|
|
41
|
+
this.winston.warn(message, context);
|
|
42
|
+
}
|
|
43
|
+
error(message, error, context) {
|
|
44
|
+
this.winston.error(message, {
|
|
45
|
+
...context,
|
|
46
|
+
error: error ? {
|
|
47
|
+
message: error.message,
|
|
48
|
+
stack: error.stack,
|
|
49
|
+
name: error.name
|
|
50
|
+
} : undefined
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
fatal(message, error, context) {
|
|
54
|
+
this.winston.error(message, {
|
|
55
|
+
...context,
|
|
56
|
+
level: 'fatal',
|
|
57
|
+
error: error ? {
|
|
58
|
+
message: error.message,
|
|
59
|
+
stack: error.stack,
|
|
60
|
+
name: error.name
|
|
61
|
+
} : undefined
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/infrastructure/logging/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SolidWorks COM Adapter Implementation
|
|
3
|
+
* Clean architecture implementation with proper abstractions
|
|
4
|
+
*/
|
|
5
|
+
import { Result, ISolidWorksAdapter, ISolidWorksModel, ISolidWorksFeature, ISolidWorksDimension, ILogger } from './core-abstractions';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for the SolidWorks adapter
|
|
8
|
+
*/
|
|
9
|
+
export interface SolidWorksAdapterConfig {
|
|
10
|
+
retryAttempts?: number;
|
|
11
|
+
retryDelay?: number;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
logger?: ILogger;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Main SolidWorks Adapter implementation
|
|
17
|
+
*/
|
|
18
|
+
export declare class SolidWorksAdapter implements ISolidWorksAdapter {
|
|
19
|
+
private readonly pool;
|
|
20
|
+
private readonly logger?;
|
|
21
|
+
private currentModel;
|
|
22
|
+
constructor(config?: SolidWorksAdapterConfig);
|
|
23
|
+
connect(): Promise<Result<void>>;
|
|
24
|
+
disconnect(): Promise<Result<void>>;
|
|
25
|
+
isConnected(): boolean;
|
|
26
|
+
openModel(path: string): Promise<Result<ISolidWorksModel>>;
|
|
27
|
+
closeModel(save: boolean): Promise<Result<void>>;
|
|
28
|
+
createPart(): Promise<Result<ISolidWorksModel>>;
|
|
29
|
+
getCurrentModel(): Result<ISolidWorksModel | null>;
|
|
30
|
+
saveModel(path?: string): Promise<Result<void>>;
|
|
31
|
+
createFeature(params: any): Promise<Result<ISolidWorksFeature>>;
|
|
32
|
+
getFeatures(): Promise<Result<ISolidWorksFeature[]>>;
|
|
33
|
+
suppressFeature(name: string): Promise<Result<void>>;
|
|
34
|
+
getDimension(name: string): Promise<Result<ISolidWorksDimension>>;
|
|
35
|
+
setDimension(name: string, value: number): Promise<Result<void>>;
|
|
36
|
+
listDimensions(): Promise<Result<ISolidWorksDimension[]>>;
|
|
37
|
+
exportModel(path: string, format: string): Promise<Result<void>>;
|
|
38
|
+
/**
|
|
39
|
+
* Safe COM call with error handling
|
|
40
|
+
*/
|
|
41
|
+
private safeComCall;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=solidworks-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solidworks-adapter.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/solidworks/solidworks-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,MAAM,EAEN,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EAMpB,OAAO,EACR,MAAM,qBAAqB,CAAC;AAc7B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA6KD;;GAEG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAU;IAClC,OAAO,CAAC,YAAY,CAA0B;gBAElC,MAAM,GAAE,uBAA4B;IAS1C,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAUhC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAgBzC,WAAW,IAAI,OAAO;IAQhB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAwD1D,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAqChD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAyCrD,eAAe,IAAI,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAe5C,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IA+C/C,aAAa,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IA6D/D,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;IA2BpD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IA+CpD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAkCjE,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAsChE,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAgEzD,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IA6CtE;;OAEG;YACW,WAAW;CAQ1B"}
|
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SolidWorks COM Adapter Implementation
|
|
3
|
+
* Clean architecture implementation with proper abstractions
|
|
4
|
+
*/
|
|
5
|
+
import winax from 'winax';
|
|
6
|
+
import { ResultUtil, ModelType, ConnectionError, ModelNotFoundError, InvalidOperationError, COMError, } from './core-abstractions';
|
|
7
|
+
import { SwDocumentType, SwOpenDocOptions, SwSaveAsOptions, SwEndCondition, SwConstants, ConversionFactors, DefaultConfiguration, } from './solidworks-constants';
|
|
8
|
+
/**
|
|
9
|
+
* COM Object wrapper for safe disposal
|
|
10
|
+
*/
|
|
11
|
+
class COMObject {
|
|
12
|
+
object;
|
|
13
|
+
logger;
|
|
14
|
+
constructor(object, logger) {
|
|
15
|
+
this.object = object;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
}
|
|
18
|
+
get value() {
|
|
19
|
+
return this.object;
|
|
20
|
+
}
|
|
21
|
+
dispose() {
|
|
22
|
+
try {
|
|
23
|
+
if (this.object) {
|
|
24
|
+
// Release COM reference
|
|
25
|
+
this.object = null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
this.logger?.warn('Failed to dispose COM object', { error });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Connection pool for managing SolidWorks connections
|
|
35
|
+
*/
|
|
36
|
+
class ConnectionPool {
|
|
37
|
+
connection = null;
|
|
38
|
+
maxRetries;
|
|
39
|
+
retryDelay;
|
|
40
|
+
logger;
|
|
41
|
+
constructor(config) {
|
|
42
|
+
this.maxRetries = config.retryAttempts ?? DefaultConfiguration.Connection.RetryAttempts;
|
|
43
|
+
this.retryDelay = config.retryDelay ?? DefaultConfiguration.Connection.RetryDelay;
|
|
44
|
+
this.logger = config.logger;
|
|
45
|
+
}
|
|
46
|
+
async getConnection() {
|
|
47
|
+
if (this.connection) {
|
|
48
|
+
return ResultUtil.ok(this.connection);
|
|
49
|
+
}
|
|
50
|
+
return this.createConnection();
|
|
51
|
+
}
|
|
52
|
+
async createConnection() {
|
|
53
|
+
let lastError = null;
|
|
54
|
+
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
|
|
55
|
+
try {
|
|
56
|
+
this.logger?.debug(`Attempting to connect to SolidWorks (attempt ${attempt}/${this.maxRetries})`);
|
|
57
|
+
// Try to create or get existing SolidWorks instance
|
|
58
|
+
const swApp = await this.tryConnect();
|
|
59
|
+
if (swApp) {
|
|
60
|
+
swApp.Visible = true;
|
|
61
|
+
this.connection = new COMObject(swApp, this.logger);
|
|
62
|
+
this.logger?.info('Successfully connected to SolidWorks');
|
|
63
|
+
return ResultUtil.ok(this.connection);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
68
|
+
this.logger?.warn(`Connection attempt ${attempt} failed`, { error: lastError });
|
|
69
|
+
if (attempt < this.maxRetries) {
|
|
70
|
+
await this.delay(this.retryDelay * attempt); // Exponential backoff
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return ResultUtil.fail(new ConnectionError(`Failed to connect to SolidWorks after ${this.maxRetries} attempts`, { lastError }));
|
|
75
|
+
}
|
|
76
|
+
async tryConnect() {
|
|
77
|
+
// Try different connection methods
|
|
78
|
+
const connectionMethods = [
|
|
79
|
+
() => new winax.Object('SldWorks.Application'),
|
|
80
|
+
() => winax.Object('SldWorks.Application'),
|
|
81
|
+
() => new winax.Object('SldWorks.Application.24'), // Version specific
|
|
82
|
+
() => winax.GetObject('', 'SldWorks.Application'),
|
|
83
|
+
];
|
|
84
|
+
for (const method of connectionMethods) {
|
|
85
|
+
try {
|
|
86
|
+
const app = method();
|
|
87
|
+
if (app)
|
|
88
|
+
return app;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Continue to next method
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error('All connection methods failed');
|
|
95
|
+
}
|
|
96
|
+
delay(ms) {
|
|
97
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
98
|
+
}
|
|
99
|
+
disconnect() {
|
|
100
|
+
if (this.connection) {
|
|
101
|
+
this.connection.dispose();
|
|
102
|
+
this.connection = null;
|
|
103
|
+
this.logger?.info('Disconnected from SolidWorks');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
isConnected() {
|
|
107
|
+
return this.connection !== null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Model mapper to convert COM objects to domain models
|
|
112
|
+
*/
|
|
113
|
+
class ModelMapper {
|
|
114
|
+
static toDomainModel(comModel, id) {
|
|
115
|
+
const type = comModel.GetType();
|
|
116
|
+
const typeMap = {
|
|
117
|
+
[SwDocumentType.Part]: ModelType.Part,
|
|
118
|
+
[SwDocumentType.Assembly]: ModelType.Assembly,
|
|
119
|
+
[SwDocumentType.Drawing]: ModelType.Drawing,
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
id: id || this.generateId(),
|
|
123
|
+
path: comModel.GetPathName ? comModel.GetPathName() : '',
|
|
124
|
+
name: comModel.GetTitle ? comModel.GetTitle() : 'Untitled',
|
|
125
|
+
type: typeMap[type] || ModelType.Part,
|
|
126
|
+
isActive: true,
|
|
127
|
+
isDirty: comModel.GetSaveFlag ? comModel.GetSaveFlag() : false,
|
|
128
|
+
metadata: {
|
|
129
|
+
documentType: type,
|
|
130
|
+
version: comModel.GetVersion ? comModel.GetVersion() : null,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
static toFeature(comFeature) {
|
|
135
|
+
return {
|
|
136
|
+
id: this.generateId(),
|
|
137
|
+
name: comFeature.Name || 'Unknown',
|
|
138
|
+
type: comFeature.GetTypeName2 ? comFeature.GetTypeName2() : 'Unknown',
|
|
139
|
+
suppressed: comFeature.IsSuppressed ? comFeature.IsSuppressed() : false,
|
|
140
|
+
parameters: {
|
|
141
|
+
definitionType: comFeature.GetDefinitionType ? comFeature.GetDefinitionType() : null,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
static toDimension(name, value, feature) {
|
|
146
|
+
return {
|
|
147
|
+
name,
|
|
148
|
+
value: value * ConversionFactors.MetersToMillimeters, // Convert to mm
|
|
149
|
+
feature,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
static generateId() {
|
|
153
|
+
return `sw_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Main SolidWorks Adapter implementation
|
|
158
|
+
*/
|
|
159
|
+
export class SolidWorksAdapter {
|
|
160
|
+
pool;
|
|
161
|
+
logger;
|
|
162
|
+
currentModel = null;
|
|
163
|
+
constructor(config = {}) {
|
|
164
|
+
this.pool = new ConnectionPool(config);
|
|
165
|
+
this.logger = config.logger;
|
|
166
|
+
}
|
|
167
|
+
// ============================================
|
|
168
|
+
// CONNECTION MANAGEMENT
|
|
169
|
+
// ============================================
|
|
170
|
+
async connect() {
|
|
171
|
+
const connectionResult = await this.pool.getConnection();
|
|
172
|
+
if (ResultUtil.isFailure(connectionResult)) {
|
|
173
|
+
return ResultUtil.fail(connectionResult.error);
|
|
174
|
+
}
|
|
175
|
+
return ResultUtil.ok(undefined);
|
|
176
|
+
}
|
|
177
|
+
async disconnect() {
|
|
178
|
+
try {
|
|
179
|
+
if (this.currentModel) {
|
|
180
|
+
this.currentModel.dispose();
|
|
181
|
+
this.currentModel = null;
|
|
182
|
+
}
|
|
183
|
+
this.pool.disconnect();
|
|
184
|
+
return ResultUtil.ok(undefined);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return ResultUtil.fail(new COMError('Failed to disconnect', { error }));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
isConnected() {
|
|
191
|
+
return this.pool.isConnected();
|
|
192
|
+
}
|
|
193
|
+
// ============================================
|
|
194
|
+
// MODEL OPERATIONS
|
|
195
|
+
// ============================================
|
|
196
|
+
async openModel(path) {
|
|
197
|
+
const connectionResult = await this.pool.getConnection();
|
|
198
|
+
if (ResultUtil.isFailure(connectionResult)) {
|
|
199
|
+
return ResultUtil.fail(connectionResult.error);
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const swApp = connectionResult.data.value;
|
|
203
|
+
const docType = SwConstants.getDocumentTypeFromExtension(path);
|
|
204
|
+
if (docType === SwDocumentType.None) {
|
|
205
|
+
return ResultUtil.fail(new InvalidOperationError(`Unsupported file type: ${path}`));
|
|
206
|
+
}
|
|
207
|
+
// Open the document with proper error handling
|
|
208
|
+
const errors = { value: 0 };
|
|
209
|
+
const warnings = { value: 0 };
|
|
210
|
+
const model = await this.safeComCall(() => swApp.OpenDoc6(path, docType, SwOpenDocOptions.Silent, '', errors, warnings));
|
|
211
|
+
if (!model) {
|
|
212
|
+
return ResultUtil.fail(new ModelNotFoundError(`Failed to open model: ${path}`, {
|
|
213
|
+
errors: errors.value,
|
|
214
|
+
warnings: warnings.value,
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
this.currentModel = new COMObject(model, this.logger);
|
|
218
|
+
const domainModel = ModelMapper.toDomainModel(model);
|
|
219
|
+
this.logger?.info('Model opened successfully', {
|
|
220
|
+
path,
|
|
221
|
+
type: domainModel.type
|
|
222
|
+
});
|
|
223
|
+
return ResultUtil.ok(domainModel);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
return ResultUtil.fail(new COMError(`Failed to open model: ${path}`, { error }));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async closeModel(save) {
|
|
230
|
+
if (!this.currentModel) {
|
|
231
|
+
return ResultUtil.ok(undefined);
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
const model = this.currentModel.value;
|
|
235
|
+
if (save) {
|
|
236
|
+
const saveResult = await this.saveModel();
|
|
237
|
+
if (ResultUtil.isFailure(saveResult)) {
|
|
238
|
+
this.logger?.warn('Failed to save model before closing', {
|
|
239
|
+
error: saveResult.error
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const title = await this.safeComCall(() => model.GetTitle());
|
|
244
|
+
const connectionResult = await this.pool.getConnection();
|
|
245
|
+
if (ResultUtil.isSuccess(connectionResult)) {
|
|
246
|
+
const swApp = connectionResult.data.value;
|
|
247
|
+
await this.safeComCall(() => swApp.CloseDoc(title));
|
|
248
|
+
}
|
|
249
|
+
this.currentModel.dispose();
|
|
250
|
+
this.currentModel = null;
|
|
251
|
+
this.logger?.info('Model closed', { title, saved: save });
|
|
252
|
+
return ResultUtil.ok(undefined);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
return ResultUtil.fail(new COMError('Failed to close model', { error }));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async createPart() {
|
|
259
|
+
const connectionResult = await this.pool.getConnection();
|
|
260
|
+
if (ResultUtil.isFailure(connectionResult)) {
|
|
261
|
+
return ResultUtil.fail(connectionResult.error);
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
const swApp = connectionResult.data.value;
|
|
265
|
+
// Try to create a new part
|
|
266
|
+
const model = await this.safeComCall(() => swApp.NewPart());
|
|
267
|
+
if (!model) {
|
|
268
|
+
// Try with template
|
|
269
|
+
const template = DefaultConfiguration.Templates.DefaultPartTemplate;
|
|
270
|
+
const modelWithTemplate = await this.safeComCall(() => swApp.NewDocument(template, 0, 0, 0));
|
|
271
|
+
if (!modelWithTemplate) {
|
|
272
|
+
return ResultUtil.fail(new COMError('Failed to create new part'));
|
|
273
|
+
}
|
|
274
|
+
this.currentModel = new COMObject(modelWithTemplate, this.logger);
|
|
275
|
+
return ResultUtil.ok(ModelMapper.toDomainModel(modelWithTemplate));
|
|
276
|
+
}
|
|
277
|
+
this.currentModel = new COMObject(model, this.logger);
|
|
278
|
+
const domainModel = ModelMapper.toDomainModel(model);
|
|
279
|
+
this.logger?.info('Part created successfully');
|
|
280
|
+
return ResultUtil.ok(domainModel);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
return ResultUtil.fail(new COMError('Failed to create part', { error }));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
getCurrentModel() {
|
|
287
|
+
if (!this.currentModel) {
|
|
288
|
+
return ResultUtil.ok(null);
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
const domainModel = ModelMapper.toDomainModel(this.currentModel.value);
|
|
292
|
+
return ResultUtil.ok(domainModel);
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
return ResultUtil.fail(new COMError('Failed to get current model', { error }));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async saveModel(path) {
|
|
299
|
+
if (!this.currentModel) {
|
|
300
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
const model = this.currentModel.value;
|
|
304
|
+
if (path) {
|
|
305
|
+
// Save as
|
|
306
|
+
const success = await this.safeComCall(() => model.SaveAs3(path, SwSaveAsOptions.Silent, 0));
|
|
307
|
+
if (!success) {
|
|
308
|
+
return ResultUtil.fail(new COMError('Failed to save model to path', { path }));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Save
|
|
313
|
+
const success = await this.safeComCall(() => model.Save3(SwSaveAsOptions.Silent, 0, 0));
|
|
314
|
+
if (!success) {
|
|
315
|
+
return ResultUtil.fail(new COMError('Failed to save model'));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
this.logger?.info('Model saved', { path });
|
|
319
|
+
return ResultUtil.ok(undefined);
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
return ResultUtil.fail(new COMError('Failed to save model', { error }));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// ============================================
|
|
326
|
+
// FEATURE OPERATIONS
|
|
327
|
+
// ============================================
|
|
328
|
+
async createFeature(params) {
|
|
329
|
+
if (!this.currentModel) {
|
|
330
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
const model = this.currentModel.value;
|
|
334
|
+
const featureMgr = model.FeatureManager;
|
|
335
|
+
if (!featureMgr) {
|
|
336
|
+
return ResultUtil.fail(new COMError('Cannot access FeatureManager'));
|
|
337
|
+
}
|
|
338
|
+
// Example: Create extrusion
|
|
339
|
+
const { depth = 25, draft = 0, reverse = false } = params;
|
|
340
|
+
const feature = await this.safeComCall(() => featureMgr.FeatureExtrusion3(true, // SingleEndedFeature
|
|
341
|
+
reverse, // ReverseDirection
|
|
342
|
+
false, // UseDirection2
|
|
343
|
+
SwEndCondition.Blind, SwEndCondition.Blind, depth * ConversionFactors.MillimetersToMeters, 0.01, false, false, false, draft * ConversionFactors.DegreesToRadians, 0, false, false, false, false, false, true, false));
|
|
344
|
+
if (!feature) {
|
|
345
|
+
return ResultUtil.fail(new COMError('Failed to create feature'));
|
|
346
|
+
}
|
|
347
|
+
const domainFeature = ModelMapper.toFeature(feature);
|
|
348
|
+
this.logger?.info('Feature created', { type: domainFeature.type });
|
|
349
|
+
return ResultUtil.ok(domainFeature);
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
return ResultUtil.fail(new COMError('Failed to create feature', { error }));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async getFeatures() {
|
|
356
|
+
if (!this.currentModel) {
|
|
357
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
const model = this.currentModel.value;
|
|
361
|
+
const features = [];
|
|
362
|
+
let feature = await this.safeComCall(() => model.FirstFeature());
|
|
363
|
+
while (feature) {
|
|
364
|
+
features.push(ModelMapper.toFeature(feature));
|
|
365
|
+
feature = await this.safeComCall(() => feature.GetNextFeature());
|
|
366
|
+
}
|
|
367
|
+
this.logger?.debug('Retrieved features', { count: features.length });
|
|
368
|
+
return ResultUtil.ok(features);
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
return ResultUtil.fail(new COMError('Failed to get features', { error }));
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
async suppressFeature(name) {
|
|
375
|
+
if (!this.currentModel) {
|
|
376
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const model = this.currentModel.value;
|
|
380
|
+
const feature = await this.safeComCall(() => model.FeatureByName(name));
|
|
381
|
+
if (!feature) {
|
|
382
|
+
return ResultUtil.fail(new InvalidOperationError(`Feature not found: ${name}`));
|
|
383
|
+
}
|
|
384
|
+
const success = await this.safeComCall(() => feature.SetSuppression2(0, 2, null) // 0 = suppressed
|
|
385
|
+
);
|
|
386
|
+
if (!success) {
|
|
387
|
+
return ResultUtil.fail(new COMError(`Failed to suppress feature: ${name}`));
|
|
388
|
+
}
|
|
389
|
+
// Rebuild after suppression
|
|
390
|
+
await this.safeComCall(() => model.EditRebuild3());
|
|
391
|
+
this.logger?.info('Feature suppressed', { name });
|
|
392
|
+
return ResultUtil.ok(undefined);
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
return ResultUtil.fail(new COMError('Failed to suppress feature', { error }));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// ============================================
|
|
399
|
+
// DIMENSION OPERATIONS
|
|
400
|
+
// ============================================
|
|
401
|
+
async getDimension(name) {
|
|
402
|
+
if (!this.currentModel) {
|
|
403
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const model = this.currentModel.value;
|
|
407
|
+
const dimension = await this.safeComCall(() => model.Parameter(name));
|
|
408
|
+
if (!dimension) {
|
|
409
|
+
return ResultUtil.fail(new InvalidOperationError(`Dimension not found: ${name}`));
|
|
410
|
+
}
|
|
411
|
+
const value = await this.safeComCall(() => dimension.SystemValue);
|
|
412
|
+
const feature = name.includes('@') ? name.split('@')[1] : 'Unknown';
|
|
413
|
+
const domainDimension = ModelMapper.toDimension(name, value, feature);
|
|
414
|
+
return ResultUtil.ok(domainDimension);
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
return ResultUtil.fail(new COMError('Failed to get dimension', { error }));
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async setDimension(name, value) {
|
|
421
|
+
if (!this.currentModel) {
|
|
422
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
const model = this.currentModel.value;
|
|
426
|
+
const dimension = await this.safeComCall(() => model.Parameter(name));
|
|
427
|
+
if (!dimension) {
|
|
428
|
+
return ResultUtil.fail(new InvalidOperationError(`Dimension not found: ${name}`));
|
|
429
|
+
}
|
|
430
|
+
// Convert mm to meters for SolidWorks API
|
|
431
|
+
await this.safeComCall(() => {
|
|
432
|
+
dimension.SystemValue = value * ConversionFactors.MillimetersToMeters;
|
|
433
|
+
});
|
|
434
|
+
// Rebuild after dimension change
|
|
435
|
+
await this.safeComCall(() => model.ForceRebuild3(false));
|
|
436
|
+
this.logger?.info('Dimension set', { name, value });
|
|
437
|
+
return ResultUtil.ok(undefined);
|
|
438
|
+
}
|
|
439
|
+
catch (error) {
|
|
440
|
+
return ResultUtil.fail(new COMError('Failed to set dimension', { error }));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async listDimensions() {
|
|
444
|
+
if (!this.currentModel) {
|
|
445
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
446
|
+
}
|
|
447
|
+
try {
|
|
448
|
+
const model = this.currentModel.value;
|
|
449
|
+
const dimensions = [];
|
|
450
|
+
const processedNames = new Set();
|
|
451
|
+
let feature = await this.safeComCall(() => model.FirstFeature());
|
|
452
|
+
while (feature) {
|
|
453
|
+
try {
|
|
454
|
+
const featName = await this.safeComCall(() => feature.Name);
|
|
455
|
+
const dispDim = await this.safeComCall(() => feature.GetFirstDisplayDimension());
|
|
456
|
+
let currentDim = dispDim;
|
|
457
|
+
while (currentDim) {
|
|
458
|
+
const dim = await this.safeComCall(() => currentDim.GetDimension2(0));
|
|
459
|
+
if (dim) {
|
|
460
|
+
const fullName = await this.safeComCall(() => dim.FullName || dim.Name);
|
|
461
|
+
if (fullName && !processedNames.has(fullName)) {
|
|
462
|
+
processedNames.add(fullName);
|
|
463
|
+
const value = await this.safeComCall(() => dim.SystemValue);
|
|
464
|
+
dimensions.push(ModelMapper.toDimension(fullName, value, featName));
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
currentDim = await this.safeComCall(() => feature.GetNextDisplayDimension(currentDim));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
// Continue with next feature
|
|
472
|
+
}
|
|
473
|
+
feature = await this.safeComCall(() => feature.GetNextFeature());
|
|
474
|
+
}
|
|
475
|
+
this.logger?.debug('Retrieved dimensions', { count: dimensions.length });
|
|
476
|
+
return ResultUtil.ok(dimensions);
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
return ResultUtil.fail(new COMError('Failed to list dimensions', { error }));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// ============================================
|
|
483
|
+
// EXPORT OPERATIONS
|
|
484
|
+
// ============================================
|
|
485
|
+
async exportModel(path, format) {
|
|
486
|
+
if (!this.currentModel) {
|
|
487
|
+
return ResultUtil.fail(new InvalidOperationError('No model open'));
|
|
488
|
+
}
|
|
489
|
+
try {
|
|
490
|
+
const model = this.currentModel.value;
|
|
491
|
+
// Ensure model is saved first
|
|
492
|
+
const currentPath = await this.safeComCall(() => model.GetPathName());
|
|
493
|
+
if (!currentPath || currentPath === '') {
|
|
494
|
+
const saveResult = await this.saveModel(path.replace(/\.[^.]+$/, '.SLDPRT'));
|
|
495
|
+
if (ResultUtil.isFailure(saveResult)) {
|
|
496
|
+
return saveResult;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
// Export based on format
|
|
500
|
+
const success = await this.safeComCall(() => model.SaveAs3(path, 0, 1));
|
|
501
|
+
if (!success) {
|
|
502
|
+
return ResultUtil.fail(new COMError(`Failed to export to ${format}`));
|
|
503
|
+
}
|
|
504
|
+
this.logger?.info('Model exported', { path, format });
|
|
505
|
+
return ResultUtil.ok(undefined);
|
|
506
|
+
}
|
|
507
|
+
catch (error) {
|
|
508
|
+
return ResultUtil.fail(new COMError('Failed to export model', { error }));
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
// ============================================
|
|
512
|
+
// HELPER METHODS
|
|
513
|
+
// ============================================
|
|
514
|
+
/**
|
|
515
|
+
* Safe COM call with error handling
|
|
516
|
+
*/
|
|
517
|
+
async safeComCall(fn) {
|
|
518
|
+
try {
|
|
519
|
+
return fn();
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
this.logger?.error('COM call failed', error);
|
|
523
|
+
throw error;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=solidworks-adapter.js.map
|