tm1npm 1.2.0 → 1.3.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/lib/services/DebuggerService.d.ts +214 -0
- package/lib/services/DebuggerService.d.ts.map +1 -0
- package/lib/services/DebuggerService.js +319 -0
- package/lib/services/ProcessService.d.ts +45 -0
- package/lib/services/ProcessService.d.ts.map +1 -1
- package/lib/services/ProcessService.js +152 -0
- package/lib/services/TM1Service.d.ts +2 -0
- package/lib/services/TM1Service.d.ts.map +1 -1
- package/lib/services/TM1Service.js +2 -0
- package/lib/services/index.d.ts +1 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +3 -1
- package/lib/tests/debuggerService.test.d.ts +6 -0
- package/lib/tests/debuggerService.test.d.ts.map +1 -0
- package/lib/tests/debuggerService.test.js +279 -0
- package/package.json +1 -1
- package/src/services/DebuggerService.ts +399 -0
- package/src/services/ProcessService.ts +162 -0
- package/src/services/TM1Service.ts +3 -0
- package/src/services/index.ts +1 -0
- package/src/tests/debuggerService.test.ts +377 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { ObjectService } from './ObjectService';
|
|
2
|
+
import { RestService } from './RestService';
|
|
3
|
+
import { formatUrl } from '../utils/Utils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Debug session information
|
|
7
|
+
*/
|
|
8
|
+
export interface DebugSession {
|
|
9
|
+
id: string;
|
|
10
|
+
processName: string;
|
|
11
|
+
status: 'Running' | 'Paused' | 'Completed' | 'Failed';
|
|
12
|
+
currentLine?: number;
|
|
13
|
+
variables?: { [key: string]: any };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Process variable information
|
|
18
|
+
*/
|
|
19
|
+
export interface ProcessVariable {
|
|
20
|
+
name: string;
|
|
21
|
+
value: any;
|
|
22
|
+
type: 'String' | 'Numeric' | 'Unknown';
|
|
23
|
+
scope: 'Local' | 'Global' | 'Parameter';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Call stack frame
|
|
28
|
+
*/
|
|
29
|
+
export interface CallStackFrame {
|
|
30
|
+
procedureName: string;
|
|
31
|
+
lineNumber: number;
|
|
32
|
+
source?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Process validation result
|
|
37
|
+
*/
|
|
38
|
+
export interface ValidationResult {
|
|
39
|
+
isValid: boolean;
|
|
40
|
+
errors: Array<{
|
|
41
|
+
line: number;
|
|
42
|
+
message: string;
|
|
43
|
+
severity: 'Error' | 'Warning';
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* DebuggerService - Comprehensive TM1 process debugging service
|
|
49
|
+
*
|
|
50
|
+
* Provides advanced debugging capabilities including session management,
|
|
51
|
+
* variable inspection, expression evaluation, and call stack analysis.
|
|
52
|
+
*/
|
|
53
|
+
export class DebuggerService extends ObjectService {
|
|
54
|
+
private activeSessions: Map<string, DebugSession> = new Map();
|
|
55
|
+
|
|
56
|
+
constructor(rest: RestService) {
|
|
57
|
+
super(rest);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Create a new debug session for a process
|
|
62
|
+
*
|
|
63
|
+
* @param processName - Name of the process to debug
|
|
64
|
+
* @returns Promise<string> - Debug session ID
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const sessionId = await debuggerService.createDebugSession('MyProcess');
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
public async createDebugSession(processName: string): Promise<string> {
|
|
72
|
+
const url = formatUrl("/Processes('{}')/tm1.BeginDebug", processName);
|
|
73
|
+
const response = await this.rest.post(url, {});
|
|
74
|
+
|
|
75
|
+
const sessionId = response.data.ID || response.data.SessionId || this.generateSessionId();
|
|
76
|
+
|
|
77
|
+
// Track the session
|
|
78
|
+
this.activeSessions.set(sessionId, {
|
|
79
|
+
id: sessionId,
|
|
80
|
+
processName,
|
|
81
|
+
status: 'Paused',
|
|
82
|
+
currentLine: 0
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return sessionId;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Terminate an active debug session
|
|
90
|
+
*
|
|
91
|
+
* @param sessionId - Debug session ID
|
|
92
|
+
* @returns Promise<void>
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* await debuggerService.terminateDebugSession(sessionId);
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
public async terminateDebugSession(sessionId: string): Promise<void> {
|
|
100
|
+
const session = this.activeSessions.get(sessionId);
|
|
101
|
+
if (!session) {
|
|
102
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const url = formatUrl("/Processes('{}')/tm1.EndDebug", session.processName);
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
await this.rest.post(url, {});
|
|
109
|
+
} finally {
|
|
110
|
+
this.activeSessions.delete(sessionId);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Step into the next line (enter function calls)
|
|
116
|
+
*
|
|
117
|
+
* @param sessionId - Debug session ID
|
|
118
|
+
* @returns Promise<void>
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* await debuggerService.stepInto(sessionId);
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
public async stepInto(sessionId: string): Promise<void> {
|
|
126
|
+
const session = this.activeSessions.get(sessionId);
|
|
127
|
+
if (!session) {
|
|
128
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const url = formatUrl("/Processes('{}')/tm1.DebugStepIn", session.processName);
|
|
132
|
+
await this.rest.post(url, {});
|
|
133
|
+
|
|
134
|
+
session.status = 'Paused';
|
|
135
|
+
if (session.currentLine !== undefined) {
|
|
136
|
+
session.currentLine++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Step over the next line (don't enter function calls)
|
|
142
|
+
*
|
|
143
|
+
* @param sessionId - Debug session ID
|
|
144
|
+
* @returns Promise<void>
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* await debuggerService.stepOver(sessionId);
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
public async stepOver(sessionId: string): Promise<void> {
|
|
152
|
+
const session = this.activeSessions.get(sessionId);
|
|
153
|
+
if (!session) {
|
|
154
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const url = formatUrl("/Processes('{}')/tm1.DebugStepOver", session.processName);
|
|
158
|
+
await this.rest.post(url, {});
|
|
159
|
+
|
|
160
|
+
session.status = 'Paused';
|
|
161
|
+
if (session.currentLine !== undefined) {
|
|
162
|
+
session.currentLine++;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Step out of current function
|
|
168
|
+
*
|
|
169
|
+
* @param sessionId - Debug session ID
|
|
170
|
+
* @returns Promise<void>
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* await debuggerService.stepOut(sessionId);
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
public async stepOut(sessionId: string): Promise<void> {
|
|
178
|
+
const session = this.activeSessions.get(sessionId);
|
|
179
|
+
if (!session) {
|
|
180
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const url = formatUrl("/Processes('{}')/tm1.DebugStepOut", session.processName);
|
|
184
|
+
await this.rest.post(url, {});
|
|
185
|
+
|
|
186
|
+
session.status = 'Paused';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Continue execution until next breakpoint or completion
|
|
191
|
+
*
|
|
192
|
+
* @param sessionId - Debug session ID
|
|
193
|
+
* @returns Promise<void>
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* await debuggerService.continueExecution(sessionId);
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
public async continueExecution(sessionId: string): Promise<void> {
|
|
201
|
+
const session = this.activeSessions.get(sessionId);
|
|
202
|
+
if (!session) {
|
|
203
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const url = formatUrl("/Processes('{}')/tm1.DebugContinue", session.processName);
|
|
207
|
+
await this.rest.post(url, {});
|
|
208
|
+
|
|
209
|
+
session.status = 'Running';
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get all process variables in current debug session
|
|
214
|
+
*
|
|
215
|
+
* @param sessionId - Debug session ID
|
|
216
|
+
* @returns Promise<ProcessVariable[]> - Array of process variables
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const variables = await debuggerService.getProcessVariables(sessionId);
|
|
221
|
+
* console.log(variables);
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
public async getProcessVariables(sessionId: string): Promise<ProcessVariable[]> {
|
|
225
|
+
const session = this.activeSessions.get(sessionId);
|
|
226
|
+
if (!session) {
|
|
227
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const url = formatUrl("/Processes('{}')/Variables", session.processName);
|
|
231
|
+
const response = await this.rest.get(url);
|
|
232
|
+
|
|
233
|
+
const variables: ProcessVariable[] = [];
|
|
234
|
+
|
|
235
|
+
if (response.data.value) {
|
|
236
|
+
for (const variable of response.data.value) {
|
|
237
|
+
variables.push({
|
|
238
|
+
name: variable.Name,
|
|
239
|
+
value: variable.Value !== undefined ? variable.Value : null,
|
|
240
|
+
type: variable.Type || 'Unknown',
|
|
241
|
+
scope: variable.Scope || 'Local'
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Update session cache
|
|
247
|
+
session.variables = variables.reduce((acc, v) => {
|
|
248
|
+
acc[v.name] = v.value;
|
|
249
|
+
return acc;
|
|
250
|
+
}, {} as { [key: string]: any });
|
|
251
|
+
|
|
252
|
+
return variables;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Set a process variable value during debugging
|
|
257
|
+
*
|
|
258
|
+
* @param sessionId - Debug session ID
|
|
259
|
+
* @param variable - Variable name
|
|
260
|
+
* @param value - New value
|
|
261
|
+
* @returns Promise<void>
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* await debuggerService.setProcessVariable(sessionId, 'vCounter', 10);
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
public async setProcessVariable(
|
|
269
|
+
sessionId: string,
|
|
270
|
+
variable: string,
|
|
271
|
+
value: any
|
|
272
|
+
): Promise<void> {
|
|
273
|
+
const session = this.activeSessions.get(sessionId);
|
|
274
|
+
if (!session) {
|
|
275
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const url = formatUrl("/Processes('{}')/Variables('{}')", session.processName, variable);
|
|
279
|
+
await this.rest.patch(url, { Value: value });
|
|
280
|
+
|
|
281
|
+
// Update session cache
|
|
282
|
+
if (session.variables) {
|
|
283
|
+
session.variables[variable] = value;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Evaluate a TM1 expression in the debug context
|
|
289
|
+
*
|
|
290
|
+
* @param sessionId - Debug session ID
|
|
291
|
+
* @param expression - TM1 expression to evaluate
|
|
292
|
+
* @returns Promise<any> - Evaluation result
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```typescript
|
|
296
|
+
* const result = await debuggerService.evaluateExpression(
|
|
297
|
+
* sessionId,
|
|
298
|
+
* 'vCounter + 10'
|
|
299
|
+
* );
|
|
300
|
+
* console.log('Result:', result);
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
public async evaluateExpression(sessionId: string, expression: string): Promise<any> {
|
|
304
|
+
const session = this.activeSessions.get(sessionId);
|
|
305
|
+
if (!session) {
|
|
306
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const url = formatUrl("/Processes('{}')/tm1.Evaluate", session.processName);
|
|
310
|
+
const response = await this.rest.post(url, { Expression: expression });
|
|
311
|
+
|
|
312
|
+
return response.data.Result !== undefined ? response.data.Result : response.data.value;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Get the current call stack
|
|
317
|
+
*
|
|
318
|
+
* @param sessionId - Debug session ID
|
|
319
|
+
* @returns Promise<CallStackFrame[]> - Call stack frames
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```typescript
|
|
323
|
+
* const callStack = await debuggerService.getCallStack(sessionId);
|
|
324
|
+
* callStack.forEach(frame => {
|
|
325
|
+
* console.log(`${frame.procedureName} at line ${frame.lineNumber}`);
|
|
326
|
+
* });
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
public async getCallStack(sessionId: string): Promise<CallStackFrame[]> {
|
|
330
|
+
const session = this.activeSessions.get(sessionId);
|
|
331
|
+
if (!session) {
|
|
332
|
+
throw new Error(`Debug session ${sessionId} not found`);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const url = formatUrl("/Processes('{}')/tm1.GetCallStack", session.processName);
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
const response = await this.rest.get(url);
|
|
339
|
+
|
|
340
|
+
if (response.data.value) {
|
|
341
|
+
return response.data.value.map((frame: any) => ({
|
|
342
|
+
procedureName: frame.ProcedureName || frame.Name,
|
|
343
|
+
lineNumber: frame.LineNumber || 0,
|
|
344
|
+
source: frame.Source
|
|
345
|
+
}));
|
|
346
|
+
}
|
|
347
|
+
} catch (error: any) {
|
|
348
|
+
// If call stack API not available, return basic info
|
|
349
|
+
if (error.response?.status === 404) {
|
|
350
|
+
return [{
|
|
351
|
+
procedureName: session.processName,
|
|
352
|
+
lineNumber: session.currentLine || 0
|
|
353
|
+
}];
|
|
354
|
+
}
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Get debug session info
|
|
363
|
+
*
|
|
364
|
+
* @param sessionId - Debug session ID
|
|
365
|
+
* @returns DebugSession | undefined - Session information
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```typescript
|
|
369
|
+
* const session = debuggerService.getSessionInfo(sessionId);
|
|
370
|
+
* console.log('Status:', session?.status);
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
public getSessionInfo(sessionId: string): DebugSession | undefined {
|
|
374
|
+
return this.activeSessions.get(sessionId);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* List all active debug sessions
|
|
379
|
+
*
|
|
380
|
+
* @returns DebugSession[] - Array of active sessions
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* ```typescript
|
|
384
|
+
* const sessions = debuggerService.listActiveSessions();
|
|
385
|
+
* console.log(`${sessions.length} active sessions`);
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
public listActiveSessions(): DebugSession[] {
|
|
389
|
+
return Array.from(this.activeSessions.values());
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Generate a unique session ID
|
|
394
|
+
* @private
|
|
395
|
+
*/
|
|
396
|
+
private generateSessionId(): string {
|
|
397
|
+
return `debug_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
@@ -686,4 +686,166 @@ export class ProcessService extends ObjectService {
|
|
|
686
686
|
throw error;
|
|
687
687
|
}
|
|
688
688
|
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Analyze process dependencies (what cubes/dimensions/processes it uses)
|
|
692
|
+
*
|
|
693
|
+
* @param processName - Name of the process
|
|
694
|
+
* @returns Promise<any> - Dependency information
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```typescript
|
|
698
|
+
* const deps = await processService.analyzeProcessDependencies('ImportData');
|
|
699
|
+
* console.log('Cubes used:', deps.cubes);
|
|
700
|
+
* console.log('Dimensions used:', deps.dimensions);
|
|
701
|
+
* ```
|
|
702
|
+
*/
|
|
703
|
+
public async analyzeProcessDependencies(processName: string): Promise<any> {
|
|
704
|
+
// Get process code
|
|
705
|
+
const process = await this.get(processName);
|
|
706
|
+
|
|
707
|
+
const dependencies = {
|
|
708
|
+
cubes: [] as string[],
|
|
709
|
+
dimensions: [] as string[],
|
|
710
|
+
processes: [] as string[],
|
|
711
|
+
subsets: [] as string[]
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
// Extract all code sections
|
|
715
|
+
const allCode = [
|
|
716
|
+
process.prologProcedure || '',
|
|
717
|
+
process.metadataProcedure || '',
|
|
718
|
+
process.dataProcedure || '',
|
|
719
|
+
process.epilogProcedure || ''
|
|
720
|
+
].join('\n');
|
|
721
|
+
|
|
722
|
+
// Cube references (CellGetN, CellPutN, CubeExists, etc.)
|
|
723
|
+
const cubeMatches = allCode.match(/(?:CellGetN|CellPutN|CubeExists|CubeClear|CubeCreate|CubeDestroy)\s*\(\s*['"]([^'"]+)['"]/gi);
|
|
724
|
+
if (cubeMatches) {
|
|
725
|
+
cubeMatches.forEach(match => {
|
|
726
|
+
const cubeMatch = match.match(/['"]([^'"]+)['"]/);
|
|
727
|
+
if (cubeMatch && cubeMatch[1]) {
|
|
728
|
+
if (!dependencies.cubes.includes(cubeMatch[1])) {
|
|
729
|
+
dependencies.cubes.push(cubeMatch[1]);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Dimension references
|
|
736
|
+
const dimMatches = allCode.match(/(?:DimensionCreate|DimensionExists|DimIx)\s*\(\s*['"]([^'"]+)['"]/gi);
|
|
737
|
+
if (dimMatches) {
|
|
738
|
+
dimMatches.forEach(match => {
|
|
739
|
+
const dimMatch = match.match(/['"]([^'"]+)['"]/);
|
|
740
|
+
if (dimMatch && dimMatch[1]) {
|
|
741
|
+
if (!dependencies.dimensions.includes(dimMatch[1])) {
|
|
742
|
+
dependencies.dimensions.push(dimMatch[1]);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Process references (ExecuteProcess)
|
|
749
|
+
const processMatches = allCode.match(/ExecuteProcess\s*\(\s*['"]([^'"]+)['"]/gi);
|
|
750
|
+
if (processMatches) {
|
|
751
|
+
processMatches.forEach(match => {
|
|
752
|
+
const procMatch = match.match(/['"]([^'"]+)['"]/);
|
|
753
|
+
if (procMatch && procMatch[1]) {
|
|
754
|
+
if (!dependencies.processes.includes(procMatch[1])) {
|
|
755
|
+
dependencies.processes.push(procMatch[1]);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
return dependencies;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Validate process syntax without executing it
|
|
766
|
+
*
|
|
767
|
+
* @param processName - Name of the process
|
|
768
|
+
* @returns Promise<{isValid: boolean, errors: any[]}> - Validation result
|
|
769
|
+
*
|
|
770
|
+
* @example
|
|
771
|
+
* ```typescript
|
|
772
|
+
* const result = await processService.validateProcessSyntax('MyProcess');
|
|
773
|
+
* if (!result.isValid) {
|
|
774
|
+
* console.error('Errors:', result.errors);
|
|
775
|
+
* }
|
|
776
|
+
* ```
|
|
777
|
+
*/
|
|
778
|
+
public async validateProcessSyntax(processName: string): Promise<{isValid: boolean, errors: any[]}> {
|
|
779
|
+
try {
|
|
780
|
+
const result = await this.compileProcess(processName);
|
|
781
|
+
return {
|
|
782
|
+
isValid: result.success,
|
|
783
|
+
errors: result.errors.map((error, index) => ({
|
|
784
|
+
line: index + 1,
|
|
785
|
+
message: error,
|
|
786
|
+
severity: 'Error'
|
|
787
|
+
}))
|
|
788
|
+
};
|
|
789
|
+
} catch (error: any) {
|
|
790
|
+
return {
|
|
791
|
+
isValid: false,
|
|
792
|
+
errors: [{
|
|
793
|
+
line: 0,
|
|
794
|
+
message: error.message || 'Validation failed',
|
|
795
|
+
severity: 'Error'
|
|
796
|
+
}]
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Get process execution plan (estimated resource usage)
|
|
803
|
+
*
|
|
804
|
+
* @param processName - Name of the process
|
|
805
|
+
* @returns Promise<any> - Execution plan information
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```typescript
|
|
809
|
+
* const plan = await processService.getProcessExecutionPlan('ImportData');
|
|
810
|
+
* console.log('Estimated execution time:', plan.estimatedTime);
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
public async getProcessExecutionPlan(processName: string): Promise<any> {
|
|
814
|
+
const process = await this.get(processName);
|
|
815
|
+
|
|
816
|
+
// Analyze process characteristics
|
|
817
|
+
const plan = {
|
|
818
|
+
processName: process.name,
|
|
819
|
+
hasDataSource: !!(process as any).dataSource,
|
|
820
|
+
dataSourceType: (process as any).dataSource?.type || 'None',
|
|
821
|
+
hasParameters: process.parameters && process.parameters.length > 0,
|
|
822
|
+
parameterCount: process.parameters ? process.parameters.length : 0,
|
|
823
|
+
hasVariables: process.variables && process.variables.length > 0,
|
|
824
|
+
variableCount: process.variables ? process.variables.length : 0,
|
|
825
|
+
procedures: {
|
|
826
|
+
hasPrologProcedure: !!(process.prologProcedure && process.prologProcedure.trim()),
|
|
827
|
+
hasMetadataProcedure: !!(process.metadataProcedure && process.metadataProcedure.trim()),
|
|
828
|
+
hasDataProcedure: !!(process.dataProcedure && process.dataProcedure.trim()),
|
|
829
|
+
hasEpilogProcedure: !!(process.epilogProcedure && process.epilogProcedure.trim())
|
|
830
|
+
},
|
|
831
|
+
estimatedComplexity: 'Unknown'
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
// Estimate complexity
|
|
835
|
+
const totalCodeLength =
|
|
836
|
+
(process.prologProcedure?.length || 0) +
|
|
837
|
+
(process.metadataProcedure?.length || 0) +
|
|
838
|
+
(process.dataProcedure?.length || 0) +
|
|
839
|
+
(process.epilogProcedure?.length || 0);
|
|
840
|
+
|
|
841
|
+
if (totalCodeLength < 500) {
|
|
842
|
+
plan.estimatedComplexity = 'Low';
|
|
843
|
+
} else if (totalCodeLength < 2000) {
|
|
844
|
+
plan.estimatedComplexity = 'Medium';
|
|
845
|
+
} else {
|
|
846
|
+
plan.estimatedComplexity = 'High';
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
return plan;
|
|
850
|
+
}
|
|
689
851
|
}
|
|
@@ -3,6 +3,7 @@ import { DimensionService } from './DimensionService';
|
|
|
3
3
|
import { HierarchyService } from './HierarchyService';
|
|
4
4
|
import { SubsetService } from './SubsetService';
|
|
5
5
|
import { DataFrameService } from './DataFrameService';
|
|
6
|
+
import { DebuggerService } from './DebuggerService';
|
|
6
7
|
import {
|
|
7
8
|
CubeService,
|
|
8
9
|
ElementService,
|
|
@@ -33,6 +34,7 @@ export class TM1Service {
|
|
|
33
34
|
public files: FileService;
|
|
34
35
|
public sessions: SessionService;
|
|
35
36
|
public dataframes: DataFrameService;
|
|
37
|
+
public debugger: DebuggerService;
|
|
36
38
|
|
|
37
39
|
constructor(config: RestServiceConfig) {
|
|
38
40
|
this._tm1Rest = new RestService(config);
|
|
@@ -50,6 +52,7 @@ export class TM1Service {
|
|
|
50
52
|
this.files = new FileService(this._tm1Rest);
|
|
51
53
|
this.sessions = new SessionService(this._tm1Rest);
|
|
52
54
|
this.dataframes = new DataFrameService(this._tm1Rest);
|
|
55
|
+
this.debugger = new DebuggerService(this._tm1Rest);
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
public async connect(): Promise<void> {
|
package/src/services/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ export { ConfigurationService } from './ConfigurationService';
|
|
|
11
11
|
export { ServerService } from './ServerService';
|
|
12
12
|
export { MonitoringService } from './MonitoringService';
|
|
13
13
|
export { DataFrameService } from './DataFrameService';
|
|
14
|
+
export { DebuggerService } from './DebuggerService';
|
|
14
15
|
|
|
15
16
|
// Additional services
|
|
16
17
|
export { AnnotationService } from './AnnotationService';
|