motionmcp 1.0.2 → 2.1.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/LICENSE +202 -0
- package/README.md +241 -450
- package/dist/handlers/CommentHandler.d.ts +9 -0
- package/dist/handlers/CommentHandler.d.ts.map +1 -0
- package/dist/handlers/CommentHandler.js +66 -0
- package/dist/handlers/CommentHandler.js.map +1 -0
- package/dist/handlers/CustomFieldHandler.d.ts +14 -0
- package/dist/handlers/CustomFieldHandler.d.ts.map +1 -0
- package/dist/handlers/CustomFieldHandler.js +95 -0
- package/dist/handlers/CustomFieldHandler.js.map +1 -0
- package/dist/handlers/HandlerFactory.d.ts +15 -0
- package/dist/handlers/HandlerFactory.d.ts.map +1 -0
- package/dist/handlers/HandlerFactory.js +58 -0
- package/dist/handlers/HandlerFactory.js.map +1 -0
- package/dist/handlers/ProjectHandler.d.ts +10 -0
- package/dist/handlers/ProjectHandler.d.ts.map +1 -0
- package/dist/handlers/ProjectHandler.js +63 -0
- package/dist/handlers/ProjectHandler.js.map +1 -0
- package/dist/handlers/RecurringTaskHandler.d.ts +10 -0
- package/dist/handlers/RecurringTaskHandler.d.ts.map +1 -0
- package/dist/handlers/RecurringTaskHandler.js +68 -0
- package/dist/handlers/RecurringTaskHandler.js.map +1 -0
- package/dist/handlers/ScheduleHandler.d.ts +8 -0
- package/dist/handlers/ScheduleHandler.d.ts.map +1 -0
- package/dist/handlers/ScheduleHandler.js +43 -0
- package/dist/handlers/ScheduleHandler.js.map +1 -0
- package/dist/handlers/SearchHandler.d.ts +10 -0
- package/dist/handlers/SearchHandler.d.ts.map +1 -0
- package/dist/handlers/SearchHandler.js +116 -0
- package/dist/handlers/SearchHandler.js.map +1 -0
- package/dist/handlers/StatusHandler.d.ts +8 -0
- package/dist/handlers/StatusHandler.d.ts.map +1 -0
- package/dist/handlers/StatusHandler.js +22 -0
- package/dist/handlers/StatusHandler.js.map +1 -0
- package/dist/handlers/TaskHandler.d.ts +22 -0
- package/dist/handlers/TaskHandler.d.ts.map +1 -0
- package/dist/handlers/TaskHandler.js +324 -0
- package/dist/handlers/TaskHandler.js.map +1 -0
- package/dist/handlers/UserHandler.d.ts +9 -0
- package/dist/handlers/UserHandler.d.ts.map +1 -0
- package/dist/handlers/UserHandler.js +36 -0
- package/dist/handlers/UserHandler.js.map +1 -0
- package/dist/handlers/WorkspaceHandler.d.ts +10 -0
- package/dist/handlers/WorkspaceHandler.d.ts.map +1 -0
- package/dist/handlers/WorkspaceHandler.js +49 -0
- package/dist/handlers/WorkspaceHandler.js.map +1 -0
- package/dist/handlers/base/BaseHandler.d.ts +16 -0
- package/dist/handlers/base/BaseHandler.d.ts.map +1 -0
- package/dist/handlers/base/BaseHandler.js +31 -0
- package/dist/handlers/base/BaseHandler.js.map +1 -0
- package/dist/handlers/base/HandlerInterface.d.ts +18 -0
- package/dist/handlers/base/HandlerInterface.d.ts.map +1 -0
- package/dist/handlers/base/HandlerInterface.js +3 -0
- package/dist/handlers/base/HandlerInterface.js.map +1 -0
- package/dist/handlers/index.d.ts +14 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +31 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/mcp-server.d.ts +15 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +145 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/schemas/motion.d.ts +4971 -0
- package/dist/schemas/motion.d.ts.map +1 -0
- package/dist/schemas/motion.js +328 -0
- package/dist/schemas/motion.js.map +1 -0
- package/dist/services/motionApi.d.ts +199 -0
- package/dist/services/motionApi.d.ts.map +1 -0
- package/dist/services/motionApi.js +1950 -0
- package/dist/services/motionApi.js.map +1 -0
- package/dist/tools/ToolConfigurator.d.ts +19 -0
- package/dist/tools/ToolConfigurator.d.ts.map +1 -0
- package/dist/tools/ToolConfigurator.js +89 -0
- package/dist/tools/ToolConfigurator.js.map +1 -0
- package/dist/tools/ToolDefinitions.d.ts +25 -0
- package/dist/tools/ToolDefinitions.d.ts.map +1 -0
- package/dist/tools/ToolDefinitions.js +508 -0
- package/dist/tools/ToolDefinitions.js.map +1 -0
- package/dist/tools/ToolRegistry.d.ts +16 -0
- package/dist/tools/ToolRegistry.d.ts.map +1 -0
- package/dist/tools/ToolRegistry.js +89 -0
- package/dist/tools/ToolRegistry.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +21 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types/mcp-tool-args.d.ts +123 -0
- package/dist/types/mcp-tool-args.d.ts.map +1 -0
- package/dist/types/mcp-tool-args.js +7 -0
- package/dist/types/mcp-tool-args.js.map +1 -0
- package/dist/types/mcp.d.ts +32 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +3 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/motion.d.ts +304 -0
- package/dist/types/motion.d.ts.map +1 -0
- package/dist/types/motion.js +3 -0
- package/dist/types/motion.js.map +1 -0
- package/dist/utils/cache.d.ts +25 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +135 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/constants.d.ts +88 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +188 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/errorHandling.d.ts +50 -0
- package/dist/utils/errorHandling.d.ts.map +1 -0
- package/dist/utils/errorHandling.js +86 -0
- package/dist/utils/errorHandling.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +38 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pagination.d.ts +61 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +168 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/paginationNew.d.ts +44 -0
- package/dist/utils/paginationNew.d.ts.map +1 -0
- package/dist/utils/paginationNew.js +149 -0
- package/dist/utils/paginationNew.js.map +1 -0
- package/dist/utils/parameterUtils.d.ts +79 -0
- package/dist/utils/parameterUtils.d.ts.map +1 -0
- package/dist/utils/parameterUtils.js +189 -0
- package/dist/utils/parameterUtils.js.map +1 -0
- package/dist/utils/responseFormatters.d.ts +95 -0
- package/dist/utils/responseFormatters.d.ts.map +1 -0
- package/dist/utils/responseFormatters.js +342 -0
- package/dist/utils/responseFormatters.js.map +1 -0
- package/dist/utils/responseWrapper.d.ts +38 -0
- package/dist/utils/responseWrapper.d.ts.map +1 -0
- package/dist/utils/responseWrapper.js +201 -0
- package/dist/utils/responseWrapper.js.map +1 -0
- package/dist/utils/sanitize.d.ts +51 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +138 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/utils/validator.d.ts +37 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +74 -0
- package/dist/utils/validator.js.map +1 -0
- package/dist/utils/workspaceResolver.d.ts +40 -0
- package/dist/utils/workspaceResolver.d.ts.map +1 -0
- package/dist/utils/workspaceResolver.js +207 -0
- package/dist/utils/workspaceResolver.js.map +1 -0
- package/package.json +41 -17
- package/.claude/settings.local.json +0 -15
- package/.env.example +0 -3
- package/sample.png +0 -0
- package/src/index.js +0 -179
- package/src/mcp-server.js +0 -1137
- package/src/routes/motion.js +0 -152
- package/src/services/motionApi.js +0 -1177
- package/src/worker.js +0 -248
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Motion API Response Wrapper Utility
|
|
3
|
+
*
|
|
4
|
+
* Handles the inconsistent response patterns across Motion API endpoints:
|
|
5
|
+
* - Some return wrapped responses: { meta: {...}, [resource]: [...] }
|
|
6
|
+
* - Others return direct arrays: [...]
|
|
7
|
+
*
|
|
8
|
+
* This utility provides type-safe unwrapping with proper pagination support.
|
|
9
|
+
*/
|
|
10
|
+
import { MotionPaginationMeta } from '../types/motion';
|
|
11
|
+
/**
|
|
12
|
+
* Standard unwrapped response structure for consistent internal handling
|
|
13
|
+
*/
|
|
14
|
+
export interface UnwrappedResponse<T> {
|
|
15
|
+
data: T[];
|
|
16
|
+
meta?: MotionPaginationMeta;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Unwraps a Motion API response based on the known patterns
|
|
20
|
+
*
|
|
21
|
+
* @param response - The raw API response data
|
|
22
|
+
* @param apiEndpoint - The API endpoint name (e.g., 'tasks', 'projects', 'comments')
|
|
23
|
+
* @returns Standardized unwrapped response with data array and optional meta
|
|
24
|
+
*/
|
|
25
|
+
export declare function unwrapApiResponse<T = unknown>(response: unknown, apiEndpoint: string): UnwrappedResponse<T>;
|
|
26
|
+
/**
|
|
27
|
+
* Checks if an API endpoint supports pagination based on known patterns
|
|
28
|
+
*/
|
|
29
|
+
export declare function supportsPagination(apiEndpoint: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Gets the expected resource key for a wrapped API response
|
|
32
|
+
*/
|
|
33
|
+
export declare function getResourceKey(apiEndpoint: string): string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Updates the known pattern for an API endpoint (for runtime discovery)
|
|
36
|
+
*/
|
|
37
|
+
export declare function updateApiPattern(apiEndpoint: string, isWrapped: boolean, resourceKey?: string): void;
|
|
38
|
+
//# sourceMappingURL=responseWrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseWrapper.d.ts","sourceRoot":"","sources":["../../src/utils/responseWrapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAIvD;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,IAAI,CAAC,EAAE,oBAAoB,CAAC;CAC7B;AA6DD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAC3C,QAAQ,EAAE,OAAO,EACjB,WAAW,EAAE,MAAM,GAClB,iBAAiB,CAAC,CAAC,CAAC,CAiBtB;AAyGD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGtE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,OAAO,EAClB,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAYN"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Motion API Response Wrapper Utility
|
|
4
|
+
*
|
|
5
|
+
* Handles the inconsistent response patterns across Motion API endpoints:
|
|
6
|
+
* - Some return wrapped responses: { meta: {...}, [resource]: [...] }
|
|
7
|
+
* - Others return direct arrays: [...]
|
|
8
|
+
*
|
|
9
|
+
* This utility provides type-safe unwrapping with proper pagination support.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.unwrapApiResponse = unwrapApiResponse;
|
|
13
|
+
exports.supportsPagination = supportsPagination;
|
|
14
|
+
exports.getResourceKey = getResourceKey;
|
|
15
|
+
exports.updateApiPattern = updateApiPattern;
|
|
16
|
+
const logger_1 = require("./logger");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
/**
|
|
19
|
+
* Known API response patterns based on current codebase evidence and task documentation
|
|
20
|
+
*/
|
|
21
|
+
const API_RESPONSE_PATTERNS = {
|
|
22
|
+
// Wrapped responses (with meta pagination)
|
|
23
|
+
tasks: {
|
|
24
|
+
isWrapped: true,
|
|
25
|
+
resourceKey: 'tasks',
|
|
26
|
+
apiName: 'Tasks'
|
|
27
|
+
},
|
|
28
|
+
projects: {
|
|
29
|
+
isWrapped: true,
|
|
30
|
+
resourceKey: 'projects',
|
|
31
|
+
apiName: 'Projects'
|
|
32
|
+
},
|
|
33
|
+
comments: {
|
|
34
|
+
isWrapped: true,
|
|
35
|
+
resourceKey: 'comments',
|
|
36
|
+
apiName: 'Comments'
|
|
37
|
+
},
|
|
38
|
+
'recurring-tasks': {
|
|
39
|
+
isWrapped: true,
|
|
40
|
+
resourceKey: 'tasks', // Note: recurring tasks API returns { meta, tasks } not { meta, recurringTasks }
|
|
41
|
+
apiName: 'Recurring Tasks'
|
|
42
|
+
},
|
|
43
|
+
'custom-fields': {
|
|
44
|
+
isWrapped: true,
|
|
45
|
+
resourceKey: 'customFields',
|
|
46
|
+
apiName: 'Custom Fields'
|
|
47
|
+
},
|
|
48
|
+
// Direct array responses (no wrapper)
|
|
49
|
+
schedules: {
|
|
50
|
+
isWrapped: false,
|
|
51
|
+
apiName: 'Schedules'
|
|
52
|
+
},
|
|
53
|
+
statuses: {
|
|
54
|
+
isWrapped: false,
|
|
55
|
+
apiName: 'Statuses'
|
|
56
|
+
},
|
|
57
|
+
workspaces: {
|
|
58
|
+
isWrapped: false,
|
|
59
|
+
apiName: 'Workspaces'
|
|
60
|
+
},
|
|
61
|
+
users: {
|
|
62
|
+
isWrapped: false, // TODO: Verify this - may be wrapped with 'users' key
|
|
63
|
+
apiName: 'Users'
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Unwraps a Motion API response based on the known patterns
|
|
68
|
+
*
|
|
69
|
+
* @param response - The raw API response data
|
|
70
|
+
* @param apiEndpoint - The API endpoint name (e.g., 'tasks', 'projects', 'comments')
|
|
71
|
+
* @returns Standardized unwrapped response with data array and optional meta
|
|
72
|
+
*/
|
|
73
|
+
function unwrapApiResponse(response, apiEndpoint) {
|
|
74
|
+
const config = API_RESPONSE_PATTERNS[apiEndpoint];
|
|
75
|
+
if (!config) {
|
|
76
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Unknown API endpoint pattern: ${apiEndpoint}`, {
|
|
77
|
+
endpoint: apiEndpoint,
|
|
78
|
+
availablePatterns: Object.keys(API_RESPONSE_PATTERNS)
|
|
79
|
+
});
|
|
80
|
+
// Fallback: try to extract array from common patterns
|
|
81
|
+
return fallbackUnwrap(response, apiEndpoint);
|
|
82
|
+
}
|
|
83
|
+
if (config.isWrapped) {
|
|
84
|
+
return unwrapWrappedResponse(response, config);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
return unwrapDirectResponse(response, config);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Unwraps a wrapped response: { meta: {...}, [resourceKey]: [...] }
|
|
92
|
+
*/
|
|
93
|
+
function unwrapWrappedResponse(response, config) {
|
|
94
|
+
if (!response || typeof response !== 'object') {
|
|
95
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Expected wrapped response object for ${config.apiName}`, {
|
|
96
|
+
receivedType: typeof response,
|
|
97
|
+
response
|
|
98
|
+
});
|
|
99
|
+
return { data: [] };
|
|
100
|
+
}
|
|
101
|
+
const responseObj = response;
|
|
102
|
+
const resourceKey = config.resourceKey;
|
|
103
|
+
const data = responseObj[resourceKey];
|
|
104
|
+
const meta = responseObj.meta;
|
|
105
|
+
if (!Array.isArray(data)) {
|
|
106
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Expected array for ${resourceKey} in ${config.apiName} response`, {
|
|
107
|
+
resourceKey,
|
|
108
|
+
receivedType: typeof data,
|
|
109
|
+
hasMetaField: !!meta,
|
|
110
|
+
responseKeys: Object.keys(responseObj)
|
|
111
|
+
});
|
|
112
|
+
return { data: [] };
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
data,
|
|
116
|
+
meta: meta && typeof meta === 'object' ? meta : undefined
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Unwraps a direct array response: [...]
|
|
121
|
+
*/
|
|
122
|
+
function unwrapDirectResponse(response, config) {
|
|
123
|
+
if (!Array.isArray(response)) {
|
|
124
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Expected direct array response for ${config.apiName}`, {
|
|
125
|
+
receivedType: typeof response,
|
|
126
|
+
response
|
|
127
|
+
});
|
|
128
|
+
return { data: [] };
|
|
129
|
+
}
|
|
130
|
+
return { data: response };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Fallback unwrapping logic for unknown endpoints
|
|
134
|
+
* Attempts to handle both wrapped and direct patterns
|
|
135
|
+
*/
|
|
136
|
+
function fallbackUnwrap(response, apiEndpoint) {
|
|
137
|
+
// Case 1: Direct array
|
|
138
|
+
if (Array.isArray(response)) {
|
|
139
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.DEBUG, `Fallback: treating ${apiEndpoint} as direct array`, {
|
|
140
|
+
itemCount: response.length
|
|
141
|
+
});
|
|
142
|
+
return { data: response };
|
|
143
|
+
}
|
|
144
|
+
// Case 2: Wrapped response - try common resource keys
|
|
145
|
+
if (response && typeof response === 'object') {
|
|
146
|
+
const responseObj = response;
|
|
147
|
+
const possibleKeys = ['items', 'tasks', 'projects', 'comments', 'users', 'workspaces', 'schedules', 'statuses', 'customFields'];
|
|
148
|
+
for (const key of possibleKeys) {
|
|
149
|
+
if (Array.isArray(responseObj[key])) {
|
|
150
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.DEBUG, `Fallback: found array at ${key} for ${apiEndpoint}`, {
|
|
151
|
+
key,
|
|
152
|
+
itemCount: responseObj[key].length,
|
|
153
|
+
hasMeta: !!responseObj.meta
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
data: responseObj[key],
|
|
157
|
+
meta: responseObj.meta
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.WARN, `Fallback: no array found in object response for ${apiEndpoint}`, {
|
|
162
|
+
responseKeys: Object.keys(responseObj)
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Case 3: Unexpected response
|
|
166
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.ERROR, `Fallback: unexpected response format for ${apiEndpoint}`, {
|
|
167
|
+
responseType: typeof response,
|
|
168
|
+
response
|
|
169
|
+
});
|
|
170
|
+
return { data: [] };
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Checks if an API endpoint supports pagination based on known patterns
|
|
174
|
+
*/
|
|
175
|
+
function supportsPagination(apiEndpoint) {
|
|
176
|
+
const config = API_RESPONSE_PATTERNS[apiEndpoint];
|
|
177
|
+
return config?.isWrapped || false;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Gets the expected resource key for a wrapped API response
|
|
181
|
+
*/
|
|
182
|
+
function getResourceKey(apiEndpoint) {
|
|
183
|
+
const config = API_RESPONSE_PATTERNS[apiEndpoint];
|
|
184
|
+
return config?.resourceKey;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Updates the known pattern for an API endpoint (for runtime discovery)
|
|
188
|
+
*/
|
|
189
|
+
function updateApiPattern(apiEndpoint, isWrapped, resourceKey) {
|
|
190
|
+
API_RESPONSE_PATTERNS[apiEndpoint] = {
|
|
191
|
+
isWrapped,
|
|
192
|
+
resourceKey,
|
|
193
|
+
apiName: apiEndpoint
|
|
194
|
+
};
|
|
195
|
+
(0, logger_1.mcpLog)(constants_1.LOG_LEVELS.INFO, `Updated API pattern for ${apiEndpoint}`, {
|
|
196
|
+
endpoint: apiEndpoint,
|
|
197
|
+
isWrapped,
|
|
198
|
+
resourceKey
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=responseWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responseWrapper.js","sourceRoot":"","sources":["../../src/utils/responseWrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Sanitization Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides secure sanitization functions for user-provided content
|
|
5
|
+
* to prevent injection attacks and ensure data integrity.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Sanitize user-provided text content for safe storage and transmission
|
|
9
|
+
* Removes dangerous HTML tags, script content, and other potentially harmful input
|
|
10
|
+
*
|
|
11
|
+
* @param input - The user input to sanitize
|
|
12
|
+
* @returns Sanitized string safe for storage/transmission
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeTextContent(input: string | undefined | null): string;
|
|
15
|
+
/**
|
|
16
|
+
* Validate that sanitized content is not empty after sanitization
|
|
17
|
+
*
|
|
18
|
+
* @param original - Original user input
|
|
19
|
+
* @param sanitized - Sanitized version
|
|
20
|
+
* @returns True if content is valid after sanitization
|
|
21
|
+
*/
|
|
22
|
+
export declare function isValidSanitizedContent(original: string | undefined | null, sanitized: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Sanitize and validate comment content
|
|
25
|
+
*
|
|
26
|
+
* @param content - Comment content to sanitize
|
|
27
|
+
* @returns Object with sanitized content and validation result
|
|
28
|
+
*/
|
|
29
|
+
export declare function sanitizeCommentContent(content: string | undefined | null): {
|
|
30
|
+
sanitized: string;
|
|
31
|
+
isValid: boolean;
|
|
32
|
+
error?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Sanitize task/project description content
|
|
36
|
+
* Similar to comment content but allows empty descriptions
|
|
37
|
+
*
|
|
38
|
+
* @param description - Task or project description to sanitize
|
|
39
|
+
* @returns Sanitized description or undefined if empty/invalid
|
|
40
|
+
*/
|
|
41
|
+
export declare function sanitizeDescription(description: string | undefined | null): string | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Sanitize task/project name content
|
|
44
|
+
* Names are required and must be non-empty after sanitization
|
|
45
|
+
*
|
|
46
|
+
* @param name - Task or project name to sanitize
|
|
47
|
+
* @returns Sanitized name
|
|
48
|
+
* @throws Error if name is empty or contains invalid content
|
|
49
|
+
*/
|
|
50
|
+
export declare function sanitizeName(name: string | undefined | null): string;
|
|
51
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAmC5E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAQvG;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAwBA;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAgB9F;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAgBpE"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input Sanitization Utilities
|
|
4
|
+
*
|
|
5
|
+
* Provides secure sanitization functions for user-provided content
|
|
6
|
+
* to prevent injection attacks and ensure data integrity.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.sanitizeTextContent = sanitizeTextContent;
|
|
10
|
+
exports.isValidSanitizedContent = isValidSanitizedContent;
|
|
11
|
+
exports.sanitizeCommentContent = sanitizeCommentContent;
|
|
12
|
+
exports.sanitizeDescription = sanitizeDescription;
|
|
13
|
+
exports.sanitizeName = sanitizeName;
|
|
14
|
+
const constants_1 = require("./constants");
|
|
15
|
+
/**
|
|
16
|
+
* Sanitize user-provided text content for safe storage and transmission
|
|
17
|
+
* Removes dangerous HTML tags, script content, and other potentially harmful input
|
|
18
|
+
*
|
|
19
|
+
* @param input - The user input to sanitize
|
|
20
|
+
* @returns Sanitized string safe for storage/transmission
|
|
21
|
+
*/
|
|
22
|
+
function sanitizeTextContent(input) {
|
|
23
|
+
if (!input || typeof input !== 'string') {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
// Trim whitespace
|
|
27
|
+
const trimmed = input.trim();
|
|
28
|
+
if (trimmed.length === 0) {
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
// Remove or escape potentially dangerous characters and patterns
|
|
32
|
+
let sanitized = trimmed
|
|
33
|
+
// Remove script tags and their content entirely
|
|
34
|
+
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
|
|
35
|
+
// Remove any remaining HTML tags but keep inner text
|
|
36
|
+
.replace(/<[^>]*>/g, '')
|
|
37
|
+
// Normalize unicode non-breaking spaces
|
|
38
|
+
.replace(/\u00a0/g, ' ');
|
|
39
|
+
// Normalize whitespace introduced by stripping tags while preserving newlines
|
|
40
|
+
sanitized = sanitized
|
|
41
|
+
.replace(/\r\n/g, '\n')
|
|
42
|
+
.replace(/[ \t]{2,}/g, ' ')
|
|
43
|
+
.replace(/[ \t]+\n/g, '\n')
|
|
44
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
45
|
+
.trim();
|
|
46
|
+
// Limit length to prevent abuse - use consistent limit from constants
|
|
47
|
+
if (sanitized.length > constants_1.LIMITS.COMMENT_MAX_LENGTH) {
|
|
48
|
+
sanitized = sanitized.substring(0, constants_1.LIMITS.COMMENT_MAX_LENGTH);
|
|
49
|
+
}
|
|
50
|
+
return sanitized;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate that sanitized content is not empty after sanitization
|
|
54
|
+
*
|
|
55
|
+
* @param original - Original user input
|
|
56
|
+
* @param sanitized - Sanitized version
|
|
57
|
+
* @returns True if content is valid after sanitization
|
|
58
|
+
*/
|
|
59
|
+
function isValidSanitizedContent(original, sanitized) {
|
|
60
|
+
// If original had content but sanitized is empty, it was likely malicious
|
|
61
|
+
if (original && original.trim().length > 0 && sanitized.length === 0) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
// Must have some actual content
|
|
65
|
+
return sanitized.length > 0;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sanitize and validate comment content
|
|
69
|
+
*
|
|
70
|
+
* @param content - Comment content to sanitize
|
|
71
|
+
* @returns Object with sanitized content and validation result
|
|
72
|
+
*/
|
|
73
|
+
function sanitizeCommentContent(content) {
|
|
74
|
+
const sanitized = sanitizeTextContent(content);
|
|
75
|
+
const isValid = isValidSanitizedContent(content, sanitized);
|
|
76
|
+
if (!isValid && content && content.trim().length > 0) {
|
|
77
|
+
return {
|
|
78
|
+
sanitized: '',
|
|
79
|
+
isValid: false,
|
|
80
|
+
error: 'Comment content contains invalid or potentially harmful content'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (!isValid) {
|
|
84
|
+
return {
|
|
85
|
+
sanitized: '',
|
|
86
|
+
isValid: false,
|
|
87
|
+
error: 'Comment content cannot be empty'
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
sanitized,
|
|
92
|
+
isValid: true
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Sanitize task/project description content
|
|
97
|
+
* Similar to comment content but allows empty descriptions
|
|
98
|
+
*
|
|
99
|
+
* @param description - Task or project description to sanitize
|
|
100
|
+
* @returns Sanitized description or undefined if empty/invalid
|
|
101
|
+
*/
|
|
102
|
+
function sanitizeDescription(description) {
|
|
103
|
+
if (!description || typeof description !== 'string') {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const sanitized = sanitizeTextContent(description);
|
|
107
|
+
if (sanitized === '') {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
// Check if sanitization removed significant content (potential attack)
|
|
111
|
+
if (description.trim().length > 0 && !isValidSanitizedContent(description, sanitized)) {
|
|
112
|
+
throw new Error('Description contains invalid or potentially harmful content');
|
|
113
|
+
}
|
|
114
|
+
return sanitized;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Sanitize task/project name content
|
|
118
|
+
* Names are required and must be non-empty after sanitization
|
|
119
|
+
*
|
|
120
|
+
* @param name - Task or project name to sanitize
|
|
121
|
+
* @returns Sanitized name
|
|
122
|
+
* @throws Error if name is empty or contains invalid content
|
|
123
|
+
*/
|
|
124
|
+
function sanitizeName(name) {
|
|
125
|
+
if (!name || typeof name !== 'string') {
|
|
126
|
+
throw new Error('Name is required');
|
|
127
|
+
}
|
|
128
|
+
const sanitized = sanitizeTextContent(name);
|
|
129
|
+
if (sanitized === '') {
|
|
130
|
+
throw new Error('Name cannot be empty');
|
|
131
|
+
}
|
|
132
|
+
// Check if sanitization removed significant content (potential attack)
|
|
133
|
+
if (!isValidSanitizedContent(name, sanitized)) {
|
|
134
|
+
throw new Error('Name contains invalid or potentially harmful content');
|
|
135
|
+
}
|
|
136
|
+
return sanitized;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation Service - Runtime validation for MCP requests
|
|
3
|
+
*
|
|
4
|
+
* This module provides runtime validation of incoming MCP requests
|
|
5
|
+
* against their defined schemas using AJV, ensuring type safety
|
|
6
|
+
* at runtime and preventing malformed inputs from causing errors.
|
|
7
|
+
*/
|
|
8
|
+
import { McpToolDefinition } from '../types/mcp';
|
|
9
|
+
export declare class InputValidator {
|
|
10
|
+
private ajv;
|
|
11
|
+
private validators;
|
|
12
|
+
constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Compile and cache validators for all tool definitions
|
|
15
|
+
*/
|
|
16
|
+
initializeValidators(toolDefinitions: McpToolDefinition[]): void;
|
|
17
|
+
/**
|
|
18
|
+
* Validate input arguments against tool schema
|
|
19
|
+
*/
|
|
20
|
+
validateInput(toolName: string, args: unknown): {
|
|
21
|
+
valid: boolean;
|
|
22
|
+
errors?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Get detailed validation errors for debugging
|
|
26
|
+
*/
|
|
27
|
+
getDetailedErrors(toolName: string): any[] | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Clear all cached validators
|
|
30
|
+
*/
|
|
31
|
+
clearValidators(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Check if a validator exists for a tool
|
|
34
|
+
*/
|
|
35
|
+
hasValidator(toolName: string): boolean;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/utils/validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,UAAU,CAAgC;;IAWlD;;OAEG;IACH,oBAAoB,CAAC,eAAe,EAAE,iBAAiB,EAAE,GAAG,IAAI;IAOhE;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAsBnF;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,SAAS;IAKtD;;OAEG;IACH,eAAe,IAAI,IAAI;IAIvB;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAGxC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input Validation Service - Runtime validation for MCP requests
|
|
4
|
+
*
|
|
5
|
+
* This module provides runtime validation of incoming MCP requests
|
|
6
|
+
* against their defined schemas using AJV, ensuring type safety
|
|
7
|
+
* at runtime and preventing malformed inputs from causing errors.
|
|
8
|
+
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.InputValidator = void 0;
|
|
14
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
15
|
+
class InputValidator {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.ajv = new ajv_1.default({
|
|
18
|
+
allErrors: true,
|
|
19
|
+
coerceTypes: true, // Automatically coerce types when safe
|
|
20
|
+
allowUnionTypes: true // Allow union types in schemas
|
|
21
|
+
});
|
|
22
|
+
this.validators = new Map();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Compile and cache validators for all tool definitions
|
|
26
|
+
*/
|
|
27
|
+
initializeValidators(toolDefinitions) {
|
|
28
|
+
for (const tool of toolDefinitions) {
|
|
29
|
+
const validator = this.ajv.compile(tool.inputSchema);
|
|
30
|
+
this.validators.set(tool.name, validator);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate input arguments against tool schema
|
|
35
|
+
*/
|
|
36
|
+
validateInput(toolName, args) {
|
|
37
|
+
const validator = this.validators.get(toolName);
|
|
38
|
+
if (!validator) {
|
|
39
|
+
return {
|
|
40
|
+
valid: false,
|
|
41
|
+
errors: `No validator found for tool: ${toolName}`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const valid = validator(args);
|
|
45
|
+
if (!valid) {
|
|
46
|
+
return {
|
|
47
|
+
valid: false,
|
|
48
|
+
errors: this.ajv.errorsText(validator.errors)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return { valid: true };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get detailed validation errors for debugging
|
|
55
|
+
*/
|
|
56
|
+
getDetailedErrors(toolName) {
|
|
57
|
+
const validator = this.validators.get(toolName);
|
|
58
|
+
return validator?.errors || undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Clear all cached validators
|
|
62
|
+
*/
|
|
63
|
+
clearValidators() {
|
|
64
|
+
this.validators.clear();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check if a validator exists for a tool
|
|
68
|
+
*/
|
|
69
|
+
hasValidator(toolName) {
|
|
70
|
+
return this.validators.has(toolName);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.InputValidator = InputValidator;
|
|
74
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/utils/validator.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;AAEH,8CAA4C;AAG5C,MAAa,cAAc;IAIzB;QACE,IAAI,CAAC,GAAG,GAAG,IAAI,aAAG,CAAC;YACjB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,IAAI,EAAG,uCAAuC;YAC3D,eAAe,EAAE,IAAI,CAAE,+BAA+B;SACvD,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAC,eAAoC;QACvD,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB,EAAE,IAAa;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEhD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,gCAAgC,QAAQ,EAAE;aACnD,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC;aAC9C,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,QAAgB;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,OAAO,SAAS,EAAE,MAAM,IAAI,SAAS,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;CACF;AArED,wCAqEC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkspaceResolver - Centralized workspace resolution logic
|
|
3
|
+
*
|
|
4
|
+
* This class handles all workspace resolution patterns used throughout
|
|
5
|
+
* the Motion MCP Server, including ID resolution, name lookups, and
|
|
6
|
+
* fallback to default workspace behavior.
|
|
7
|
+
*/
|
|
8
|
+
import { MotionWorkspace } from '../types/motion';
|
|
9
|
+
import { MotionApiService } from '../services/motionApi';
|
|
10
|
+
interface WorkspaceResolverOptions {
|
|
11
|
+
fallbackToDefault?: boolean;
|
|
12
|
+
validateAccess?: boolean;
|
|
13
|
+
useCache?: boolean;
|
|
14
|
+
}
|
|
15
|
+
interface WorkspaceArgs {
|
|
16
|
+
workspaceId?: string;
|
|
17
|
+
workspaceName?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class WorkspaceResolver {
|
|
20
|
+
private motionService;
|
|
21
|
+
constructor(motionApiService: MotionApiService);
|
|
22
|
+
/**
|
|
23
|
+
* Main workspace resolution method - handles all workspace resolution patterns
|
|
24
|
+
*/
|
|
25
|
+
resolveWorkspace(args?: WorkspaceArgs, options?: WorkspaceResolverOptions): Promise<MotionWorkspace>;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve workspace by ID - validates the workspace exists
|
|
28
|
+
*/
|
|
29
|
+
private resolveByWorkspaceId;
|
|
30
|
+
/**
|
|
31
|
+
* Resolve workspace by name - finds matching workspace
|
|
32
|
+
*/
|
|
33
|
+
private resolveByWorkspaceName;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve default workspace - gets the first available workspace
|
|
36
|
+
*/
|
|
37
|
+
private resolveDefaultWorkspace;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=workspaceResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceResolver.d.ts","sourceRoot":"","sources":["../../src/utils/workspaceResolver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,UAAU,wBAAwB;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,aAAa;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,aAAa,CAAmB;gBAE5B,gBAAgB,EAAE,gBAAgB;IAO9C;;OAEG;IACG,gBAAgB,CACpB,IAAI,GAAE,aAAkB,EACxB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,eAAe,CAAC;IAqF3B;;OAEG;YACW,oBAAoB;IA2ClC;;OAEG;YACW,sBAAsB;IA+DpC;;OAEG;YACW,uBAAuB;CAyCtC"}
|