tm1npm 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/objects/Axis.d.ts +1 -0
  2. package/lib/objects/Axis.d.ts.map +1 -1
  3. package/lib/objects/Axis.js +3 -0
  4. package/lib/objects/Chore.d.ts +2 -2
  5. package/lib/objects/Chore.d.ts.map +1 -1
  6. package/lib/objects/Chore.js +7 -13
  7. package/lib/objects/Cube.d.ts.map +1 -1
  8. package/lib/objects/Cube.js +2 -1
  9. package/lib/objects/Hierarchy.js +10 -10
  10. package/lib/objects/MDXView.d.ts +2 -0
  11. package/lib/objects/MDXView.d.ts.map +1 -1
  12. package/lib/objects/MDXView.js +30 -9
  13. package/lib/objects/NativeView.d.ts +5 -5
  14. package/lib/objects/NativeView.d.ts.map +1 -1
  15. package/lib/objects/NativeView.js +17 -34
  16. package/lib/objects/Process.d.ts +8 -3
  17. package/lib/objects/Process.d.ts.map +1 -1
  18. package/lib/objects/Process.js +143 -33
  19. package/lib/objects/Subset.d.ts.map +1 -1
  20. package/lib/objects/Subset.js +10 -3
  21. package/lib/objects/User.d.ts +5 -5
  22. package/lib/objects/User.d.ts.map +1 -1
  23. package/lib/objects/User.js +14 -23
  24. package/lib/tests/debuggerService.test.js +3 -1
  25. package/lib/tests/objectModelParity.test.js +362 -11
  26. package/lib/tests/objects.improved.test.js +28 -5
  27. package/lib/tests/user.issue61.test.d.ts +2 -0
  28. package/lib/tests/user.issue61.test.d.ts.map +1 -0
  29. package/lib/tests/user.issue61.test.js +180 -0
  30. package/lib/utils/Utils.d.ts +6 -1
  31. package/lib/utils/Utils.d.ts.map +1 -1
  32. package/lib/utils/Utils.js +56 -7
  33. package/package.json +1 -1
  34. package/src/objects/Axis.ts +4 -0
  35. package/src/objects/Chore.ts +7 -14
  36. package/src/objects/Cube.ts +2 -1
  37. package/src/objects/Hierarchy.ts +11 -11
  38. package/src/objects/MDXView.ts +29 -9
  39. package/src/objects/NativeView.ts +26 -42
  40. package/src/objects/Process.ts +182 -66
  41. package/src/objects/Subset.ts +17 -3
  42. package/src/objects/User.ts +17 -23
  43. package/src/tests/debuggerService.test.ts +3 -1
  44. package/src/tests/objectModelParity.test.ts +456 -11
  45. package/src/tests/objects.improved.test.ts +41 -9
  46. package/src/tests/user.issue61.test.ts +206 -0
  47. package/src/utils/Utils.ts +60 -7
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const User_1 = require("../objects/User");
4
+ const Utils_1 = require("../utils/Utils");
5
+ describe('UserType — string enum (issue #61)', () => {
6
+ test('should produce correct string names from toString()', () => {
7
+ expect(User_1.UserType.User.toString()).toBe('User');
8
+ expect(User_1.UserType.SecurityAdmin.toString()).toBe('SecurityAdmin');
9
+ expect(User_1.UserType.DataAdmin.toString()).toBe('DataAdmin');
10
+ expect(User_1.UserType.Admin.toString()).toBe('Admin');
11
+ expect(User_1.UserType.OperationsAdmin.toString()).toBe('OperationsAdmin');
12
+ });
13
+ test('should serialize Type field as string name in body', () => {
14
+ const user = new User_1.User('Alice', [], undefined, undefined, User_1.UserType.Admin);
15
+ const body = JSON.parse(user.body);
16
+ expect(body.Type).toBe('Admin');
17
+ });
18
+ test('should serialize User type as "User" string in body', () => {
19
+ const user = new User_1.User('Alice', []);
20
+ const body = JSON.parse(user.body);
21
+ expect(body.Type).toBe('User');
22
+ });
23
+ test('should parse string value in userType setter', () => {
24
+ const user = new User_1.User('Alice', []);
25
+ user.userType = 'Admin';
26
+ expect(user.userType).toBe(User_1.UserType.Admin);
27
+ });
28
+ test('should parse case-insensitive string in userType setter', () => {
29
+ const user = new User_1.User('Alice', []);
30
+ user.userType = 'admin';
31
+ expect(user.userType).toBe(User_1.UserType.Admin);
32
+ });
33
+ test('should throw on invalid userType string', () => {
34
+ const user = new User_1.User('Alice', []);
35
+ expect(() => { user.userType = 'InvalidType'; }).toThrow();
36
+ });
37
+ });
38
+ describe('User — group auto-detection (issue #61)', () => {
39
+ test('should detect Admin type from groups', () => {
40
+ const user = new User_1.User('Alice', ['Admin']);
41
+ expect(user.userType).toBe(User_1.UserType.Admin);
42
+ });
43
+ test('should detect SecurityAdmin type from groups', () => {
44
+ const user = new User_1.User('Alice', ['SecurityAdmin']);
45
+ expect(user.userType).toBe(User_1.UserType.SecurityAdmin);
46
+ });
47
+ test('should detect DataAdmin type from groups', () => {
48
+ const user = new User_1.User('Alice', ['DataAdmin']);
49
+ expect(user.userType).toBe(User_1.UserType.DataAdmin);
50
+ });
51
+ test('should detect OperationsAdmin type from groups', () => {
52
+ const user = new User_1.User('Alice', ['OperationsAdmin']);
53
+ expect(user.userType).toBe(User_1.UserType.OperationsAdmin);
54
+ });
55
+ test('should default to User type when no special groups present', () => {
56
+ const user = new User_1.User('Alice', ['Everyone', 'SomeTeam']);
57
+ expect(user.userType).toBe(User_1.UserType.User);
58
+ });
59
+ test('should add correct string group when userType set to Admin', () => {
60
+ const user = new User_1.User('Alice', []);
61
+ user.userType = User_1.UserType.Admin;
62
+ expect(user.groups).toContain('Admin');
63
+ });
64
+ test('should not add a group when userType set to User', () => {
65
+ const user = new User_1.User('Alice', []);
66
+ user.userType = User_1.UserType.User;
67
+ expect(user.groups).toHaveLength(0);
68
+ });
69
+ });
70
+ describe('User — isXxxAdmin getters (issue #61)', () => {
71
+ test('should return true for isAdmin when Admin group present', () => {
72
+ const user = new User_1.User('Alice', ['Admin']);
73
+ expect(user.isAdmin).toBe(true);
74
+ });
75
+ test('should return false for isAdmin when Admin group absent', () => {
76
+ const user = new User_1.User('Alice', ['Everyone']);
77
+ expect(user.isAdmin).toBe(false);
78
+ });
79
+ test('should return true for isDataAdmin when Admin group present', () => {
80
+ const user = new User_1.User('Alice', ['Admin']);
81
+ expect(user.isDataAdmin).toBe(true);
82
+ });
83
+ test('should return true for isDataAdmin when DataAdmin group present', () => {
84
+ const user = new User_1.User('Alice', ['DataAdmin']);
85
+ expect(user.isDataAdmin).toBe(true);
86
+ });
87
+ test('should return true for isSecurityAdmin when SecurityAdmin group present', () => {
88
+ const user = new User_1.User('Alice', ['SecurityAdmin']);
89
+ expect(user.isSecurityAdmin).toBe(true);
90
+ });
91
+ test('should return true for isOpsAdmin when OperationsAdmin group present', () => {
92
+ const user = new User_1.User('Alice', ['OperationsAdmin']);
93
+ expect(user.isOpsAdmin).toBe(true);
94
+ });
95
+ });
96
+ describe('User.fromDict — Type field parsing (issue #61)', () => {
97
+ test('should parse Type string field from API response dict', () => {
98
+ const dict = {
99
+ Name: 'Alice',
100
+ FriendlyName: 'Alice',
101
+ Groups: [{ Name: 'Admin' }],
102
+ Type: 'Admin',
103
+ Enabled: true,
104
+ };
105
+ const user = User_1.User.fromDict(dict);
106
+ expect(user.userType).toBe(User_1.UserType.Admin);
107
+ });
108
+ test('should parse SecurityAdmin Type field from API response dict', () => {
109
+ const dict = {
110
+ Name: 'Bob',
111
+ FriendlyName: 'Bob',
112
+ Groups: [{ Name: 'SecurityAdmin' }],
113
+ Type: 'SecurityAdmin',
114
+ Enabled: true,
115
+ };
116
+ const user = User_1.User.fromDict(dict);
117
+ expect(user.userType).toBe(User_1.UserType.SecurityAdmin);
118
+ });
119
+ });
120
+ describe('CaseAndSpaceInsensitiveSet — casing preservation (issue #61)', () => {
121
+ test('should preserve original casing of first insertion', () => {
122
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
123
+ set.add('Admin');
124
+ set.add('ADMIN');
125
+ set.add('admin');
126
+ expect(set.size).toBe(1);
127
+ expect(Array.from(set)).toEqual(['Admin']);
128
+ });
129
+ test('should find by any casing variant', () => {
130
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
131
+ set.add('HelloWorld');
132
+ expect(set.has('helloworld')).toBe(true);
133
+ expect(set.has('HELLOWORLD')).toBe(true);
134
+ expect(set.has('Hello World')).toBe(true);
135
+ expect(set.has('hello world')).toBe(true);
136
+ });
137
+ test('should return first-inserted casing during iteration', () => {
138
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
139
+ set.add('MyGroup');
140
+ set.add('mygroup');
141
+ set.add('MYGROUP');
142
+ expect(Array.from(set)).toEqual(['MyGroup']);
143
+ });
144
+ test('should delete by any casing variant', () => {
145
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
146
+ set.add('Admin');
147
+ expect(set.delete('ADMIN')).toBe(true);
148
+ expect(set.size).toBe(0);
149
+ expect(set.has('Admin')).toBe(false);
150
+ });
151
+ test('should return false when deleting non-existent entry', () => {
152
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
153
+ expect(set.delete('NonExistent')).toBe(false);
154
+ });
155
+ test('should maintain correct size after operations', () => {
156
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
157
+ set.add('A');
158
+ set.add('B');
159
+ set.add('a'); // duplicate — ignored
160
+ expect(set.size).toBe(2);
161
+ set.delete('A');
162
+ expect(set.size).toBe(1);
163
+ });
164
+ test('should clear all entries', () => {
165
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
166
+ set.add('A');
167
+ set.add('B');
168
+ set.clear();
169
+ expect(set.size).toBe(0);
170
+ expect(set.has('A')).toBe(false);
171
+ });
172
+ test('should handle values with spaces', () => {
173
+ const set = new Utils_1.CaseAndSpaceInsensitiveSet();
174
+ set.add('Data Admin');
175
+ expect(set.has('dataadmin')).toBe(true);
176
+ expect(set.has('DataAdmin')).toBe(true);
177
+ expect(Array.from(set)).toEqual(['Data Admin']);
178
+ });
179
+ });
180
+ //# sourceMappingURL=user.issue61.test.js.map
@@ -20,14 +20,17 @@ export declare class CaseAndSpaceInsensitiveMap<T> extends Map<string, T> {
20
20
  delete(key: string): boolean;
21
21
  }
