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
|
@@ -582,6 +582,158 @@ class ProcessService extends ObjectService_1.ObjectService {
|
|
|
582
582
|
throw error;
|
|
583
583
|
}
|
|
584
584
|
}
|
|
585
|
+
/**
|
|
586
|
+
* Analyze process dependencies (what cubes/dimensions/processes it uses)
|
|
587
|
+
*
|
|
588
|
+
* @param processName - Name of the process
|
|
589
|
+
* @returns Promise<any> - Dependency information
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* ```typescript
|
|
593
|
+
* const deps = await processService.analyzeProcessDependencies('ImportData');
|
|
594
|
+
* console.log('Cubes used:', deps.cubes);
|
|
595
|
+
* console.log('Dimensions used:', deps.dimensions);
|
|
596
|
+
* ```
|
|
597
|
+
*/
|
|
598
|
+
async analyzeProcessDependencies(processName) {
|
|
599
|
+
// Get process code
|
|
600
|
+
const process = await this.get(processName);
|
|
601
|
+
const dependencies = {
|
|
602
|
+
cubes: [],
|
|
603
|
+
dimensions: [],
|
|
604
|
+
processes: [],
|
|
605
|
+
subsets: []
|
|
606
|
+
};
|
|
607
|
+
// Extract all code sections
|
|
608
|
+
const allCode = [
|
|
609
|
+
process.prologProcedure || '',
|
|
610
|
+
process.metadataProcedure || '',
|
|
611
|
+
process.dataProcedure || '',
|
|
612
|
+
process.epilogProcedure || ''
|
|
613
|
+
].join('\n');
|
|
614
|
+
// Cube references (CellGetN, CellPutN, CubeExists, etc.)
|
|
615
|
+
const cubeMatches = allCode.match(/(?:CellGetN|CellPutN|CubeExists|CubeClear|CubeCreate|CubeDestroy)\s*\(\s*['"]([^'"]+)['"]/gi);
|
|
616
|
+
if (cubeMatches) {
|
|
617
|
+
cubeMatches.forEach(match => {
|
|
618
|
+
const cubeMatch = match.match(/['"]([^'"]+)['"]/);
|
|
619
|
+
if (cubeMatch && cubeMatch[1]) {
|
|
620
|
+
if (!dependencies.cubes.includes(cubeMatch[1])) {
|
|
621
|
+
dependencies.cubes.push(cubeMatch[1]);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
// Dimension references
|
|
627
|
+
const dimMatches = allCode.match(/(?:DimensionCreate|DimensionExists|DimIx)\s*\(\s*['"]([^'"]+)['"]/gi);
|
|
628
|
+
if (dimMatches) {
|
|
629
|
+
dimMatches.forEach(match => {
|
|
630
|
+
const dimMatch = match.match(/['"]([^'"]+)['"]/);
|
|
631
|
+
if (dimMatch && dimMatch[1]) {
|
|
632
|
+
if (!dependencies.dimensions.includes(dimMatch[1])) {
|
|
633
|
+
dependencies.dimensions.push(dimMatch[1]);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
// Process references (ExecuteProcess)
|
|
639
|
+
const processMatches = allCode.match(/ExecuteProcess\s*\(\s*['"]([^'"]+)['"]/gi);
|
|
640
|
+
if (processMatches) {
|
|
641
|
+
processMatches.forEach(match => {
|
|
642
|
+
const procMatch = match.match(/['"]([^'"]+)['"]/);
|
|
643
|
+
if (procMatch && procMatch[1]) {
|
|
644
|
+
if (!dependencies.processes.includes(procMatch[1])) {
|
|
645
|
+
dependencies.processes.push(procMatch[1]);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
return dependencies;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Validate process syntax without executing it
|
|
654
|
+
*
|
|
655
|
+
* @param processName - Name of the process
|
|
656
|
+
* @returns Promise<{isValid: boolean, errors: any[]}> - Validation result
|
|
657
|
+
*
|
|
658
|
+
* @example
|
|
659
|
+
* ```typescript
|
|
660
|
+
* const result = await processService.validateProcessSyntax('MyProcess');
|
|
661
|
+
* if (!result.isValid) {
|
|
662
|
+
* console.error('Errors:', result.errors);
|
|
663
|
+
* }
|
|
664
|
+
* ```
|
|
665
|
+
*/
|
|
666
|
+
async validateProcessSyntax(processName) {
|
|
667
|
+
try {
|
|
668
|
+
const result = await this.compileProcess(processName);
|
|
669
|
+
return {
|
|
670
|
+
isValid: result.success,
|
|
671
|
+
errors: result.errors.map((error, index) => ({
|
|
672
|
+
line: index + 1,
|
|
673
|
+
message: error,
|
|
674
|
+
severity: 'Error'
|
|
675
|
+
}))
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
return {
|
|
680
|
+
isValid: false,
|
|
681
|
+
errors: [{
|
|
682
|
+
line: 0,
|
|
683
|
+
message: error.message || 'Validation failed',
|
|
684
|
+
severity: 'Error'
|
|
685
|
+
}]
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Get process execution plan (estimated resource usage)
|
|
691
|
+
*
|
|
692
|
+
* @param processName - Name of the process
|
|
693
|
+
* @returns Promise<any> - Execution plan information
|
|
694
|
+
*
|
|
695
|
+
* @example
|
|
696
|
+
* ```typescript
|
|
697
|
+
* const plan = await processService.getProcessExecutionPlan('ImportData');
|
|
698
|
+
* console.log('Estimated execution time:', plan.estimatedTime);
|
|
699
|
+
* ```
|
|
700
|
+
*/
|
|
701
|
+
async getProcessExecutionPlan(processName) {
|
|
702
|
+
var _a, _b, _c, _d, _e;
|
|
703
|
+
const process = await this.get(processName);
|
|
704
|
+
// Analyze process characteristics
|
|
705
|
+
const plan = {
|
|
706
|
+
processName: process.name,
|
|
707
|
+
hasDataSource: !!process.dataSource,
|
|
708
|
+
dataSourceType: ((_a = process.dataSource) === null || _a === void 0 ? void 0 : _a.type) || 'None',
|
|
709
|
+
hasParameters: process.parameters && process.parameters.length > 0,
|
|
710
|
+
parameterCount: process.parameters ? process.parameters.length : 0,
|
|
711
|
+
hasVariables: process.variables && process.variables.length > 0,
|
|
712
|
+
variableCount: process.variables ? process.variables.length : 0,
|
|
713
|
+
procedures: {
|
|
714
|
+
hasPrologProcedure: !!(process.prologProcedure && process.prologProcedure.trim()),
|
|
715
|
+
hasMetadataProcedure: !!(process.metadataProcedure && process.metadataProcedure.trim()),
|
|
716
|
+
hasDataProcedure: !!(process.dataProcedure && process.dataProcedure.trim()),
|
|
717
|
+
hasEpilogProcedure: !!(process.epilogProcedure && process.epilogProcedure.trim())
|
|
718
|
+
},
|
|
719
|
+
estimatedComplexity: 'Unknown'
|
|
720
|
+
};
|
|
721
|
+
// Estimate complexity
|
|
722
|
+
const totalCodeLength = (((_b = process.prologProcedure) === null || _b === void 0 ? void 0 : _b.length) || 0) +
|
|
723
|
+
(((_c = process.metadataProcedure) === null || _c === void 0 ? void 0 : _c.length) || 0) +
|
|
724
|
+
(((_d = process.dataProcedure) === null || _d === void 0 ? void 0 : _d.length) || 0) +
|
|
725
|
+
(((_e = process.epilogProcedure) === null || _e === void 0 ? void 0 : _e.length) || 0);
|
|
726
|
+
if (totalCodeLength < 500) {
|
|
727
|
+
plan.estimatedComplexity = 'Low';
|
|
728
|
+
}
|
|
729
|
+
else if (totalCodeLength < 2000) {
|
|
730
|
+
plan.estimatedComplexity = 'Medium';
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
plan.estimatedComplexity = 'High';
|
|
734
|
+
}
|
|
735
|
+
return plan;
|
|
736
|
+
}
|
|
585
737
|
}
|
|
586
738
|
exports.ProcessService = ProcessService;
|
|
587
739
|
//# sourceMappingURL=ProcessService.js.map
|
|
@@ -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 { CubeService, ElementService, CellService, ProcessService, ViewService, SecurityService, FileService, SessionService, ServerService, MonitoringService } from './index';
|
|
7
8
|
export declare class TM1Service {
|
|
8
9
|
private _tm1Rest;
|
|
@@ -20,6 +21,7 @@ export declare class TM1Service {
|
|
|
20
21
|
files: FileService;
|
|
21
22
|
sessions: SessionService;
|
|
22
23
|
dataframes: DataFrameService;
|
|
24
|
+
debugger: DebuggerService;
|
|
23
25
|
constructor(config: RestServiceConfig);
|
|
24
26
|
connect(): Promise<void>;
|
|
25
27
|
logout(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TM1Service.d.ts","sourceRoot":"","sources":["../../src/services/TM1Service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EACH,WAAW,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAEjB,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,WAAW,CAAC,CAAoB;IAEjC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"TM1Service.d.ts","sourceRoot":"","sources":["../../src/services/TM1Service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACH,WAAW,EACX,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAEjB,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,WAAW,CAAC,CAAoB;IAEjC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,eAAe,CAAC;gBAErB,MAAM,EAAE,iBAAiB;IAmBxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxC,IAAW,MAAM,IAAI,aAAa,CAKjC;IAED,IAAW,UAAU,IAAI,iBAAiB,CAKzC;IAEY,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAKzB,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC;IAK3B,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAK1C,IAAW,UAAU,IAAI,WAAW,CAEnC;IAEM,YAAY,IAAI,MAAM,GAAG,SAAS;IAIlC,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAItC,UAAU,IAAI,MAAM,GAAG,SAAS;IAIhC,UAAU,IAAI,OAAO;IAIf,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;WAMxB,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAO7D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAOxC"}
|
|
@@ -6,6 +6,7 @@ const DimensionService_1 = require("./DimensionService");
|
|
|
6
6
|
const HierarchyService_1 = require("./HierarchyService");
|
|
7
7
|
const SubsetService_1 = require("./SubsetService");
|
|
8
8
|
const DataFrameService_1 = require("./DataFrameService");
|
|
9
|
+
const DebuggerService_1 = require("./DebuggerService");
|
|
9
10
|
const index_1 = require("./index");
|
|
10
11
|
class TM1Service {
|
|
11
12
|
constructor(config) {
|
|
@@ -23,6 +24,7 @@ class TM1Service {
|
|
|
23
24
|
this.files = new index_1.FileService(this._tm1Rest);
|
|
24
25
|
this.sessions = new index_1.SessionService(this._tm1Rest);
|
|
25
26
|
this.dataframes = new DataFrameService_1.DataFrameService(this._tm1Rest);
|
|
27
|
+
this.debugger = new DebuggerService_1.DebuggerService(this._tm1Rest);
|
|
26
28
|
}
|
|
27
29
|
async connect() {
|
|
28
30
|
await this._tm1Rest.connect();
|
package/lib/services/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { ConfigurationService } from './ConfigurationService';
|
|
|
10
10
|
export { ServerService } from './ServerService';
|
|
11
11
|
export { MonitoringService } from './MonitoringService';
|
|
12
12
|
export { DataFrameService } from './DataFrameService';
|
|
13
|
+
export { DebuggerService } from './DebuggerService';
|
|
13
14
|
export { AnnotationService } from './AnnotationService';
|
|
14
15
|
export { ApplicationService } from './ApplicationService';
|
|
15
16
|
export { AuditLogService } from './AuditLogService';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
package/lib/services/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UserService = exports.TransactionLogService = exports.ThreadService = exports.SandboxService = exports.PowerBiService = exports.MessageLogService = exports.ManageService = exports.LoggerService = exports.JobService = exports.GitService = exports.ChoreService = exports.AuditLogService = exports.ApplicationService = exports.AnnotationService = exports.DataFrameService = exports.MonitoringService = exports.ServerService = exports.ConfigurationService = exports.SessionService = exports.FileService = exports.SecurityService = exports.ViewService = exports.ProcessService = exports.CellService = exports.ElementService = exports.CubeService = void 0;
|
|
3
|
+
exports.UserService = exports.TransactionLogService = exports.ThreadService = exports.SandboxService = exports.PowerBiService = exports.MessageLogService = exports.ManageService = exports.LoggerService = exports.JobService = exports.GitService = exports.ChoreService = exports.AuditLogService = exports.ApplicationService = exports.AnnotationService = exports.DebuggerService = exports.DataFrameService = exports.MonitoringService = exports.ServerService = exports.ConfigurationService = exports.SessionService = exports.FileService = exports.SecurityService = exports.ViewService = exports.ProcessService = exports.CellService = exports.ElementService = exports.CubeService = void 0;
|
|
4
4
|
// Export all service implementations
|
|
5
5
|
var CubeService_1 = require("./CubeService");
|
|
6
6
|
Object.defineProperty(exports, "CubeService", { enumerable: true, get: function () { return CubeService_1.CubeService; } });
|
|
@@ -26,6 +26,8 @@ var MonitoringService_1 = require("./MonitoringService");
|
|
|
26
26
|
Object.defineProperty(exports, "MonitoringService", { enumerable: true, get: function () { return MonitoringService_1.MonitoringService; } });
|
|
27
27
|
var DataFrameService_1 = require("./DataFrameService");
|
|
28
28
|
Object.defineProperty(exports, "DataFrameService", { enumerable: true, get: function () { return DataFrameService_1.DataFrameService; } });
|
|
29
|
+
var DebuggerService_1 = require("./DebuggerService");
|
|
30
|
+
Object.defineProperty(exports, "DebuggerService", { enumerable: true, get: function () { return DebuggerService_1.DebuggerService; } });
|
|
29
31
|
// Additional services
|
|
30
32
|
var AnnotationService_1 = require("./AnnotationService");
|
|
31
33
|
Object.defineProperty(exports, "AnnotationService", { enumerable: true, get: function () { return AnnotationService_1.AnnotationService; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debuggerService.test.d.ts","sourceRoot":"","sources":["../../src/tests/debuggerService.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Unit tests for DebuggerService (Issue #13)
|
|
4
|
+
* Tests debug session management, variable inspection, and process analysis
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const DebuggerService_1 = require("../services/DebuggerService");
|
|
8
|
+
const ProcessService_1 = require("../services/ProcessService");
|
|
9
|
+
const RestService_1 = require("../services/RestService");
|
|
10
|
+
// Mock RestService
|
|
11
|
+
jest.mock('../services/RestService');
|
|
12
|
+
// Helper to create mock AxiosResponse
|
|
13
|
+
const createMockResponse = (data) => ({
|
|
14
|
+
data,
|
|
15
|
+
status: 200,
|
|
16
|
+
statusText: 'OK',
|
|
17
|
+
headers: {},
|
|
18
|
+
config: {}
|
|
19
|
+
});
|
|
20
|
+
describe('DebuggerService and Enhanced Process Debugging (Issue #13)', () => {
|
|
21
|
+
let debuggerService;
|
|
22
|
+
let processService;
|
|
23
|
+
let mockRestService;
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
mockRestService = new RestService_1.RestService({
|
|
26
|
+
address: 'localhost',
|
|
27
|
+
port: 8001,
|
|
28
|
+
user: 'admin',
|
|
29
|
+
password: 'apple'
|
|
30
|
+
});
|
|
31
|
+
debuggerService = new DebuggerService_1.DebuggerService(mockRestService);
|
|
32
|
+
processService = new ProcessService_1.ProcessService(mockRestService);
|
|
33
|
+
});
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
jest.clearAllMocks();
|
|
36
|
+
});
|
|
37
|
+
describe('DebuggerService - Session Management', () => {
|
|
38
|
+
describe('createDebugSession', () => {
|
|
39
|
+
it('should create a debug session successfully', async () => {
|
|
40
|
+
mockRestService.post.mockResolvedValue(createMockResponse({
|
|
41
|
+
ID: 'debug-session-123'
|
|
42
|
+
}));
|
|
43
|
+
const sessionId = await debuggerService.createDebugSession('MyProcess');
|
|
44
|
+
expect(sessionId).toBeDefined();
|
|
45
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.BeginDebug", {});
|
|
46
|
+
});
|
|
47
|
+
it('should track the created session', async () => {
|
|
48
|
+
mockRestService.post.mockResolvedValue(createMockResponse({
|
|
49
|
+
ID: 'debug-session-456'
|
|
50
|
+
}));
|
|
51
|
+
const sessionId = await debuggerService.createDebugSession('TestProcess');
|
|
52
|
+
const sessionInfo = debuggerService.getSessionInfo(sessionId);
|
|
53
|
+
expect(sessionInfo).toBeDefined();
|
|
54
|
+
expect(sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.processName).toBe('TestProcess');
|
|
55
|
+
expect(sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.status).toBe('Paused');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe('terminateDebugSession', () => {
|
|
59
|
+
it('should terminate a debug session', async () => {
|
|
60
|
+
mockRestService.post.mockResolvedValueOnce(createMockResponse({ ID: 'session-789' }));
|
|
61
|
+
mockRestService.post.mockResolvedValueOnce(createMockResponse({}));
|
|
62
|
+
const sessionId = await debuggerService.createDebugSession('MyProcess');
|
|
63
|
+
await debuggerService.terminateDebugSession(sessionId);
|
|
64
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.EndDebug", {});
|
|
65
|
+
const sessionInfo = debuggerService.getSessionInfo(sessionId);
|
|
66
|
+
expect(sessionInfo).toBeUndefined();
|
|
67
|
+
});
|
|
68
|
+
it('should throw error if session not found', async () => {
|
|
69
|
+
await expect(debuggerService.terminateDebugSession('non-existent')).rejects.toThrow('Debug session non-existent not found');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe('listActiveSessions', () => {
|
|
73
|
+
it('should list all active debug sessions', async () => {
|
|
74
|
+
mockRestService.post
|
|
75
|
+
.mockResolvedValueOnce(createMockResponse({ ID: 'session-1' }))
|
|
76
|
+
.mockResolvedValueOnce(createMockResponse({ ID: 'session-2' }));
|
|
77
|
+
await debuggerService.createDebugSession('Process1');
|
|
78
|
+
await debuggerService.createDebugSession('Process2');
|
|
79
|
+
const sessions = debuggerService.listActiveSessions();
|
|
80
|
+
expect(sessions).toHaveLength(2);
|
|
81
|
+
expect(sessions.some(s => s.processName === 'Process1')).toBe(true);
|
|
82
|
+
expect(sessions.some(s => s.processName === 'Process2')).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('DebuggerService - Debug Control', () => {
|
|
87
|
+
let sessionId;
|
|
88
|
+
beforeEach(async () => {
|
|
89
|
+
mockRestService.post.mockResolvedValue(createMockResponse({ ID: 'test-session' }));
|
|
90
|
+
sessionId = await debuggerService.createDebugSession('MyProcess');
|
|
91
|
+
});
|
|
92
|
+
describe('stepInto', () => {
|
|
93
|
+
it('should step into next line', async () => {
|
|
94
|
+
mockRestService.post.mockResolvedValue(createMockResponse({}));
|
|
95
|
+
await debuggerService.stepInto(sessionId);
|
|
96
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.DebugStepIn", {});
|
|
97
|
+
});
|
|
98
|
+
it('should throw error if session not found', async () => {
|
|
99
|
+
await expect(debuggerService.stepInto('invalid-session')).rejects.toThrow('Debug session invalid-session not found');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('stepOver', () => {
|
|
103
|
+
it('should step over next line', async () => {
|
|
104
|
+
mockRestService.post.mockResolvedValue(createMockResponse({}));
|
|
105
|
+
await debuggerService.stepOver(sessionId);
|
|
106
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.DebugStepOver", {});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('stepOut', () => {
|
|
110
|
+
it('should step out of current function', async () => {
|
|
111
|
+
mockRestService.post.mockResolvedValue(createMockResponse({}));
|
|
112
|
+
await debuggerService.stepOut(sessionId);
|
|
113
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.DebugStepOut", {});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('continueExecution', () => {
|
|
117
|
+
it('should continue execution', async () => {
|
|
118
|
+
mockRestService.post.mockResolvedValue(createMockResponse({}));
|
|
119
|
+
await debuggerService.continueExecution(sessionId);
|
|
120
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.DebugContinue", {});
|
|
121
|
+
const sessionInfo = debuggerService.getSessionInfo(sessionId);
|
|
122
|
+
expect(sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.status).toBe('Running');
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('DebuggerService - Variable Inspection', () => {
|
|
127
|
+
let sessionId;
|
|
128
|
+
beforeEach(async () => {
|
|
129
|
+
mockRestService.post.mockResolvedValue(createMockResponse({ ID: 'test-session' }));
|
|
130
|
+
sessionId = await debuggerService.createDebugSession('MyProcess');
|
|
131
|
+
});
|
|
132
|
+
describe('getProcessVariables', () => {
|
|
133
|
+
it('should get all process variables', async () => {
|
|
134
|
+
mockRestService.get.mockResolvedValue(createMockResponse({
|
|
135
|
+
value: [
|
|
136
|
+
{ Name: 'vCounter', Value: 10, Type: 'Numeric', Scope: 'Local' },
|
|
137
|
+
{ Name: 'vName', Value: 'Test', Type: 'String', Scope: 'Local' },
|
|
138
|
+
{ Name: 'pYear', Value: 2024, Type: 'Numeric', Scope: 'Parameter' }
|
|
139
|
+
]
|
|
140
|
+
}));
|
|
141
|
+
const variables = await debuggerService.getProcessVariables(sessionId);
|
|
142
|
+
expect(variables).toHaveLength(3);
|
|
143
|
+
expect(variables[0]).toMatchObject({
|
|
144
|
+
name: 'vCounter',
|
|
145
|
+
value: 10,
|
|
146
|
+
type: 'Numeric',
|
|
147
|
+
scope: 'Local'
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe('setProcessVariable', () => {
|
|
152
|
+
it('should set a process variable value', async () => {
|
|
153
|
+
mockRestService.patch.mockResolvedValue(createMockResponse({}));
|
|
154
|
+
await debuggerService.setProcessVariable(sessionId, 'vCounter', 20);
|
|
155
|
+
expect(mockRestService.patch).toHaveBeenCalledWith("/Processes('MyProcess')/Variables('vCounter')", { Value: 20 });
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe('evaluateExpression', () => {
|
|
159
|
+
it('should evaluate a TM1 expression', async () => {
|
|
160
|
+
mockRestService.post.mockResolvedValue(createMockResponse({
|
|
161
|
+
Result: 30
|
|
162
|
+
}));
|
|
163
|
+
const result = await debuggerService.evaluateExpression(sessionId, 'vCounter + 10');
|
|
164
|
+
expect(result).toBe(30);
|
|
165
|
+
expect(mockRestService.post).toHaveBeenCalledWith("/Processes('MyProcess')/tm1.Evaluate", { Expression: 'vCounter + 10' });
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
describe('getCallStack', () => {
|
|
169
|
+
it('should get the call stack', async () => {
|
|
170
|
+
mockRestService.get.mockResolvedValue(createMockResponse({
|
|
171
|
+
value: [
|
|
172
|
+
{ ProcedureName: 'Main', LineNumber: 10 },
|
|
173
|
+
{ ProcedureName: 'Prolog', LineNumber: 5 }
|
|
174
|
+
]
|
|
175
|
+
}));
|
|
176
|
+
const callStack = await debuggerService.getCallStack(sessionId);
|
|
177
|
+
expect(callStack).toHaveLength(2);
|
|
178
|
+
expect(callStack[0].procedureName).toBe('Main');
|
|
179
|
+
expect(callStack[0].lineNumber).toBe(10);
|
|
180
|
+
});
|
|
181
|
+
it('should return basic info if call stack API not available', async () => {
|
|
182
|
+
mockRestService.get.mockRejectedValue({ response: { status: 404 } });
|
|
183
|
+
const callStack = await debuggerService.getCallStack(sessionId);
|
|
184
|
+
expect(callStack).toHaveLength(1);
|
|
185
|
+
expect(callStack[0].procedureName).toBe('MyProcess');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
describe('ProcessService - Enhanced Debugging', () => {
|
|
190
|
+
describe('analyzeProcessDependencies', () => {
|
|
191
|
+
it('should analyze process dependencies', async () => {
|
|
192
|
+
mockRestService.get.mockResolvedValue(createMockResponse({
|
|
193
|
+
Name: 'ImportData',
|
|
194
|
+
PrologProcedure: `
|
|
195
|
+
IF(CubeExists('Sales') = 0);
|
|
196
|
+
CubeCreate('Sales', 'Year', 'Month', 'Value');
|
|
197
|
+
ENDIF;
|
|
198
|
+
ExecuteProcess('SetupDimensions');
|
|
199
|
+
`,
|
|
200
|
+
DataProcedure: `
|
|
201
|
+
vValue = CellGetN('Budget', '2024', 'Jan');
|
|
202
|
+
CellPutN(vValue, 'Sales', '2024', 'Jan');
|
|
203
|
+
`,
|
|
204
|
+
EpilogProcedure: '',
|
|
205
|
+
MetadataProcedure: '',
|
|
206
|
+
Parameters: [],
|
|
207
|
+
Variables: []
|
|
208
|
+
}));
|
|
209
|
+
const deps = await processService.analyzeProcessDependencies('ImportData');
|
|
210
|
+
expect(deps.cubes).toContain('Sales');
|
|
211
|
+
expect(deps.cubes).toContain('Budget');
|
|
212
|
+
expect(deps.processes).toContain('SetupDimensions');
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('validateProcessSyntax', () => {
|
|
216
|
+
it('should return valid for correct syntax', async () => {
|
|
217
|
+
mockRestService.get.mockResolvedValue(createMockResponse({
|
|
218
|
+
Name: 'ValidProcess',
|
|
219
|
+
PrologProcedure: 'vCounter = 1;',
|
|
220
|
+
DataProcedure: '',
|
|
221
|
+
EpilogProcedure: '',
|
|
222
|
+
MetadataProcedure: '',
|
|
223
|
+
Parameters: [],
|
|
224
|
+
Variables: []
|
|
225
|
+
}));
|
|
226
|
+
mockRestService.post.mockResolvedValue(createMockResponse({}));
|
|
227
|
+
const result = await processService.validateProcessSyntax('ValidProcess');
|
|
228
|
+
expect(result.isValid).toBe(true);
|
|
229
|
+
expect(result.errors).toHaveLength(0);
|
|
230
|
+
});
|
|
231
|
+
it('should return errors for invalid syntax', async () => {
|
|
232
|
+
mockRestService.get.mockResolvedValue(createMockResponse({
|
|
233
|
+
Name: 'InvalidProcess',
|
|
234
|
+
PrologProcedure: 'INVALID SYNTAX;',
|
|
235
|
+
DataProcedure: '',
|
|
236
|
+
EpilogProcedure: '',
|
|
237
|
+
MetadataProcedure: '',
|
|
238
|
+
Parameters: [],
|
|
239
|
+
Variables: []
|
|
240
|
+
}));
|
|
241
|
+
mockRestService.post.mockRejectedValue({
|
|
242
|
+
response: {
|
|
243
|
+
status: 400,
|
|
244
|
+
data: {
|
|
245
|
+
error: {
|
|
246
|
+
message: 'Syntax error on line 1'
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
const result = await processService.validateProcessSyntax('InvalidProcess');
|
|
252
|
+
expect(result.isValid).toBe(false);
|
|
253
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
describe('getProcessExecutionPlan', () => {
|
|
257
|
+
it('should analyze process execution plan', async () => {
|
|
258
|
+
mockRestService.get.mockResolvedValue(createMockResponse({
|
|
259
|
+
Name: 'ComplexProcess',
|
|
260
|
+
PrologProcedure: 'A'.repeat(600),
|
|
261
|
+
DataProcedure: 'B'.repeat(800),
|
|
262
|
+
EpilogProcedure: 'C'.repeat(400),
|
|
263
|
+
MetadataProcedure: '',
|
|
264
|
+
Parameters: [{ Name: 'pYear', Type: 'Numeric' }],
|
|
265
|
+
Variables: [{ Name: 'vCounter', Type: 'Numeric' }]
|
|
266
|
+
}));
|
|
267
|
+
const plan = await processService.getProcessExecutionPlan('ComplexProcess');
|
|
268
|
+
expect(plan.processName).toBe('ComplexProcess');
|
|
269
|
+
expect(plan.hasParameters).toBe(true);
|
|
270
|
+
expect(plan.parameterCount).toBe(1);
|
|
271
|
+
expect(plan.hasVariables).toBe(true);
|
|
272
|
+
expect(plan.variableCount).toBe(1);
|
|
273
|
+
expect(plan.procedures.hasPrologProcedure).toBe(true);
|
|
274
|
+
expect(plan.estimatedComplexity).toBe('Medium');
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
//# sourceMappingURL=debuggerService.test.js.map
|