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.
- package/CHANGELOG.md +89 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/services/ApplicationService.d.ts +19 -3
- package/lib/services/ApplicationService.d.ts.map +1 -1
- package/lib/services/ApplicationService.js +232 -6
- package/lib/services/AsyncOperationService.d.ts +8 -1
- package/lib/services/AsyncOperationService.d.ts.map +1 -1
- package/lib/services/AsyncOperationService.js +69 -26
- package/lib/services/ElementService.d.ts +67 -1
- package/lib/services/ElementService.d.ts.map +1 -1
- package/lib/services/ElementService.js +214 -0
- package/lib/services/FileService.d.ts.map +1 -1
- package/lib/services/HierarchyService.d.ts +26 -0
- package/lib/services/HierarchyService.d.ts.map +1 -1
- package/lib/services/HierarchyService.js +306 -0
- package/lib/services/ProcessService.d.ts +40 -22
- package/lib/services/ProcessService.d.ts.map +1 -1
- package/lib/services/ProcessService.js +118 -111
- package/lib/services/RestService.d.ts +213 -25
- package/lib/services/RestService.d.ts.map +1 -1
- package/lib/services/RestService.js +841 -263
- package/lib/services/SubsetService.d.ts +2 -0
- package/lib/services/SubsetService.d.ts.map +1 -1
- package/lib/services/SubsetService.js +33 -0
- package/lib/services/TM1Service.d.ts +44 -1
- package/lib/services/TM1Service.d.ts.map +1 -1
- package/lib/services/TM1Service.js +96 -4
- package/lib/services/index.d.ts +1 -1
- package/lib/services/index.d.ts.map +1 -1
- package/lib/tests/100PercentParityCheck.test.js +23 -6
- package/lib/tests/applicationService.issue38.test.d.ts +5 -0
- package/lib/tests/applicationService.issue38.test.d.ts.map +1 -0
- package/lib/tests/applicationService.issue38.test.js +237 -0
- package/lib/tests/asyncOperationService.test.js +51 -45
- package/lib/tests/bugfix28.test.js +12 -4
- package/lib/tests/elementService.issue37.test.d.ts +5 -0
- package/lib/tests/elementService.issue37.test.d.ts.map +1 -0
- package/lib/tests/elementService.issue37.test.js +413 -0
- package/lib/tests/elementService.issue38.test.d.ts +5 -0
- package/lib/tests/elementService.issue38.test.d.ts.map +1 -0
- package/lib/tests/elementService.issue38.test.js +79 -0
- package/lib/tests/hierarchyService.issue38.test.d.ts +5 -0
- package/lib/tests/hierarchyService.issue38.test.d.ts.map +1 -0
- package/lib/tests/hierarchyService.issue38.test.js +460 -0
- package/lib/tests/processService.comprehensive.test.js +9 -9
- package/lib/tests/processService.test.js +234 -0
- package/lib/tests/restService.test.d.ts +0 -4
- package/lib/tests/restService.test.d.ts.map +1 -1
- package/lib/tests/restService.test.js +1558 -143
- package/lib/tests/subsetService.issue38.test.d.ts +5 -0
- package/lib/tests/subsetService.issue38.test.d.ts.map +1 -0
- package/lib/tests/subsetService.issue38.test.js +113 -0
- package/lib/tests/tm1Service.test.js +80 -8
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/services/ApplicationService.ts +282 -10
- package/src/services/AsyncOperationService.ts +76 -29
- package/src/services/ElementService.ts +322 -1
- package/src/services/FileService.ts +3 -3
- package/src/services/HierarchyService.ts +419 -1
- package/src/services/ProcessService.ts +185 -142
- package/src/services/RestService.ts +1021 -267
- package/src/services/SubsetService.ts +48 -0
- package/src/services/TM1Service.ts +127 -6
- package/src/services/index.ts +1 -1
- package/src/tests/100PercentParityCheck.test.ts +29 -8
- package/src/tests/applicationService.issue38.test.ts +293 -0
- package/src/tests/asyncOperationService.test.ts +52 -48
- package/src/tests/bugfix28.test.ts +12 -4
- package/src/tests/elementService.issue37.test.ts +571 -0
- package/src/tests/elementService.issue38.test.ts +103 -0
- package/src/tests/hierarchyService.issue38.test.ts +599 -0
- package/src/tests/processService.comprehensive.test.ts +10 -10
- package/src/tests/processService.test.ts +295 -3
- package/src/tests/restService.test.ts +1844 -139
- package/src/tests/subsetService.issue38.test.ts +182 -0
- package/src/tests/tm1Service.test.ts +95 -11
|
@@ -2,6 +2,7 @@ import { AxiosResponse } from 'axios';
|
|
|
2
2
|
import { RestService } from './RestService';
|
|
3
3
|
import { ObjectService } from './ObjectService';
|
|
4
4
|
import { Subset } from '../objects/Subset';
|
|
5
|
+
import { Element } from '../objects/Element';
|
|
5
6
|
export declare class SubsetService extends ObjectService {
|
|
6
7
|
private elementService?;
|
|
7
8
|
constructor(rest: RestService);
|
|
@@ -17,6 +18,7 @@ export declare class SubsetService extends ObjectService {
|
|
|
17
18
|
updateOrCreate(subset: Subset, isPrivate?: boolean): Promise<AxiosResponse>;
|
|
18
19
|
deleteElementsFromStaticSubset(dimensionName: string, hierarchyName: string, subsetName: string, isPrivate?: boolean): Promise<AxiosResponse>;
|
|
19
20
|
getElementNames(dimensionName: string, hierarchyName: string, subsetName: string, isPrivate?: boolean): Promise<string[]>;
|
|
21
|
+
updateStaticElements(subsetOrName: Subset | string, dimensionName?: string, hierarchyName?: string, isPrivate?: boolean, elements?: Array<string | Element>): Promise<AxiosResponse>;
|
|
20
22
|
private updateSubsetInstance;
|
|
21
23
|
private getSubsetCollection;
|
|
22
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubsetService.d.ts","sourceRoot":"","sources":["../../src/services/SubsetService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"SubsetService.d.ts","sourceRoot":"","sources":["../../src/services/SubsetService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAK7C,qBAAa,aAAc,SAAQ,aAAa;IAC5C,OAAO,CAAC,cAAc,CAAC,CAAiB;gBAE5B,IAAI,EAAE,WAAW;IAIhB,MAAM,CACf,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,aAAa,CAAC;IAEZ,MAAM,CACf,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,GAAG,EACX,SAAS,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,aAAa,CAAC;IAmCZ,GAAG,CACZ,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,GAAG,CAAC;IAaF,MAAM,CACf,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,aAAa,CAAC;IAEZ,MAAM,CACf,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,GAAG,EACX,SAAS,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,aAAa,CAAC;IA6BZ,MAAM,CACf,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,aAAa,CAAC;IAYZ,MAAM,CACf,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,OAAO,CAAC;IAqBN,WAAW,CACpB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC;IAYP,UAAU,CACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,aAAa,CAAC,EAAE,MAAM,EACtB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,aAAa,CAAC;IAkBZ,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,OAAe,GAAG,OAAO,CAAC,aAAa,CAAC;IAOlF,8BAA8B,CACvC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,aAAa,CAAC;IAYZ,eAAe,CACxB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAe,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC;IAgCP,oBAAoB,CAC7B,YAAY,EAAE,MAAM,GAAG,MAAM,EAC7B,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,EACtB,SAAS,GAAE,OAAe,EAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,GACnC,OAAO,CAAC,aAAa,CAAC;YAwCX,oBAAoB;IAqBlC,OAAO,CAAC,mBAAmB;CAG9B"}
|
|
@@ -5,6 +5,7 @@ const ObjectService_1 = require("./ObjectService");
|
|
|
5
5
|
const Subset_1 = require("../objects/Subset");
|
|
6
6
|
const ElementService_1 = require("./ElementService");
|
|
7
7
|
const TM1Exception_1 = require("../exceptions/TM1Exception");
|
|
8
|
+
const Utils_1 = require("../utils/Utils");
|
|
8
9
|
class SubsetService extends ObjectService_1.ObjectService {
|
|
9
10
|
constructor(rest) {
|
|
10
11
|
super(rest);
|
|
@@ -111,6 +112,38 @@ class SubsetService extends ObjectService_1.ObjectService {
|
|
|
111
112
|
}
|
|
112
113
|
return await this.elementService.executeSetMdxElementNames(subset.expression);
|
|
113
114
|
}
|
|
115
|
+
async updateStaticElements(subsetOrName, dimensionName, hierarchyName, isPrivate = false, elements) {
|
|
116
|
+
let subsetName;
|
|
117
|
+
let dimName;
|
|
118
|
+
let hierName;
|
|
119
|
+
let elementNames;
|
|
120
|
+
if (subsetOrName instanceof Subset_1.Subset) {
|
|
121
|
+
const subset = subsetOrName;
|
|
122
|
+
subsetName = subset.name;
|
|
123
|
+
dimName = dimensionName || subset.dimensionName;
|
|
124
|
+
hierName = hierarchyName || subset.hierarchyName;
|
|
125
|
+
elementNames = elements
|
|
126
|
+
? elements.map(e => typeof e === 'string' ? e : e.name)
|
|
127
|
+
: subset.elements;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
if (!dimensionName) {
|
|
131
|
+
throw new Error('dimensionName is required when passing subset name as string');
|
|
132
|
+
}
|
|
133
|
+
subsetName = subsetOrName;
|
|
134
|
+
dimName = dimensionName;
|
|
135
|
+
hierName = hierarchyName || dimName;
|
|
136
|
+
elementNames = (elements || []).map(e => typeof e === 'string' ? e : e.name);
|
|
137
|
+
}
|
|
138
|
+
const subsetsCollection = this.getSubsetCollection(isPrivate);
|
|
139
|
+
const url = this.formatUrl("/Dimensions('{}')/Hierarchies('{}')/{}('{}')/Elements/$ref", dimName, hierName, subsetsCollection, subsetName);
|
|
140
|
+
const body = {
|
|
141
|
+
value: elementNames.map(elementName => ({
|
|
142
|
+
'@odata.id': (0, Utils_1.formatUrl)("Dimensions('{}')/Hierarchies('{}')/Elements('{}')", dimName, hierName, elementName)
|
|
143
|
+
}))
|
|
144
|
+
};
|
|
145
|
+
return await this.rest.put(url, JSON.stringify(body));
|
|
146
|
+
}
|
|
114
147
|
async updateSubsetInstance(subset, isPrivate) {
|
|
115
148
|
if (subset.isStatic) {
|
|
116
149
|
await this.deleteElementsFromStaticSubset(subset.dimensionName, subset.hierarchyName, subset.name, isPrivate);
|
|
@@ -7,11 +7,37 @@ import { DebuggerService } from './DebuggerService';
|
|
|
7
7
|
import { BulkService } from './BulkService';
|
|
8
8
|
import { AsyncOperationService } from './AsyncOperationService';
|
|
9
9
|
import { PowerBiService } from './PowerBiService';
|
|
10
|
+
import { ApplicationService } from './ApplicationService';
|
|
11
|
+
import { AnnotationService } from './AnnotationService';
|
|
12
|
+
import { ChoreService } from './ChoreService';
|
|
13
|
+
import { GitService } from './GitService';
|
|
14
|
+
import { SandboxService } from './SandboxService';
|
|
15
|
+
import { JobService } from './JobService';
|
|
16
|
+
import { UserService } from './UserService';
|
|
17
|
+
import { ThreadService } from './ThreadService';
|
|
18
|
+
import { TransactionLogService } from './TransactionLogService';
|
|
19
|
+
import { MessageLogService } from './MessageLogService';
|
|
20
|
+
import { ConfigurationService } from './ConfigurationService';
|
|
21
|
+
import { AuditLogService } from './AuditLogService';
|
|
22
|
+
import { LoggerService } from './LoggerService';
|
|
23
|
+
import { User } from '../objects/User';
|
|
10
24
|
import { CubeService, ElementService, CellService, ProcessService, ViewService, SecurityService, FileService, SessionService, ServerService, MonitoringService } from './index';
|
|
11
25
|
export declare class TM1Service {
|
|
12
26
|
private _tm1Rest;
|
|
13
27
|
private _server?;
|
|
14
28
|
private _monitoring?;
|
|
29
|
+
private _annotations?;
|
|
30
|
+
private _chores?;
|
|
31
|
+
private _git?;
|
|
32
|
+
private _sandboxes?;
|
|
33
|
+
private _jobs?;
|
|
34
|
+
private _users?;
|
|
35
|
+
private _threads?;
|
|
36
|
+
private _transactionLogs?;
|
|
37
|
+
private _messageLogs?;
|
|
38
|
+
private _configuration?;
|
|
39
|
+
private _auditLogs?;
|
|
40
|
+
private _loggers?;
|
|
15
41
|
dimensions: DimensionService;
|
|
16
42
|
hierarchies: HierarchyService;
|
|
17
43
|
subsets: SubsetService;
|
|
@@ -28,20 +54,37 @@ export declare class TM1Service {
|
|
|
28
54
|
bulk: BulkService;
|
|
29
55
|
asyncOperations: AsyncOperationService;
|
|
30
56
|
powerbi: PowerBiService;
|
|
57
|
+
applications: ApplicationService;
|
|
31
58
|
constructor(config: RestServiceConfig);
|
|
32
59
|
connect(): Promise<void>;
|
|
33
60
|
logout(): Promise<void>;
|
|
34
61
|
disconnect(): Promise<void>;
|
|
35
62
|
get server(): ServerService;
|
|
36
63
|
get monitoring(): MonitoringService;
|
|
37
|
-
|
|
64
|
+
get annotations(): AnnotationService;
|
|
65
|
+
get chores(): ChoreService;
|
|
66
|
+
get git(): GitService;
|
|
67
|
+
get sandboxes(): SandboxService;
|
|
68
|
+
get jobs(): JobService;
|
|
69
|
+
get users(): UserService;
|
|
70
|
+
get threads(): ThreadService;
|
|
71
|
+
get transactionLogs(): TransactionLogService;
|
|
72
|
+
get messageLogs(): MessageLogService;
|
|
73
|
+
get configuration(): ConfigurationService;
|
|
74
|
+
get auditLogs(): AuditLogService;
|
|
75
|
+
get loggers(): LoggerService;
|
|
76
|
+
whoami(): Promise<User>;
|
|
38
77
|
getMetadata(): Promise<any>;
|
|
78
|
+
get version(): string | undefined;
|
|
39
79
|
getVersion(): Promise<string>;
|
|
40
80
|
get connection(): RestService;
|
|
41
81
|
getSessionId(): string | undefined;
|
|
42
82
|
setSandbox(sandboxName?: string): void;
|
|
43
83
|
getSandbox(): string | undefined;
|
|
44
84
|
isLoggedIn(): boolean;
|
|
85
|
+
/** Reconnects without teardown. Use reAuthenticate() for full disconnect+reconnect. */
|
|
86
|
+
reConnect(): Promise<void>;
|
|
87
|
+
/** Full teardown + reconnect. If disconnect() throws, connect() is not attempted. */
|
|
45
88
|
reAuthenticate(): Promise<void>;
|
|
46
89
|
static create(config: RestServiceConfig): Promise<TM1Service>;
|
|
47
90
|
dispose(): 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,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,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;
|
|
1
|
+
{"version":3,"file":"TM1Service.d.ts","sourceRoot":"","sources":["../../src/services/TM1Service.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,19 @@ const DebuggerService_1 = require("./DebuggerService");
|
|
|
10
10
|
const BulkService_1 = require("./BulkService");
|
|
11
11
|
const AsyncOperationService_1 = require("./AsyncOperationService");
|
|
12
12
|
const PowerBiService_1 = require("./PowerBiService");
|
|
13
|
+
const ApplicationService_1 = require("./ApplicationService");
|
|
14
|
+
const AnnotationService_1 = require("./AnnotationService");
|
|
15
|
+
const ChoreService_1 = require("./ChoreService");
|
|
16
|
+
const GitService_1 = require("./GitService");
|
|
17
|
+
const SandboxService_1 = require("./SandboxService");
|
|
18
|
+
const JobService_1 = require("./JobService");
|
|
19
|
+
const UserService_1 = require("./UserService");
|
|
20
|
+
const ThreadService_1 = require("./ThreadService");
|
|
21
|
+
const TransactionLogService_1 = require("./TransactionLogService");
|
|
22
|
+
const MessageLogService_1 = require("./MessageLogService");
|
|
23
|
+
const ConfigurationService_1 = require("./ConfigurationService");
|
|
24
|
+
const AuditLogService_1 = require("./AuditLogService");
|
|
25
|
+
const LoggerService_1 = require("./LoggerService");
|
|
13
26
|
const index_1 = require("./index");
|
|
14
27
|
class TM1Service {
|
|
15
28
|
constructor(config) {
|
|
@@ -34,6 +47,7 @@ class TM1Service {
|
|
|
34
47
|
this.debugger = new DebuggerService_1.DebuggerService(this._tm1Rest);
|
|
35
48
|
this.bulk = new BulkService_1.BulkService(this._tm1Rest, this.cells, this.views);
|
|
36
49
|
this.powerbi = new PowerBiService_1.PowerBiService(this._tm1Rest);
|
|
50
|
+
this.applications = new ApplicationService_1.ApplicationService(this._tm1Rest);
|
|
37
51
|
}
|
|
38
52
|
async connect() {
|
|
39
53
|
await this._tm1Rest.connect();
|
|
@@ -56,17 +70,90 @@ class TM1Service {
|
|
|
56
70
|
}
|
|
57
71
|
return this._monitoring;
|
|
58
72
|
}
|
|
73
|
+
get annotations() {
|
|
74
|
+
if (!this._annotations) {
|
|
75
|
+
this._annotations = new AnnotationService_1.AnnotationService(this._tm1Rest);
|
|
76
|
+
}
|
|
77
|
+
return this._annotations;
|
|
78
|
+
}
|
|
79
|
+
get chores() {
|
|
80
|
+
if (!this._chores) {
|
|
81
|
+
this._chores = new ChoreService_1.ChoreService(this._tm1Rest);
|
|
82
|
+
}
|
|
83
|
+
return this._chores;
|
|
84
|
+
}
|
|
85
|
+
get git() {
|
|
86
|
+
if (!this._git) {
|
|
87
|
+
this._git = new GitService_1.GitService(this._tm1Rest);
|
|
88
|
+
}
|
|
89
|
+
return this._git;
|
|
90
|
+
}
|
|
91
|
+
get sandboxes() {
|
|
92
|
+
if (!this._sandboxes) {
|
|
93
|
+
this._sandboxes = new SandboxService_1.SandboxService(this._tm1Rest);
|
|
94
|
+
}
|
|
95
|
+
return this._sandboxes;
|
|
96
|
+
}
|
|
97
|
+
get jobs() {
|
|
98
|
+
if (!this._jobs) {
|
|
99
|
+
this._jobs = new JobService_1.JobService(this._tm1Rest);
|
|
100
|
+
}
|
|
101
|
+
return this._jobs;
|
|
102
|
+
}
|
|
103
|
+
get users() {
|
|
104
|
+
if (!this._users) {
|
|
105
|
+
this._users = new UserService_1.UserService(this._tm1Rest);
|
|
106
|
+
}
|
|
107
|
+
return this._users;
|
|
108
|
+
}
|
|
109
|
+
get threads() {
|
|
110
|
+
if (!this._threads) {
|
|
111
|
+
this._threads = new ThreadService_1.ThreadService(this._tm1Rest);
|
|
112
|
+
}
|
|
113
|
+
return this._threads;
|
|
114
|
+
}
|
|
115
|
+
get transactionLogs() {
|
|
116
|
+
if (!this._transactionLogs) {
|
|
117
|
+
this._transactionLogs = new TransactionLogService_1.TransactionLogService(this._tm1Rest);
|
|
118
|
+
}
|
|
119
|
+
return this._transactionLogs;
|
|
120
|
+
}
|
|
121
|
+
get messageLogs() {
|
|
122
|
+
if (!this._messageLogs) {
|
|
123
|
+
this._messageLogs = new MessageLogService_1.MessageLogService(this._tm1Rest);
|
|
124
|
+
}
|
|
125
|
+
return this._messageLogs;
|
|
126
|
+
}
|
|
127
|
+
get configuration() {
|
|
128
|
+
if (!this._configuration) {
|
|
129
|
+
this._configuration = new ConfigurationService_1.ConfigurationService(this._tm1Rest);
|
|
130
|
+
}
|
|
131
|
+
return this._configuration;
|
|
132
|
+
}
|
|
133
|
+
get auditLogs() {
|
|
134
|
+
if (!this._auditLogs) {
|
|
135
|
+
this._auditLogs = new AuditLogService_1.AuditLogService(this._tm1Rest);
|
|
136
|
+
}
|
|
137
|
+
return this._auditLogs;
|
|
138
|
+
}
|
|
139
|
+
get loggers() {
|
|
140
|
+
if (!this._loggers) {
|
|
141
|
+
this._loggers = new LoggerService_1.LoggerService(this._tm1Rest);
|
|
142
|
+
}
|
|
143
|
+
return this._loggers;
|
|
144
|
+
}
|
|
59
145
|
async whoami() {
|
|
60
|
-
|
|
61
|
-
return user.name;
|
|
146
|
+
return await this.security.getCurrentUser();
|
|
62
147
|
}
|
|
63
148
|
async getMetadata() {
|
|
64
149
|
const response = await this._tm1Rest.get('/$metadata');
|
|
65
150
|
return response.data;
|
|
66
151
|
}
|
|
152
|
+
get version() {
|
|
153
|
+
return this._tm1Rest.version;
|
|
154
|
+
}
|
|
67
155
|
async getVersion() {
|
|
68
|
-
|
|
69
|
-
return response.data.value;
|
|
156
|
+
return await this._tm1Rest.getVersion();
|
|
70
157
|
}
|
|
71
158
|
get connection() {
|
|
72
159
|
return this._tm1Rest;
|
|
@@ -83,6 +170,11 @@ class TM1Service {
|
|
|
83
170
|
isLoggedIn() {
|
|
84
171
|
return this._tm1Rest.isLoggedIn();
|
|
85
172
|
}
|
|
173
|
+
/** Reconnects without teardown. Use reAuthenticate() for full disconnect+reconnect. */
|
|
174
|
+
async reConnect() {
|
|
175
|
+
await this._tm1Rest.connect();
|
|
176
|
+
}
|
|
177
|
+
/** Full teardown + reconnect. If disconnect() throws, connect() is not attempted. */
|
|
86
178
|
async reAuthenticate() {
|
|
87
179
|
await this._tm1Rest.disconnect();
|
|
88
180
|
await this._tm1Rest.connect();
|
package/lib/services/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { CubeService } from './CubeService';
|
|
2
2
|
export { ElementService } from './ElementService';
|
|
3
3
|
export { CellService } from './CellService';
|
|
4
|
-
export { ProcessService } from './ProcessService';
|
|
4
|
+
export { ProcessService, CompileSyntaxError } from './ProcessService';
|
|
5
5
|
export { ViewService } from './ViewService';
|
|
6
6
|
export { SecurityService } from './SecurityService';
|
|
7
7
|
export { FileService } from './FileService';
|
|
@@ -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;
|
|
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,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtE,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;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,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"}
|
|
@@ -54,14 +54,25 @@ describe('100% TM1py Parity Function Existence', () => {
|
|
|
54
54
|
console.log('✅ All 16 ElementService functions exist');
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
|
-
describe('ProcessService - Debug Operations (
|
|
58
|
-
test('All
|
|
57
|
+
describe('ProcessService - Debug Operations & Parity (11 functions)', () => {
|
|
58
|
+
test('All ProcessService debug and parity functions should exist', () => {
|
|
59
|
+
// Debug step/continue (from #33)
|
|
59
60
|
expect(typeof processService.debugStepOver).toBe('function');
|
|
60
61
|
expect(typeof processService.debugStepIn).toBe('function');
|
|
61
62
|
expect(typeof processService.debugStepOut).toBe('function');
|
|
62
63
|
expect(typeof processService.debugContinue).toBe('function');
|
|
63
64
|
expect(typeof processService.evaluateBooleanTiExpression).toBe('function');
|
|
64
|
-
|
|
65
|
+
// Debug breakpoint methods — renamed for tm1py parity (#36)
|
|
66
|
+
expect(typeof processService.debugGetBreakpoints).toBe('function');
|
|
67
|
+
expect(typeof processService.debugAddBreakpoint).toBe('function');
|
|
68
|
+
expect(typeof processService.debugRemoveBreakpoint).toBe('function');
|
|
69
|
+
// Async polling — rewritten for tm1py parity (#36)
|
|
70
|
+
expect(typeof processService.pollExecuteWithReturn).toBe('function');
|
|
71
|
+
// Unbound process compile (#36)
|
|
72
|
+
expect(typeof processService.compileProcess).toBe('function');
|
|
73
|
+
// TI expression evaluation (#36)
|
|
74
|
+
expect(typeof processService.evaluateTiExpression).toBe('function');
|
|
75
|
+
console.log('✅ All 11 ProcessService functions exist');
|
|
65
76
|
});
|
|
66
77
|
});
|
|
67
78
|
describe('CellService - Async Operations (3 functions)', () => {
|
|
@@ -79,7 +90,7 @@ describe('100% TM1py Parity Function Existence', () => {
|
|
|
79
90
|
});
|
|
80
91
|
});
|
|
81
92
|
describe('100% Parity Achievement Summary', () => {
|
|
82
|
-
test('should confirm all
|
|
93
|
+
test('should confirm all 28 functions are implemented', () => {
|
|
83
94
|
const implementedFunctions = {
|
|
84
95
|
ElementService: [
|
|
85
96
|
'deleteElementsUseTi',
|
|
@@ -104,7 +115,13 @@ describe('100% TM1py Parity Function Existence', () => {
|
|
|
104
115
|
'debugStepIn',
|
|
105
116
|
'debugStepOut',
|
|
106
117
|
'debugContinue',
|
|
107
|
-
'evaluateBooleanTiExpression'
|
|
118
|
+
'evaluateBooleanTiExpression',
|
|
119
|
+
'debugGetBreakpoints',
|
|
120
|
+
'debugAddBreakpoint',
|
|
121
|
+
'debugRemoveBreakpoint',
|
|
122
|
+
'pollExecuteWithReturn',
|
|
123
|
+
'compileProcess',
|
|
124
|
+
'evaluateTiExpression'
|
|
108
125
|
],
|
|
109
126
|
CellService: [
|
|
110
127
|
'writeDataframeAsync',
|
|
@@ -130,7 +147,7 @@ describe('100% TM1py Parity Function Existence', () => {
|
|
|
130
147
|
});
|
|
131
148
|
const totalFunctions = Object.values(implementedFunctions)
|
|
132
149
|
.reduce((total, funcs) => total + funcs.length, 0);
|
|
133
|
-
expect(totalFunctions).toBe(
|
|
150
|
+
expect(totalFunctions).toBe(31); // 16 + 11 + 3 + 1
|
|
134
151
|
console.log('🎉 100% TM1py Parity Achieved!');
|
|
135
152
|
console.log(`✅ ${implementedFunctions.ElementService.length} ElementService functions`);
|
|
136
153
|
console.log(`✅ ${implementedFunctions.ProcessService.length} ProcessService functions`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applicationService.issue38.test.d.ts","sourceRoot":"","sources":["../../src/tests/applicationService.issue38.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ApplicationService Tests — Issue #38 new methods
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ApplicationService_1 = require("../services/ApplicationService");
|
|
7
|
+
const TM1Exception_1 = require("../exceptions/TM1Exception");
|
|
8
|
+
const Application_1 = require("../objects/Application");
|
|
9
|
+
const createMockResponse = (data, status = 200) => ({
|
|
10
|
+
data,
|
|
11
|
+
status,
|
|
12
|
+
statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
|
|
13
|
+
headers: {},
|
|
14
|
+
config: {}
|
|
15
|
+
});
|
|
16
|
+
describe('ApplicationService — Issue #38 new methods', () => {
|
|
17
|
+
let applicationService;
|
|
18
|
+
let mockRestService;
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
mockRestService = {
|
|
21
|
+
get: jest.fn(),
|
|
22
|
+
post: jest.fn(),
|
|
23
|
+
patch: jest.fn(),
|
|
24
|
+
delete: jest.fn(),
|
|
25
|
+
put: jest.fn(),
|
|
26
|
+
config: {},
|
|
27
|
+
rest: {},
|
|
28
|
+
buildBaseUrl: jest.fn(),
|
|
29
|
+
extractErrorMessage: jest.fn()
|
|
30
|
+
};
|
|
31
|
+
applicationService = new ApplicationService_1.ApplicationService(mockRestService);
|
|
32
|
+
});
|
|
33
|
+
// ===== discover =====
|
|
34
|
+
describe('discover', () => {
|
|
35
|
+
test('should return public items at root when includePrivate=false', async () => {
|
|
36
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
37
|
+
if (url.includes('Contents') && !url.includes('PrivateContents')) {
|
|
38
|
+
return createMockResponse({
|
|
39
|
+
value: [
|
|
40
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'SalesCube' },
|
|
41
|
+
{ '@odata.type': '#ibm.tm1.api.v1.FolderApplication', Name: 'Reports' }
|
|
42
|
+
]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return createMockResponse({ value: [] });
|
|
46
|
+
});
|
|
47
|
+
const results = await applicationService.discover('', false, false);
|
|
48
|
+
expect(results.length).toBeGreaterThanOrEqual(2);
|
|
49
|
+
const names = results.map(r => r.name);
|
|
50
|
+
expect(names).toContain('SalesCube');
|
|
51
|
+
expect(names).toContain('Reports');
|
|
52
|
+
// All should be public
|
|
53
|
+
results.forEach(r => expect(r.is_private).toBe(false));
|
|
54
|
+
});
|
|
55
|
+
test('should include private items when includePrivate=true', async () => {
|
|
56
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
57
|
+
if (url.includes('PrivateContents')) {
|
|
58
|
+
return createMockResponse({
|
|
59
|
+
value: [
|
|
60
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'PrivateReport' }
|
|
61
|
+
]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return createMockResponse({
|
|
65
|
+
value: [
|
|
66
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'PublicCube' }
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
const results = await applicationService.discover('', true, false);
|
|
71
|
+
const privateItems = results.filter(r => r.is_private);
|
|
72
|
+
const publicItems = results.filter(r => !r.is_private);
|
|
73
|
+
expect(privateItems.length).toBeGreaterThanOrEqual(1);
|
|
74
|
+
expect(publicItems.length).toBeGreaterThanOrEqual(1);
|
|
75
|
+
const privateNames = privateItems.map(r => r.name);
|
|
76
|
+
expect(privateNames).toContain('PrivateReport');
|
|
77
|
+
});
|
|
78
|
+
test('should find private items inside public folders with includePrivate', async () => {
|
|
79
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
80
|
+
// Public root contents: one public folder
|
|
81
|
+
if (url === "/Contents('Applications')/Contents") {
|
|
82
|
+
return createMockResponse({
|
|
83
|
+
value: [
|
|
84
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'PublicCube' }
|
|
85
|
+
]
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Private root contents: uses public path + PrivateContents leaf
|
|
89
|
+
if (url === "/Contents('Applications')/PrivateContents") {
|
|
90
|
+
return createMockResponse({
|
|
91
|
+
value: [
|
|
92
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'PrivateInPublicRoot' }
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return createMockResponse({ value: [] });
|
|
97
|
+
});
|
|
98
|
+
const results = await applicationService.discover('', true, false);
|
|
99
|
+
const names = results.map(r => r.name);
|
|
100
|
+
expect(names).toContain('PublicCube');
|
|
101
|
+
expect(names).toContain('PrivateInPublicRoot');
|
|
102
|
+
const privateItem = results.find(r => r.name === 'PrivateInPublicRoot');
|
|
103
|
+
expect(privateItem === null || privateItem === void 0 ? void 0 : privateItem.is_private).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
test('should recurse into folders when recursive=true', async () => {
|
|
106
|
+
// TM1 returns @odata.type like '#ibm.tm1.api.v1.FolderApplication'.
|
|
107
|
+
// _extractTypeFromOdata strips 'Application' suffix → 'Folder', which triggers recursion.
|
|
108
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
109
|
+
if (url.includes('PrivateContents')) {
|
|
110
|
+
return createMockResponse({ value: [] });
|
|
111
|
+
}
|
|
112
|
+
// Root Contents call
|
|
113
|
+
if (url.match(/Contents\('Applications'\)\/Contents$/)) {
|
|
114
|
+
return createMockResponse({
|
|
115
|
+
value: [
|
|
116
|
+
{ '@odata.type': '#ibm.tm1.api.v1.FolderApplication', Name: 'Reports' }
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// Sub-folder Contents call
|
|
121
|
+
if (url.includes("Contents('Reports')/Contents")) {
|
|
122
|
+
return createMockResponse({
|
|
123
|
+
value: [
|
|
124
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'SalesReport' }
|
|
125
|
+
]
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return createMockResponse({ value: [] });
|
|
129
|
+
});
|
|
130
|
+
const results = await applicationService.discover('', false, true);
|
|
131
|
+
const names = results.map(r => r.name);
|
|
132
|
+
expect(names).toContain('Reports');
|
|
133
|
+
expect(names).toContain('SalesReport');
|
|
134
|
+
});
|
|
135
|
+
test('should use PrivateContents for nested paths in private context', async () => {
|
|
136
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
137
|
+
// Root private contents returns a folder
|
|
138
|
+
if (url === "/Contents('Applications')/PrivateContents") {
|
|
139
|
+
return createMockResponse({
|
|
140
|
+
value: [
|
|
141
|
+
{ '@odata.type': '#ibm.tm1.api.v1.FolderApplication', Name: 'PrivateFolder' }
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// Nested private folder contents — must use PrivateContents, not Contents
|
|
146
|
+
if (url.includes("PrivateContents('PrivateFolder')/PrivateContents")) {
|
|
147
|
+
return createMockResponse({
|
|
148
|
+
value: [
|
|
149
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'DeepCube' }
|
|
150
|
+
]
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// If the code incorrectly uses Contents for nested private paths, this will 404
|
|
154
|
+
if (url.includes("Contents('PrivateFolder')/Contents")) {
|
|
155
|
+
throw new TM1Exception_1.TM1RestException('Not found', 404, { status: 404 });
|
|
156
|
+
}
|
|
157
|
+
return createMockResponse({ value: [] });
|
|
158
|
+
});
|
|
159
|
+
const results = await applicationService.discover('', true, true);
|
|
160
|
+
const names = results.map(r => r.name);
|
|
161
|
+
expect(names).toContain('PrivateFolder');
|
|
162
|
+
expect(names).toContain('DeepCube');
|
|
163
|
+
});
|
|
164
|
+
test('should return empty array on 404', async () => {
|
|
165
|
+
mockRestService.get.mockRejectedValue(new TM1Exception_1.TM1RestException('Not found', 404, { status: 404 }));
|
|
166
|
+
const results = await applicationService.discover('NonExistentPath', false, false);
|
|
167
|
+
expect(results).toEqual([]);
|
|
168
|
+
});
|
|
169
|
+
test('should include type in result items', async () => {
|
|
170
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
171
|
+
if (url.includes('PrivateContents')) {
|
|
172
|
+
return createMockResponse({ value: [] });
|
|
173
|
+
}
|
|
174
|
+
return createMockResponse({
|
|
175
|
+
value: [
|
|
176
|
+
{ '@odata.type': '#ibm.tm1.api.v1.CubeApplication', Name: 'MyCube' }
|
|
177
|
+
]
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
const results = await applicationService.discover('', false, false);
|
|
181
|
+
const cubeItem = results.find(r => r.name === 'MyCube');
|
|
182
|
+
expect(cubeItem).toBeDefined();
|
|
183
|
+
expect(cubeItem === null || cubeItem === void 0 ? void 0 : cubeItem.type).toBe('Cube');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
// ===== getNames with private path resolution (_resolvePath) =====
|
|
187
|
+
describe('getNames — private path', () => {
|
|
188
|
+
test('should use PrivateContents leaf collection even when parent path is public', async () => {
|
|
189
|
+
const calledUrls = [];
|
|
190
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
191
|
+
calledUrls.push(url);
|
|
192
|
+
if (url.includes('?$top=0')) {
|
|
193
|
+
// Public path probe succeeds — folder is public
|
|
194
|
+
return createMockResponse({});
|
|
195
|
+
}
|
|
196
|
+
if (url.includes('/PrivateContents')) {
|
|
197
|
+
return createMockResponse({
|
|
198
|
+
value: [{ Name: 'PrivateApp' }]
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return createMockResponse({
|
|
202
|
+
value: [{ Name: 'PublicApp' }]
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
const names = await applicationService.getNames('MyFolder', true);
|
|
206
|
+
expect(names).toContain('PrivateApp');
|
|
207
|
+
// The final data-fetch URL must use PrivateContents for the leaf
|
|
208
|
+
const dataUrl = calledUrls.find(u => !u.includes('$top=0') && u.includes('PrivateContents'));
|
|
209
|
+
expect(dataUrl).toBeDefined();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
// ===== exists with private path =====
|
|
213
|
+
describe('exists — private path', () => {
|
|
214
|
+
test('should use _resolvePath for private paths', async () => {
|
|
215
|
+
// Simulate all-public probe succeeds
|
|
216
|
+
mockRestService.get.mockImplementation(async (url) => {
|
|
217
|
+
if (url.includes('?$top=0')) {
|
|
218
|
+
return createMockResponse({});
|
|
219
|
+
}
|
|
220
|
+
// exists check — return 200
|
|
221
|
+
return createMockResponse({ Name: 'MyCubeApp' });
|
|
222
|
+
});
|
|
223
|
+
const result = await applicationService.exists('MyFolder', Application_1.ApplicationTypes.CUBE, 'MyCubeApp', true);
|
|
224
|
+
expect(typeof result).toBe('boolean');
|
|
225
|
+
});
|
|
226
|
+
test('should return false when private path resolution fails with not-found', async () => {
|
|
227
|
+
mockRestService.get.mockRejectedValue(new TM1Exception_1.TM1RestException('Not found', 404, { status: 404 }));
|
|
228
|
+
const result = await applicationService.exists('NonExistent', Application_1.ApplicationTypes.CUBE, 'SomeCube', true);
|
|
229
|
+
expect(result).toBe(false);
|
|
230
|
+
});
|
|
231
|
+
test('should rethrow server errors from private exists', async () => {
|
|
232
|
+
mockRestService.get.mockRejectedValue(new TM1Exception_1.TM1RestException('Internal server error', 500, { status: 500 }));
|
|
233
|
+
await expect(applicationService.exists('SomePath', Application_1.ApplicationTypes.CUBE, 'SomeCube', true)).rejects.toThrow('Internal server error');
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
//# sourceMappingURL=applicationService.issue38.test.js.map
|