tm1npm 1.5.3 → 2.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/lib/index.d.ts +1 -1
  3. package/lib/index.d.ts.map +1 -1
  4. package/lib/services/ApplicationService.d.ts +19 -3
  5. package/lib/services/ApplicationService.d.ts.map +1 -1
  6. package/lib/services/ApplicationService.js +232 -6
  7. package/lib/services/AsyncOperationService.d.ts +8 -1
  8. package/lib/services/AsyncOperationService.d.ts.map +1 -1
  9. package/lib/services/AsyncOperationService.js +69 -26
  10. package/lib/services/ElementService.d.ts +67 -1
  11. package/lib/services/ElementService.d.ts.map +1 -1
  12. package/lib/services/ElementService.js +214 -0
  13. package/lib/services/FileService.d.ts.map +1 -1
  14. package/lib/services/HierarchyService.d.ts +26 -0
  15. package/lib/services/HierarchyService.d.ts.map +1 -1
  16. package/lib/services/HierarchyService.js +306 -0
  17. package/lib/services/ProcessService.d.ts +40 -22
  18. package/lib/services/ProcessService.d.ts.map +1 -1
  19. package/lib/services/ProcessService.js +118 -111
  20. package/lib/services/RestService.d.ts +213 -25
  21. package/lib/services/RestService.d.ts.map +1 -1
  22. package/lib/services/RestService.js +841 -263
  23. package/lib/services/SubsetService.d.ts +2 -0
  24. package/lib/services/SubsetService.d.ts.map +1 -1
  25. package/lib/services/SubsetService.js +33 -0
  26. package/lib/services/TM1Service.d.ts +44 -1
  27. package/lib/services/TM1Service.d.ts.map +1 -1
  28. package/lib/services/TM1Service.js +96 -4
  29. package/lib/services/index.d.ts +1 -1
  30. package/lib/services/index.d.ts.map +1 -1
  31. package/lib/tests/100PercentParityCheck.test.js +23 -6
  32. package/lib/tests/applicationService.issue38.test.d.ts +5 -0
  33. package/lib/tests/applicationService.issue38.test.d.ts.map +1 -0
  34. package/lib/tests/applicationService.issue38.test.js +237 -0
  35. package/lib/tests/asyncOperationService.test.js +51 -45
  36. package/lib/tests/bugfix28.test.js +12 -4
  37. package/lib/tests/elementService.issue37.test.d.ts +5 -0
  38. package/lib/tests/elementService.issue37.test.d.ts.map +1 -0
  39. package/lib/tests/elementService.issue37.test.js +413 -0
  40. package/lib/tests/elementService.issue38.test.d.ts +5 -0
  41. package/lib/tests/elementService.issue38.test.d.ts.map +1 -0
  42. package/lib/tests/elementService.issue38.test.js +79 -0
  43. package/lib/tests/hierarchyService.issue38.test.d.ts +5 -0
  44. package/lib/tests/hierarchyService.issue38.test.d.ts.map +1 -0
  45. package/lib/tests/hierarchyService.issue38.test.js +460 -0
  46. package/lib/tests/processService.comprehensive.test.js +9 -9
  47. package/lib/tests/processService.test.js +234 -0
  48. package/lib/tests/restService.test.d.ts +0 -4
  49. package/lib/tests/restService.test.d.ts.map +1 -1
  50. package/lib/tests/restService.test.js +1558 -143
  51. package/lib/tests/subsetService.issue38.test.d.ts +5 -0
  52. package/lib/tests/subsetService.issue38.test.d.ts.map +1 -0
  53. package/lib/tests/subsetService.issue38.test.js +113 -0
  54. package/lib/tests/tm1Service.test.js +80 -8
  55. package/package.json +1 -1
  56. package/src/index.ts +1 -1
  57. package/src/services/ApplicationService.ts +282 -10
  58. package/src/services/AsyncOperationService.ts +76 -29
  59. package/src/services/ElementService.ts +322 -1
  60. package/src/services/FileService.ts +3 -3
  61. package/src/services/HierarchyService.ts +419 -1
  62. package/src/services/ProcessService.ts +185 -142
  63. package/src/services/RestService.ts +1021 -267
  64. package/src/services/SubsetService.ts +48 -0
  65. package/src/services/TM1Service.ts +127 -6
  66. package/src/services/index.ts +1 -1
  67. package/src/tests/100PercentParityCheck.test.ts +29 -8
  68. package/src/tests/applicationService.issue38.test.ts +293 -0
  69. package/src/tests/asyncOperationService.test.ts +52 -48
  70. package/src/tests/bugfix28.test.ts +12 -4
  71. package/src/tests/elementService.issue37.test.ts +571 -0
  72. package/src/tests/elementService.issue38.test.ts +103 -0
  73. package/src/tests/hierarchyService.issue38.test.ts +599 -0
  74. package/src/tests/processService.comprehensive.test.ts +10 -10
  75. package/src/tests/processService.test.ts +295 -3
  76. package/src/tests/restService.test.ts +1844 -139
  77. package/src/tests/subsetService.issue38.test.ts +182 -0
  78. package/src/tests/tm1Service.test.ts +95 -11