22
22
  export declare class CaseAndSpaceInsensitiveSet extends Set<string> {
23
- private normalizeValue;
23
+ private _normalizedMap;
24
+ constructor(values?: Iterable<string>);
24
25
  add(value: string): this;
25
26
  has(value: string): boolean;
26
27
  delete(value: string): boolean;
28
+ clear(): void;
27
29
  }
28
30
  export declare function caseAndSpaceInsensitiveEquals(str1: string, str2: string): boolean;
29
31
  export declare function lowerAndDropSpaces(str: string): string;
30
32
  export declare function escapeODataValue(str: string): string;
33
+ export declare function buildUrlFriendlyObjectName(objectName: string): string;
31
34
  export declare function formatUrl(template: string, ...args: string[]): string;
32
35
  export declare function extractCellsetCells(cellset: any): any[];
33
36
  export declare function buildMdxFromAxes(axes: any[]): string;
@@ -59,6 +62,7 @@ export declare function getMdxElementFromAttribute(attribute: string, cube: stri
59
62
  export declare function buildMdxTuple(members: string[]): string;
60
63
  export declare function verifyVersion(actualVersion: string, requiredVersion: string): boolean;
61
64
  export declare function readObjectNameFromUrl(url: string): string;
65
+ export declare function readObjectNameFromUrl(url: string, pattern: string | RegExp): string | null;
62
66
  export declare function parseODataBindUrl(url: string): string[];
63
67
  export declare function integerizeVersion(version: string): number;
64
68
  export declare function frameToSignificantValue(value: any): any;
@@ -74,6 +78,7 @@ export declare const Utils: {
74
78
  CaseAndSpaceInsensitiveSet: typeof CaseAndSpaceInsensitiveSet;
75
79
  caseAndSpaceInsensitiveEquals: typeof caseAndSpaceInsensitiveEquals;
76
80
  lowerAndDropSpaces: typeof lowerAndDropSpaces;
81
+ buildUrlFriendlyObjectName: typeof buildUrlFriendlyObjectName;
77
82
  formatUrl: typeof formatUrl;
78
83
  extractCellsetCells: typeof extractCellsetCells;
79
84
  buildMdxFromAxes: typeof buildMdxFromAxes;
@@ -1 +1 @@
1
- {"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../src/utils/Utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../src/utils/Utils.ts"],"names":[],"mappings":"AAAA,qBAAa,2BAA2B,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,YAAY;IAIpB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAIhC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAG/B;AAED,qBAAa,iCAAiC,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,YAAY;IAIpB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAIhC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAG/B;AAED,qBAAa,0BAA0B,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,YAAY;IAIpB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAIhC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAI/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAG/B;AAED,qBAAa,0BAA2B,SAAQ,GAAG,CAAC,MAAM,CAAC;IACvD,OAAO,CAAC,cAAc,CAAsB;gBAEhC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC;IAUrC,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IASxB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAI3B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQ9B,KAAK,IAAI,IAAI;CAIhB;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAMrE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,CAKvD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CA0BpD;AAED,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAE3G;AAED,wBAAgB,4CAA4C,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAgBzG;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnH;AAED,wBAAgB,wCAAwC,CAAC,yBAAyB,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAgBpH;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAAI,CAS/H;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,KAAK,IAAI,CAU9H;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAQnG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAUvG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAU3G;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAUtG;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAK7D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQxE;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQ5D;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED,wBAAgB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAGhD;AAGD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAElF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAKvD;AAGD,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAmBrF;AAID,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;AAC3D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAwB5F,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAKvD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzD;AAGD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAQvD;AAGD,qBAAa,4BAA4B;IACzB,OAAO,CAAC,aAAa;gBAAb,aAAa,GAAE,GAAQ;CAG9C;AAGD,wBAAgB,uBAAuB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIhE;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAExD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BjB,CAAC;AAGF;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAiCtG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,GAAE,OAAc,EAAE,UAAU,GAAE,OAAc,IACtE,QAAQ,GAAG,EAAE,aAAa,MAAM,EAAE,YAAY,kBAAkB,KAAG,IAAI,CAsC3F;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,GAAE,MAAU,EAAE,SAAS,GAAE,MAAa,IACrD,QAAQ,GAAG,EAAE,aAAa,MAAM,EAAE,YAAY,kBAAkB,KAAG,IAAI,CAiC3F"}
@@ -4,6 +4,7 @@ exports.Utils = exports.HTTPAdapterWithSocketOptions = exports.CaseAndSpaceInsen
4
4
  exports.caseAndSpaceInsensitiveEquals = caseAndSpaceInsensitiveEquals;
5
5
  exports.lowerAndDropSpaces = lowerAndDropSpaces;
6
6
  exports.escapeODataValue = escapeODataValue;
7
+ exports.buildUrlFriendlyObjectName = buildUrlFriendlyObjectName;
7
8
  exports.formatUrl = formatUrl;
8
9
  exports.extractCellsetCells = extractCellsetCells;
9
10
  exports.buildMdxFromAxes = buildMdxFromAxes;
@@ -90,17 +91,37 @@ class CaseAndSpaceInsensitiveMap extends Map {
90
91
  }
91
92
  exports.CaseAndSpaceInsensitiveMap = CaseAndSpaceInsensitiveMap;
92
93
  class CaseAndSpaceInsensitiveSet extends Set {
93
- normalizeValue(value) {
94
- return value.toLowerCase().replace(/\s+/g, '');
94
+ constructor(values) {
95
+ super();
96
+ this._normalizedMap = new Map();
97
+ if (values) {
98
+ for (const v of values) {
99
+ this.add(v);
100
+ }
101
+ }
95
102
  }
96
103
  add(value) {
97
- return super.add(this.normalizeValue(value));
104
+ const key = lowerAndDropSpaces(value);
105
+ if (!this._normalizedMap.has(key)) {
106
+ this._normalizedMap.set(key, value);
107
+ super.add(value);
108
+ }
109
+ return this;
98
110
  }
99
111
  has(value) {
100
- return super.has(this.normalizeValue(value));
112
+ return this._normalizedMap.has(lowerAndDropSpaces(value));
101
113
  }
102
114
  delete(value) {
103
- return super.delete(this.normalizeValue(value));
115
+ const key = lowerAndDropSpaces(value);
116
+ const original = this._normalizedMap.get(key);
117
+ if (original === undefined)
118
+ return false;
119
+ this._normalizedMap.delete(key);
120
+ return super.delete(original);
121
+ }
122
+ clear() {
123
+ this._normalizedMap.clear();
124
+ super.clear();
104
125
  }
105
126
  }
106
127
  exports.CaseAndSpaceInsensitiveSet = CaseAndSpaceInsensitiveSet;
@@ -118,6 +139,14 @@ function lowerAndDropSpaces(str) {
118
139
  function escapeODataValue(str) {
119
140
  return str.replace(/'/g, "''");
120
141
  }
142
+ function buildUrlFriendlyObjectName(objectName) {
143
+ return objectName
144
+ .replace(/'/g, "''")
145
+ .replace(/%/g, "%25")
146
+ .replace(/#/g, "%23")
147
+ .replace(/\?/g, "%3F")
148
+ .replace(/&/g, "%26");
149
+ }
121
150
  function formatUrl(template, ...args) {
122
151
  let url = template;
123
152
  for (const arg of args) {
@@ -329,8 +358,27 @@ function verifyVersion(actualVersion, requiredVersion) {
329
358
  }
330
359
  return true; // Equal versions
331
360
  }
332
- function readObjectNameFromUrl(url) {
333
- // Extract object name from URL like "/Dimensions('DimName')" -> "DimName"
361
+ function readObjectNameFromUrl(url, pattern) {
362
+ // tm1py parity: when `pattern` is provided, behave like
363
+ // `re.match(pattern, url)` + `unquote(match.group(1))` — anchored at start,
364
+ // URL-decodes the first capture group, returns null on no match.
365
+ if (pattern !== undefined) {
366
+ const re = typeof pattern === 'string'
367
+ ? new RegExp(pattern.startsWith('^') ? pattern : '^' + pattern)
368
+ : pattern;
369
+ const m = url.match(re);
370
+ if (!m || m[1] === undefined)
371
+ return null;
372
+ try {
373
+ return decodeURIComponent(m[1]);
374
+ }
375
+ catch (_a) {
376
+ // tm1py parity: urllib.parse.unquote is permissive on malformed %XX
377
+ // (returns the original string). decodeURIComponent throws — fall back.
378
+ return m[1];
379
+ }
380
+ }
381
+ // Backward-compat: extract first ('name') segment, return '' on no match
334
382
  const match = url.match(/\('([^']+)'\)/);
335
383
  return match ? match[1] : '';
336
384
  }
@@ -381,6 +429,7 @@ exports.Utils = {
381
429
  CaseAndSpaceInsensitiveSet,
382
430
  caseAndSpaceInsensitiveEquals,
383
431
  lowerAndDropSpaces,
432
+ buildUrlFriendlyObjectName,
384
433
  formatUrl,
385
434
  extractCellsetCells,
386
435
  buildMdxFromAxes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tm1npm",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "A Node.js module for TM1",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -102,6 +102,10 @@ export class ViewTitleSelection {
102
102
  return this._subset;
103
103
  }
104
104
 
105
+ public set subset(value: Subset | AnonymousSubset) {
106
+ this._subset = value;
107
+ }
108
+
105
109
  public get dimensionName(): string {
106
110
  return this._dimensionName;
107
111
  }
@@ -148,11 +148,11 @@ export class Chore extends TM1Object {
148
148
  return body;
149
149
  }
150
150
 
151
- public reschedule(frequency: ChoreFrequency, startTime?: ChoreStartTime): void {
152
- /** Reschedule the chore
151
+ public setFrequency(frequency: ChoreFrequency, startTime?: ChoreStartTime): void {
152
+ /** Replace the chore frequency (and optionally start time)
153
153
  *
154
154
  * :param frequency: new ChoreFrequency
155
- * :param start_time: new ChoreStartTime (optional)
155
+ * :param startTime: new ChoreStartTime (optional)
156
156
  */
157
157
  this._frequency = frequency;
158
158
  if (startTime) {
@@ -197,22 +197,15 @@ export class Chore extends TM1Object {
197
197
  return { [this._name]: processNames };
198
198
  }
199
199
 
200
- public rescheduleByTime(days: number = 0, hours: number = 0, minutes: number = 0, seconds: number = 0): void {
201
- /** Programmatically reschedule a chore by adding time to current start time
200
+ public reschedule(days: number = 0, hours: number = 0, minutes: number = 0, seconds: number = 0): void {
201
+ /** Reschedule the chore by adding time to the current start time.
202
+ *
202
203
  * :param days: Days to add
203
204
  * :param hours: Hours to add
204
205
  * :param minutes: Minutes to add
205
206
  * :param seconds: Seconds to add
206
207
  */
207
- if (this._startTime.datetime) {
208
- const newDateTime = new Date(this._startTime.datetime);
209
- newDateTime.setDate(newDateTime.getDate() + days);
210
- newDateTime.setHours(newDateTime.getHours() + hours);
211
- newDateTime.setMinutes(newDateTime.getMinutes() + minutes);
212
- newDateTime.setSeconds(newDateTime.getSeconds() + seconds);
213
-
214
- this._startTime = new ChoreStartTime(newDateTime, this._startTime.tz);
215
- }
208
+ this._startTime.add(days, hours, minutes, seconds);
216
209
  }
217
210
 
218
211
  public static fromJson(choreAsJson: string): Chore {
@@ -1,5 +1,6 @@
1
1
  import { TM1Object } from './TM1Object';
2
2
  import { Rules } from './Rules';
3
+ import { buildUrlFriendlyObjectName } from '../utils/Utils';
3
4
 
4
5
  export class Cube extends TM1Object {
5
6
  /** Abstraction of a TM1 Cube
@@ -113,7 +114,7 @@ export class Cube extends TM1Object {
113
114
  private constructBody(): any {
114
115
  const body: any = {
115
116
  Name: this._name,
116
- Dimensions: this._dimensions.map(dim => ({ Name: dim }))
117
+ "Dimensions@odata.bind": this._dimensions.map(dim => `Dimensions('${buildUrlFriendlyObjectName(dim)}')`)
117
118
  };
118
119
 
119
120
  if (this._rules) {
@@ -1,7 +1,7 @@
1
1
  import { TM1Object } from './TM1Object';
2
2
  import { Element, ElementType } from './Element';
3
3
  import { ElementAttribute } from './ElementAttribute';
4
- import { lowerAndDropSpaces } from '../utils/Utils';
4
+ import { lowerAndDropSpaces, caseAndSpaceInsensitiveEquals } from '../utils/Utils';
5
5
 
6
6
  export class Hierarchy extends TM1Object {
7
7
  private _name: string;
@@ -29,7 +29,7 @@ export class Hierarchy extends TM1Object {
29
29
 
30
30
  if (elements) {
31
31
  for (const elem of elements) {
32
- this._elements.set(elem.name.toLowerCase(), elem);
32
+ this._elements.set(lowerAndDropSpaces(elem.name), elem);
33
33
  }
34
34
  }
35
35
 
@@ -98,7 +98,7 @@ export class Hierarchy extends TM1Object {
98
98
  }
99
99
 
100
100
  public get elementNames(): string[] {
101
- return Array.from(this._elements.keys());
101
+ return Array.from(this._elements.values()).map(e => e.name);
102
102
  }
103
103
 
104
104
  public get elementAttributes(): ElementAttribute[] {
@@ -172,19 +172,19 @@ export class Hierarchy extends TM1Object {
172
172
  }
173
173
 
174
174
  public addElement(element: Element): void {
175
- this._elements.set(element.name.toLowerCase(), element);
175
+ this._elements.set(lowerAndDropSpaces(element.name), element);
176
176
  }
177
177
 
178
178
  public removeElement(elementName: string): boolean {
179
- return this._elements.delete(elementName.toLowerCase());
179
+ return this._elements.delete(lowerAndDropSpaces(elementName));
180
180
  }
181
181
 
182
182
  public getElement(elementName: string): Element | undefined {
183
- return this._elements.get(elementName.toLowerCase());
183
+ return this._elements.get(lowerAndDropSpaces(elementName));
184
184
  }
185
185
 
186
186
  public hasElement(elementName: string): boolean {
187
- return this._elements.has(elementName.toLowerCase());
187
+ return this._elements.has(lowerAndDropSpaces(elementName));
188
188
  }
189
189
 
190
190
  public addEdge(parentName: string, componentName: string, weight: number = 1): void {
@@ -216,7 +216,7 @@ export class Hierarchy extends TM1Object {
216
216
 
217
217
  public removeElementAttribute(attributeName: string): boolean {
218
218
  const index = this._elementAttributes.findIndex(ea =>
219
- ea.name.toLowerCase() === attributeName.toLowerCase());
219
+ caseAndSpaceInsensitiveEquals(ea.name, attributeName));
220
220
 
221
221
  if (index !== -1) {
222
222
  this._elementAttributes.splice(index, 1);
@@ -227,12 +227,12 @@ export class Hierarchy extends TM1Object {
227
227
 
228
228
  public getElementAttribute(attributeName: string): ElementAttribute | undefined {
229
229
  return this._elementAttributes.find(ea =>
230
- ea.name.toLowerCase() === attributeName.toLowerCase());
230
+ caseAndSpaceInsensitiveEquals(ea.name, attributeName));
231
231
  }
232
232
 
233
233
  public hasElementAttribute(attributeName: string): boolean {
234
234
  return this._elementAttributes.some(ea =>
235
- ea.name.toLowerCase() === attributeName.toLowerCase());
235
+ caseAndSpaceInsensitiveEquals(ea.name, attributeName));
236
236
  }
237
237
 
238
238
  public getAncestors(elementName: string, recursive: boolean = false): string[] {
@@ -337,7 +337,7 @@ export class Hierarchy extends TM1Object {
337
337
  const element = this._elements.get(oldKey)!;
338
338
  element.name = newName;
339
339
  this._elements.delete(oldKey);
340
- this._elements.set(newName.toLowerCase(), element);
340
+ this._elements.set(lowerAndDropSpaces(newName), element);
341
341
  }
342
342
 
343
343
  // Rebuild edges replacing all occurrences of oldName
@@ -7,6 +7,27 @@ export class MDXView extends View {
7
7
  * IMPORTANT. MDXViews can't be seen through the old TM1 clients (Archict, Perspectives). They do exist though!
8
8
  */
9
9
 
10
+ private static readonly _DYNAMIC_PROPERTIES_EXCLUDED_KEYS: ReadonlySet<string> = new Set([
11
+ '@odata.type',
12
+ '@odata.context',
13
+ '@odata.etag',
14
+ 'Name',
15
+ 'MDX',
16
+ 'Cube',
17
+ 'Attributes',
18
+ 'LocalizedAttributes',
19
+ ]);
20
+
21
+ private static _filterDynamicProperties(properties: Record<string, any>): Record<string, any> {
22
+ const out: Record<string, any> = {};
23
+ for (const key of Object.keys(properties)) {
24
+ if (!MDXView._DYNAMIC_PROPERTIES_EXCLUDED_KEYS.has(key)) {
25
+ out[key] = properties[key];
26
+ }
27
+ }
28
+ return out;
29
+ }
30
+
10
31
  private _mdx: string;
11
32
  private _dynamicProperties: Record<string, any>;
12
33
 
@@ -85,21 +106,20 @@ export class MDXView extends View {
85
106
 
86
107
  public static fromDict(viewAsDict: any, cubeName?: string): MDXView {
87
108
  return new MDXView(
88
- viewAsDict.Cube?.Name || cubeName!,
109
+ cubeName ? cubeName : viewAsDict.Cube.Name,
89
110
  viewAsDict.Name,
90
111
  viewAsDict.MDX,
91
- viewAsDict.Properties || {}
112
+ MDXView._filterDynamicProperties(viewAsDict),
92
113
  );
93
114
  }
94
115
 
95
116
  private constructBody(): string {
96
- const mdxViewAsDict: any = {};
97
- mdxViewAsDict['@odata.type'] = 'ibm.tm1.api.v1.MDXView';
98
- mdxViewAsDict['Name'] = this._name;
99
- mdxViewAsDict['MDX'] = this._mdx;
100
- if (Object.keys(this._dynamicProperties).length > 0) {
101
- mdxViewAsDict['Properties'] = this._dynamicProperties;
102
- }
117
+ const mdxViewAsDict: Record<string, any> = {
118
+ '@odata.type': 'ibm.tm1.api.v1.MDXView',
119
+ Name: this._name,
120
+ MDX: this._mdx,
121
+ ...MDXView._filterDynamicProperties(this._dynamicProperties),
122
+ };
103
123
  return JSON.stringify(mdxViewAsDict);
104
124
  }
105
125
  }