@@ -1,13 +1,38 @@
1
1
  import { AxiosResponse } from 'axios';
2
2
  import { v4 as uuidv4 } from 'uuid';
3
- import { RestService } from './RestService';
3
+ import { RequestOptions, RestService } from './RestService';
4
4
  import { ObjectService } from './ObjectService';
5
5
  import { Process } from '../objects/Process';
6
- import { ProcessDebugBreakpoint } from '../objects/ProcessDebugBreakpoint';
6
+ import { ProcessDebugBreakpoint, BreakPointType, HitMode } from '../objects/ProcessDebugBreakpoint';
7
7
  import { TM1RestException, TM1Exception } from '../exceptions/TM1Exception';
8
8
  import { formatUrl, lowerAndDropSpaces } from '../utils/Utils';
9
9
  import { OperationStatus, OperationType } from './AsyncOperationService';
10
10
 
11
+ export interface CompileSyntaxError {
12
+ LineNumber: number;
13
+ Message: string;
14
+ }
15
+
16
+ interface ProcessExecuteBody {
17
+ Parameters?: Array<{ Name: string; Value: unknown }>;
18
+ }
19
+
20
+ interface ProcessExecuteSummary {
21
+ ProcessExecuteStatusCode: string;
22
+ ErrorLogFile?: { Filename?: string } | null;
23
+ }
24
+
25
+ interface ValidationError {
26
+ line: number;
27
+ message: string;
28
+ severity: string;
29
+ }
30
+
31
+ interface ValidationResult {
32
+ isValid: boolean;
33
+ errors: ValidationError[];
34
+ }
35
+
11
36
  export class ProcessService extends ObjectService {
12
37
  /** Service to handle Object Updates for TI Processes
13
38
  *
@@ -74,7 +99,7 @@ export class ProcessService extends ObjectService {
74
99
 
75
100
  const response = await this.rest.get(url);
76
101
  const responseAsDict = response.data;
77
- return responseAsDict.value.map((p: any) => Process.fromDict(p));
102
+ return responseAsDict.value.map((p: Record<string, unknown>) => Process.fromDict(p));
78
103
  }
79
104
 
80
105
  public async getAllNames(skipControlProcesses: boolean = false): Promise<string[]> {
@@ -88,7 +113,7 @@ export class ProcessService extends ObjectService {
88
113
  const url = "/Processes?$select=Name" + (skipControlProcesses ? modelProcessFilter : "");
89
114
 
90
115
  const response = await this.rest.get(url);
91
- const processes = response.data.value.map((process: any) => process.Name);
116
+ const processes = response.data.value.map((process: { Name: string }) => process.Name);
92
117
  return processes;
93
118
  }
94
119
 
@@ -169,8 +194,8 @@ export class ProcessService extends ObjectService {
169
194
  * :return: response
170
195
  */
171
196
  const url = formatUrl("/Processes('{}')/tm1.Execute", processName);
172
-
173
- const body: any = {};
197
+
198
+ const body: ProcessExecuteBody = {};
174
199
  if (parameters && Object.keys(parameters).length > 0) {
175
200
  body.Parameters = Object.entries(parameters).map(([name, value]) => ({
176
201
  Name: name,
@@ -194,8 +219,8 @@ export class ProcessService extends ObjectService {
194
219
  * :return: response including execution details
195
220
  */
196
221
  const url = formatUrl("/Processes('{}')/tm1.ExecuteWithReturn?$expand=*", processName);
197
-
198
- const body: any = {};
222
+
223
+ const body: ProcessExecuteBody = {};
199
224
  if (parameters && Object.keys(parameters).length > 0) {
200
225
  body.Parameters = Object.entries(parameters).map(([name, value]) => ({
201
226
  Name: name,
@@ -203,9 +228,9 @@ export class ProcessService extends ObjectService {
203
228
  }));
204
229
  }
205
230
 
206
- const config: any = {};
231
+ const config: RequestOptions = {};
207
232
  if (timeout) {
208
- config.timeout = timeout * 1000;
233
+ config.timeout = timeout;
209
234
  }
210
235
 
211
236
  return await this.rest.post(url, JSON.stringify(body), config);
@@ -221,105 +246,53 @@ export class ProcessService extends ObjectService {
221
246
  return await this.rest.post(url, '{}');
222
247
  }
223
248
 
224
- public async compileProcess(processName: string): Promise<{success: boolean, errors: string[]}> {
225
- /** Compile a process and return detailed compilation results
249
+ public async compileProcess(process: Process): Promise<CompileSyntaxError[]> {
250
+ /** Compile an unbound process and return syntax errors
226
251
  *
227
- * :param process_name: name of the process
228
- * :return: compilation result with success status and error details
252
+ * :param process: Instance of .Process class
253
+ * :return: list of syntax errors (empty if successful)
229
254
  */
230
- try {
231
- const response = await this.compile(processName);
232
-
233
- // Check if compilation was successful
234
- if (response.status === 200) {
235
- return {
236
- success: true,
237
- errors: []
238
- };
239
- } else {
240
- return {
241
- success: false,
242
- errors: [response.statusText || 'Compilation failed']
243
- };
244
- }
245
- } catch (error: any) {
246
- const errorMessage = error.response?.data?.error?.message || error.message || 'Unknown compilation error';
247
- return {
248
- success: false,
249
- errors: [errorMessage]
250
- };
251
- }
255
+ const url = '/CompileProcess';
256
+ const payload = { Process: process.bodyAsDict };
257
+ const response = await this.rest.post(url, JSON.stringify(payload));
258
+ return response.data.value;
252
259
  }
253
260
 
254
261
  /**
255
- * Poll execution status for async process execution
262
+ * Poll for async execution result
263
+ *
264
+ * :param asyncId: async operation ID returned from executeWithReturn with returnAsyncId=true
265
+ * :return: tuple of [success, status, errorLogFile] or null if not ready
256
266
  */
257
- public async pollExecuteWithReturn(
258
- processName: string,
259
- parameters?: Record<string, any>,
260
- timeout: number = 300,
261
- pollInterval: number = 5
262
- ): Promise<any> {
263
- /** Execute process asynchronously and poll for completion
264
- *
265
- * :param process_name: name of the process
266
- * :param parameters: dictionary of process parameters
267
- * :param timeout: maximum time to wait for completion (seconds)
268
- * :param poll_interval: time between status checks (seconds)
269
- * :return: execution result when completed
270
- */
271
-
272
- // Start async execution
273
- const executeUrl = formatUrl("/Processes('{}')/tm1.ExecuteAsync", processName);
274
- const body: any = {};
275
-
276
- if (parameters && Object.keys(parameters).length > 0) {
277
- body.Parameters = Object.entries(parameters).map(([name, value]) => ({
278
- Name: name,
279
- Value: value
280
- }));
281
- }
282
-
283
- const executeResponse = await this.rest.post(executeUrl, JSON.stringify(body));
284
- const executionId = executeResponse.data.ID || executeResponse.data.ExecutionId;
285
-
286
- if (!executionId) {
287
- throw new TM1Exception('Failed to start async process execution');
288
- }
289
-
290
- // Poll for completion
291
- const startTime = Date.now();
292
- const maxTime = timeout * 1000;
293
-
294
- while (Date.now() - startTime < maxTime) {
295
- try {
296
- // Check execution status
297
- const statusUrl = `/ExecutionStatus('${executionId}')`;
298
- const statusResponse = await this.rest.get(statusUrl);
299
- const status = statusResponse.data;
300
-
301
- if (status.Status === 'Completed') {
302
- // Get execution results
303
- const resultUrl = `/ExecutionResults('${executionId}')`;
304
- const resultResponse = await this.rest.get(resultUrl);
305
- return resultResponse.data;
306
- } else if (status.Status === 'Failed') {
307
- throw new TM1Exception(`Process execution failed: ${status.ErrorMessage || 'Unknown error'}`);
308
- }
309
-
310
- // Wait before next poll
311
- await new Promise(resolve => setTimeout(resolve, pollInterval * 1000));
312
-
313
- } catch (error) {
314
- if (error instanceof TM1Exception) {
315
- throw error;
316
- }
317
- // If status check fails, wait and retry
318
- await new Promise(resolve => setTimeout(resolve, pollInterval * 1000));
267
+ public async pollExecuteWithReturn(asyncId: string): Promise<[boolean, string, string | null] | null> {
268
+ try {
269
+ const response = await this.rest.retrieve_async_response(asyncId);
270
+ // tm1py returns None while the async op is still in-flight (status 202).
271
+ if (response.status !== 200 && response.status !== 201) {
272
+ return null;
319
273
  }
274
+ // TODO: tm1py handles TM1 < v11 binary-wrapped responses via
275
+ // build_response_from_binary_response. Add support if needed.
276
+ return this._executeWithReturnParseResponse(response.data);
277
+ } catch (error) {
278
+ // 404 means the async resource hasn't materialized yet — return null
279
+ // so the caller can retry. 202 means still running. Both are
280
+ // retryable, unlike AsyncOperationService which treats 404 as
281
+ // terminal FAILED for locally-tracked operations.
282
+ const err = error as { status?: number; response?: { status?: number } };
283
+ const status = err?.status ?? err?.response?.status;
284
+ if (status === 202 || status === 404) {
285
+ return null;
286
+ }
287
+ throw error;
320
288
  }
321
-
322
- throw new TM1Exception(`Process execution timed out after ${timeout} seconds`);
289
+ }
290
+
291
+ private _executeWithReturnParseResponse(executionSummary: ProcessExecuteSummary): [boolean, string, string | null] {
292
+ const success = executionSummary.ProcessExecuteStatusCode === 'CompletedSuccessfully';
293
+ const status = executionSummary.ProcessExecuteStatusCode;
294
+ const errorLogFile = executionSummary.ErrorLogFile?.Filename ?? null;
295
+ return [success, status, errorLogFile];
323
296
  }
324
297
 
325
298
  public async executeProcessWithReturn(
@@ -347,7 +320,7 @@ export class ProcessService extends ObjectService {
347
320
  return '';
348
321
  }
349
322
 
350
- public async getProcessDebugBreakpoints(debugId: string): Promise<ProcessDebugBreakpoint[]> {
323
+ public async debugGetBreakpoints(debugId: string): Promise<ProcessDebugBreakpoint[]> {
351
324
  /** Get debug breakpoints for a debug context
352
325
  *
353
326
  * :param debugId: debug session ID
@@ -355,28 +328,27 @@ export class ProcessService extends ObjectService {
355
328
  */
356
329
  const url = formatUrl("/ProcessDebugContexts('{}')/Breakpoints", debugId);
357
330
  const response = await this.rest.get(url);
358
- return response.data.value.map((bp: any) => ProcessDebugBreakpoint.fromDict(bp));
331
+ return response.data.value.map((bp: Record<string, unknown>) => ProcessDebugBreakpoint.fromDict(bp));
359
332
  }
360
333
 
361
- public async createProcessDebugBreakpoint(
334
+ public async debugAddBreakpoint(
362
335
  debugId: string,
363
336
  breakpoint: ProcessDebugBreakpoint
364
337
  ): Promise<AxiosResponse> {
365
- /** Create a debug breakpoint in a debug context
338
+ /** Add a single breakpoint to a debug context (delegates to debugAddBreakpoints)
366
339
  *
367
340
  * :param debugId: debug session ID
368
341
  * :param breakpoint: ProcessDebugBreakpoint object
369
342
  * :return: response
370
343
  */
371
- const url = formatUrl("/ProcessDebugContexts('{}')/Breakpoints", debugId);
372
- return await this.rest.post(url, breakpoint.body);
344
+ return this.debugAddBreakpoints(debugId, [breakpoint]);
373
345
  }
374
346
 
375
- public async deleteProcessDebugBreakpoint(
347
+ public async debugRemoveBreakpoint(
376
348
  debugId: string,
377
349
  breakpointId: number
378
350
  ): Promise<AxiosResponse> {
379
- /** Delete a debug breakpoint from a debug context
351
+ /** Remove a breakpoint from a debug context
380
352
  *
381
353
  * :param debugId: debug session ID
382
354
  * :param breakpointId: ID of the breakpoint
@@ -588,7 +560,7 @@ export class ProcessService extends ObjectService {
588
560
  }
589
561
 
590
562
  const response = await this.rest.get(url);
591
- return response.data.value.map((log: any) => log.Filename);
563
+ return response.data.value.map((log: { Filename: string }) => log.Filename);
592
564
  }
593
565
 
594
566
  public async getErrorLogFilenames(
@@ -675,7 +647,7 @@ export class ProcessService extends ObjectService {
675
647
  }
676
648
 
677
649
  const response = await this.rest.get(url);
678
- return response.data.value.map((process: any) => process.Name);
650
+ return response.data.value.map((process: { Name: string }) => process.Name);
679
651
  }
680
652
 
681
653
  public async updateOrCreate(process: Process): Promise<AxiosResponse> {
@@ -729,7 +701,7 @@ export class ProcessService extends ObjectService {
729
701
  processName
730
702
  );
731
703
 
732
- const body: any = {};
704
+ const body: ProcessExecuteBody = {};
733
705
  if (parameters && Object.keys(parameters).length > 0) {
734
706
  body.Parameters = Object.entries(parameters).map(([name, value]) => ({
735
707
  Name: name,
@@ -737,12 +709,14 @@ export class ProcessService extends ObjectService {
737
709
  }));
738
710
  }
739
711
 
740
- const config: any = {};
712
+ const config: RequestOptions = {};
741
713
  if (timeout) {
742
- config.timeout = timeout * 1000;
714
+ config.timeout = timeout;
743
715
  }
744
716
 
745
- const response = await this.rest.post(url, JSON.stringify(body), config);
717
+ // rest.post returns AxiosResponse | string (string only when caller
718
+ // opts into returnAsyncId). debugProcess never does, so narrow.
719
+ const response = (await this.rest.post(url, JSON.stringify(body), config)) as AxiosResponse;
746
720
  return response.data;
747
721
  }
748
722
 
@@ -859,6 +833,79 @@ export class ProcessService extends ObjectService {
859
833
  }
860
834
  }
861
835
 
836
+ /**
837
+ * Evaluate a TI expression and return the string result.
838
+ *
839
+ * Creates a temporary process with sFunc = {formula}, compiles it,
840
+ * starts a debug session, adds a data breakpoint on sFunc, continues
841
+ * execution to evaluate, reads the result, and cleans up.
842
+ */
843
+ public async evaluateTiExpression(formula: string): Promise<string> {
844
+ // tm1py uses formula[formula.find("=") + 1:] which greedily strips at the
845
+ // first "=" anywhere in the string. We use a regex to only strip a leading
846
+ // "=" prefix (e.g. "=NOW;" → "NOW;"), avoiding mangling formulas with
847
+ // embedded "=" (e.g. comparisons like "IF(1=1,...)").
848
+ formula = formula.replace(/^\s*=\s*/, '');
849
+
850
+ // Ensure semicolon at end
851
+ if (!formula.trim().endsWith(';')) {
852
+ formula += ';';
853
+ }
854
+
855
+ const prologList = [`sFunc = ${formula}`, "sDebug='Stop';"];
856
+ const processName = `}TM1py${uuidv4()}`;
857
+ const p = new Process(
858
+ processName,
859
+ false,
860
+ undefined,
861
+ undefined,
862
+ undefined,
863
+ undefined,
864
+ Process.AUTO_GENERATED_STATEMENTS + prologList.join('\r\n'),
865
+ '',
866
+ '',
867
+ ''
868
+ );
869
+
870
+ const syntaxErrors = await this.compileProcess(p);
871
+ if (syntaxErrors && syntaxErrors.length > 0) {
872
+ throw new Error(syntaxErrors.map(e => `Line ${e.LineNumber}: ${e.Message}`).join('; '));
873
+ }
874
+
875
+ try {
876
+ await this.create(p);
877
+ const debugContext = await this.debugProcess(processName);
878
+ const debugId = debugContext.ID;
879
+
880
+ const breakpoint = new ProcessDebugBreakpoint(
881
+ 1,
882
+ BreakPointType.PROCESS_DEBUG_CONTEXT_DATA_BREAK_POINT,
883
+ true,
884
+ HitMode.BREAK_ALWAYS,
885
+ 0,
886
+ '',
887
+ 'sFunc'
888
+ );
889
+
890
+ await this.debugAddBreakpoint(debugId, breakpoint);
891
+ await this.debugContinue(debugId);
892
+ const result = await this.debugGetVariableValues(debugId);
893
+ await this.debugContinue(debugId);
894
+
895
+ if (!result || !('sFunc' in result)) {
896
+ throw new Error('unknown error: no formula result found');
897
+ }
898
+ return result['sFunc'];
899
+
900
+ } finally {
901
+ try {
902
+ await this.delete(processName);
903
+ } catch (_) {
904
+ // Cleanup failure should not mask the original error
905
+ }
906
+ }
907
+ }
908
+
862
909
  /**
863
910
  * Analyze process dependencies (what cubes/dimensions/processes it uses)
864
911
  *
@@ -868,8 +915,8 @@ export class ProcessService extends ObjectService {
868
915
  * @example
869
916
  * ```typescript
870
917
  * const deps = await processService.analyzeProcessDependencies('ImportData');
871
- * console.log('Cubes used:', deps.cubes);
872
- * console.log('Dimensions used:', deps.dimensions);
918
+ * // deps.cubes => array of cube names referenced in the process
919
+ * // deps.dimensions => array of dimension names referenced in the process
873
920
  * ```
874
921
  */
875
922
  public async analyzeProcessDependencies(processName: string): Promise<any> {
@@ -937,35 +984,32 @@ export class ProcessService extends ObjectService {
937
984
  * Validate process syntax without executing it
938
985
  *
939
986
  * @param processName - Name of the process
940
- * @returns Promise<{isValid: boolean, errors: any[]}> - Validation result
987
+ * @returns Promise<ValidationResult> - Validation result
941
988
  *
942
989
  * @example
943
990
  * ```typescript
944
991
  * const result = await processService.validateProcessSyntax('MyProcess');
945
992
  * if (!result.isValid) {
946
- * console.error('Errors:', result.errors);
993
+ * // result.errors contains ValidationError[] entries
947
994
  * }
948
995
  * ```
949
996
  */
950
- public async validateProcessSyntax(processName: string): Promise<{isValid: boolean, errors: any[]}> {
997
+ public async validateProcessSyntax(processName: string): Promise<ValidationResult> {
951
998
  try {
952
- const result = await this.compileProcess(processName);
999
+ const response = await this.compile(processName);
1000
+ if (response.status === 200) {
1001
+ return { isValid: true, errors: [] };
1002
+ }
953
1003
  return {
954
- isValid: result.success,
955
- errors: result.errors.map((error, index) => ({
956
- line: index + 1,
957
- message: error,
958
- severity: 'Error'
959
- }))
1004
+ isValid: false,
1005
+ errors: [{ line: 0, message: response.statusText || 'Compilation failed', severity: 'Error' }]
960
1006
  };
961
- } catch (error: any) {
1007
+ } catch (error) {
1008
+ const err = error as { response?: { data?: { error?: { message?: string } } }; message?: string };
1009
+ const errorMessage = err.response?.data?.error?.message || err.message || 'Validation failed';
962
1010
  return {
963
1011
  isValid: false,
964
- errors: [{
965
- line: 0,
966
- message: error.message || 'Validation failed',
967
- severity: 'Error'
968
- }]
1012
+ errors: [{ line: 0, message: errorMessage, severity: 'Error' }]
969
1013
  };
970
1014
  }
971
1015
  }
@@ -979,7 +1023,7 @@ export class ProcessService extends ObjectService {
979
1023
  * @example
980
1024
  * ```typescript
981
1025
  * const plan = await processService.getProcessExecutionPlan('ImportData');
982
- * console.log('Estimated execution time:', plan.estimatedTime);
1026
+ * // plan.estimatedTime => estimated execution time (ms)
983
1027
  * ```
984
1028
  */
985
1029
  public async getProcessExecutionPlan(processName: string): Promise<any> {
@@ -1059,19 +1103,20 @@ export class ProcessService extends ObjectService {
1059
1103
 
1060
1104
  // Execute process asynchronously
1061
1105
  this.executeWithReturn(processName, parameters)
1062
- .then((result: any) => {
1106
+ .then((result: unknown) => {
1063
1107
  asyncOps.updateOperationStatus(
1064
1108
  operationId,
1065
1109
  OperationStatus.COMPLETED,
1066
1110
  result
1067
1111
  );
1068
1112
  })
1069
- .catch((error: any) => {
1113
+ .catch((error: unknown) => {
1114
+ const message = (error as { message?: string })?.message ?? String(error);
1070
1115
  asyncOps.updateOperationStatus(
1071
1116
  operationId,
1072
1117
  OperationStatus.FAILED,
1073
1118
  undefined,
1074
- error.message || String(error)
1119
+ message
1075
1120
  );
1076
1121
  });
1077
1122
 
@@ -1087,9 +1132,7 @@ export class ProcessService extends ObjectService {
1087
1132
  * @example
1088
1133
  * ```typescript
1089
1134
  * const status = await processService.pollProcessExecution(operationId);
1090
- * if (status === OperationStatus.COMPLETED) {
1091
- * console.log('Process completed!');
1092
- * }
1135
+ * // if (status === OperationStatus.COMPLETED) handle completion
1093
1136
  * ```
1094
1137
  */
1095
1138
  public async pollProcessExecution(operationId: string): Promise<OperationStatus> {
@@ -1110,7 +1153,7 @@ export class ProcessService extends ObjectService {
1110
1153
  * @example
1111
1154
  * ```typescript
1112
1155
  * await processService.cancelProcessExecution(operationId);
1113
- * console.log('Process execution cancelled');
1156
+ * // cancellation is acknowledged once the promise resolves
1114
1157
  * ```
1115
1158
  */
1116
1159
  public async cancelProcessExecution(operationId: string): Promise<void> {
@@ -1121,4 +1164,4 @@ export class ProcessService extends ObjectService {
1121
1164
 
1122
1165
  await asyncOps.cancelAsyncOperation(operationId);
1123
1166
  }
1124
- }
1167
+ }