@vcd/sdk 0.13.0 → 15.0.0-alpha.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 (92) hide show
  1. package/client/client/api.result.service.d.ts +20 -0
  2. package/client/client/constants.d.ts +10 -0
  3. package/client/client/index.d.ts +7 -0
  4. package/client/client/logging.interceptor.d.ts +14 -0
  5. package/client/client/request.headers.interceptor.d.ts +20 -0
  6. package/client/client/response.normalization.interceptor.d.ts +39 -0
  7. package/client/client/vcd.api.client.d.ts +351 -0
  8. package/client/client/vcd.http.client.d.ts +32 -0
  9. package/client/client/vcd.transfer.client.d.ts +121 -0
  10. package/client/container-hooks/index.d.ts +58 -0
  11. package/client/index.d.ts +2 -0
  12. package/client/openapi.d.ts +76 -0
  13. package/client/query/filter.builder.d.ts +162 -0
  14. package/client/query/index.d.ts +2 -0
  15. package/client/query/query.builder.d.ts +30 -0
  16. package/common/container-hooks.d.ts +2 -2
  17. package/core/plugin.module.d.ts +10 -5
  18. package/esm2020/client/client/api.result.service.mjs +43 -0
  19. package/esm2020/client/client/constants.mjs +13 -0
  20. package/esm2020/client/client/index.mjs +8 -0
  21. package/esm2020/client/client/logging.interceptor.mjs +44 -0
  22. package/esm2020/client/client/request.headers.interceptor.mjs +91 -0
  23. package/esm2020/client/client/response.normalization.interceptor.mjs +59 -0
  24. package/esm2020/client/client/vcd.api.client.mjs +602 -0
  25. package/esm2020/client/client/vcd.http.client.mjs +52 -0
  26. package/esm2020/client/client/vcd.transfer.client.mjs +166 -0
  27. package/esm2020/client/container-hooks/index.mjs +57 -0
  28. package/esm2020/client/index.mjs +3 -0
  29. package/esm2020/client/openapi.mjs +16 -0
  30. package/esm2020/client/query/filter.builder.mjs +195 -0
  31. package/esm2020/client/query/index.mjs +3 -0
  32. package/esm2020/client/query/query.builder.mjs +79 -0
  33. package/esm2020/common/container-hooks.mjs +74 -0
  34. package/esm2020/common/index.mjs +2 -0
  35. package/esm2020/core/index.mjs +2 -0
  36. package/esm2020/core/plugin.module.mjs +18 -0
  37. package/esm2020/main.mjs +45 -0
  38. package/esm2020/public-api.mjs +8 -0
  39. package/esm2020/vcd-sdk.mjs +5 -0
  40. package/fesm2015/vcd-sdk.mjs +1513 -0
  41. package/fesm2015/vcd-sdk.mjs.map +1 -0
  42. package/fesm2020/vcd-sdk.mjs +1508 -0
  43. package/fesm2020/vcd-sdk.mjs.map +1 -0
  44. package/index.d.ts +5 -0
  45. package/main.d.ts +11 -5
  46. package/package.json +30 -39
  47. package/public-api.d.ts +1 -1
  48. package/vcd-sdk-15.0.0-alpha.0.tgz +0 -0
  49. package/LICENSE.txt +0 -12
  50. package/README.md +0 -119
  51. package/bundles/vcd-sdk.umd.js +0 -810
  52. package/bundles/vcd-sdk.umd.js.map +0 -1
  53. package/bundles/vcd-sdk.umd.min.js +0 -16
  54. package/bundles/vcd-sdk.umd.min.js.map +0 -1
  55. package/esm2015/common/container-hooks.js +0 -219
  56. package/esm2015/common/index.js +0 -6
  57. package/esm2015/core/index.js +0 -6
  58. package/esm2015/core/plugin.module.js +0 -53
  59. package/esm2015/i18n/index.js +0 -8
  60. package/esm2015/i18n/translate.pipe.js +0 -92
  61. package/esm2015/i18n/translate.service.js +0 -229
  62. package/esm2015/i18n/translation.loader.js +0 -63
  63. package/esm2015/main.js +0 -37
  64. package/esm2015/public-api.js +0 -12
  65. package/esm2015/vcd-sdk.js +0 -10
  66. package/esm5/common/container-hooks.js +0 -266
  67. package/esm5/common/index.js +0 -6
  68. package/esm5/core/index.js +0 -6
  69. package/esm5/core/plugin.module.js +0 -64
  70. package/esm5/i18n/index.js +0 -8
  71. package/esm5/i18n/translate.pipe.js +0 -108
  72. package/esm5/i18n/translate.service.js +0 -280
  73. package/esm5/i18n/translation.loader.js +0 -68
  74. package/esm5/main.js +0 -41
  75. package/esm5/public-api.js +0 -12
  76. package/esm5/vcd-sdk.js +0 -10
  77. package/fesm2015/vcd-sdk.js +0 -511
  78. package/fesm2015/vcd-sdk.js.map +0 -1
  79. package/fesm5/vcd-sdk.js +0 -620
  80. package/fesm5/vcd-sdk.js.map +0 -1
  81. package/i18n/index.d.ts +0 -3
  82. package/i18n/translate.pipe.d.ts +0 -12
  83. package/i18n/translate.service.d.ts +0 -21
  84. package/i18n/translation.loader.d.ts +0 -11
  85. package/schematics/collection.json +0 -10
  86. package/schematics/ng-add/index.d.ts +0 -3
  87. package/schematics/ng-add/index.js +0 -101
  88. package/schematics/ng-add/index.ts +0 -134
  89. package/schematics/ng-add/schema.d.ts +0 -8
  90. package/schematics/ng-add/schema.json +0 -19
  91. package/vcd-sdk.d.ts +0 -5
  92. package/vcd-sdk.metadata.json +0 -1
@@ -0,0 +1,1513 @@
1
+ import * as i1 from '@angular/common/http';
2
+ import { HttpResponse, HttpClient, HttpHeaders, HttpClientModule } from '@angular/common/http';
3
+ import * as i0 from '@angular/core';
4
+ import { Injectable, Optional, InjectionToken, NgModule } from '@angular/core';
5
+ import { CommonModule } from '@angular/common';
6
+ import { tap, finalize, map, catchError, switchMap, retry, flatMap, skipWhile, share, concatMap, filter, withLatestFrom } from 'rxjs/operators';
7
+ import { Observable, throwError, BehaviorSubject, of, ReplaySubject, merge } from 'rxjs';
8
+ import { TaskType } from '@vcd/bindings/vcloud/api/rest/schema_v1_5';
9
+
10
+ // tslint:disable:variable-name
11
+ // tslint:disable-next-line:no-namespace
12
+ var Query;
13
+ (function (Query) {
14
+ class Builder {
15
+ constructor() {
16
+ this._format = Format.ID_RECORDS;
17
+ this._links = true;
18
+ this._pageSize = 25;
19
+ }
20
+ static getBuilder() {
21
+ return new Builder();
22
+ }
23
+ static ofType(type) {
24
+ const qb = new Builder();
25
+ qb._type = type;
26
+ return qb;
27
+ }
28
+ format(format) {
29
+ this._format = format;
30
+ return this;
31
+ }
32
+ links(links) {
33
+ this._links = links;
34
+ return this;
35
+ }
36
+ pageSize(pageSize) {
37
+ this._pageSize = pageSize;
38
+ return this;
39
+ }
40
+ fields(...fields) {
41
+ this._fields = fields;
42
+ return this;
43
+ }
44
+ filter(filter) {
45
+ this._filter = filter;
46
+ return this;
47
+ }
48
+ sort(...sort) {
49
+ this._sort = sort;
50
+ return this;
51
+ }
52
+ get() {
53
+ let query = `?type=${this._type}&format=${this._format}&links=${this._links}&pageSize=${this._pageSize}`;
54
+ if (this._fields && this._fields.length > 0) {
55
+ query += `&fields=${this._fields.join(',')}`;
56
+ }
57
+ if (this._filter) {
58
+ query += `&filter=${this._filter}`;
59
+ }
60
+ if (this._sort) {
61
+ this._sort.forEach(s => {
62
+ query += `&${s.reverse ? 'sortDesc' : 'sortAsc'}=${s.field}`;
63
+ });
64
+ }
65
+ return query;
66
+ }
67
+ getCloudAPI() {
68
+ let query = `?pageSize=${this._pageSize}`;
69
+ if (this._filter) {
70
+ query += `&filter=${this._filter}`;
71
+ }
72
+ if (this._sort) {
73
+ this._sort.forEach(s => {
74
+ query += `&${s.reverse ? 'sortDesc' : 'sortAsc'}=${s.field}`;
75
+ });
76
+ }
77
+ return query;
78
+ }
79
+ }
80
+ Query.Builder = Builder;
81
+ class Format {
82
+ }
83
+ Format.ID_RECORDS = 'idrecords';
84
+ Format.RECORDS = 'records';
85
+ Format.REFERENCES = 'references';
86
+ Query.Format = Format;
87
+ })(Query || (Query = {}));
88
+
89
+ // tslint:disable-next-line:no-namespace
90
+ var Filter;
91
+ (function (Filter) {
92
+ class Operators {
93
+ }
94
+ Operators.OR = ',';
95
+ Operators.AND = ';';
96
+ Operators.GT = '=gt=';
97
+ Operators.GE = '=ge=';
98
+ Operators.LT = '=lt=';
99
+ Operators.LE = '=le=';
100
+ Operators.EQ = '==';
101
+ Operators.NEQ = '!=';
102
+ /**
103
+ * Collection of strategies for wilcard string matching.
104
+ */
105
+ class MatchMode {
106
+ }
107
+ /**
108
+ * Match the start of a string.
109
+ */
110
+ MatchMode.START = 'START';
111
+ /**
112
+ * Match the end of a string.
113
+ */
114
+ MatchMode.END = 'END';
115
+ /**
116
+ * Match anywhere in the string.
117
+ */
118
+ MatchMode.ANYWHERE = 'ANYWHERE';
119
+ Filter.MatchMode = MatchMode;
120
+ class BuilderChain {
121
+ constructor(parent) {
122
+ this.result = '';
123
+ this.parent = parent;
124
+ }
125
+ query() {
126
+ return this.buildPartial();
127
+ }
128
+ // tslint:disable-next-line:max-line-length
129
+ and(condition1, condition2, conditionN) {
130
+ if (!condition1) {
131
+ return this.simpleAnd();
132
+ }
133
+ this.result += '(' + condition1.buildPartial() + Operators.AND + condition2.buildPartial();
134
+ if (conditionN && conditionN.length) {
135
+ conditionN.forEach((condition) => {
136
+ this.result += Operators.AND + condition.buildPartial();
137
+ });
138
+ }
139
+ this.result += ')';
140
+ return this;
141
+ }
142
+ simpleAnd() {
143
+ if (this.currentCompositeOp === Operators.OR || this.parent && this.parent.currentCompositeOp === Operators.OR) {
144
+ if (this.parent) {
145
+ this.parent.result = '(' + this.parent.result;
146
+ this.result += ')';
147
+ }
148
+ else {
149
+ this.wrap();
150
+ }
151
+ this.currentCompositeOp = Operators.AND;
152
+ }
153
+ this.result += Operators.AND;
154
+ return this;
155
+ }
156
+ // tslint:disable-next-line:max-line-length
157
+ or(condition1, condition2, conditionN) {
158
+ if (!condition1) {
159
+ return this.simpleOr();
160
+ }
161
+ this.result += '(' + condition1.buildPartial() + Operators.OR + condition2.buildPartial();
162
+ if (conditionN && conditionN.length) {
163
+ conditionN.forEach((condition) => {
164
+ this.result += Operators.OR + condition.buildPartial();
165
+ });
166
+ }
167
+ this.result += ')';
168
+ return this;
169
+ }
170
+ simpleOr() {
171
+ if (this.currentCompositeOp === Operators.AND || (this.parent && this.parent.currentCompositeOp === Operators.AND)) {
172
+ if (this.parent) {
173
+ this.parent.result = '(' + this.parent.result;
174
+ this.result += ')';
175
+ }
176
+ else {
177
+ this.wrap();
178
+ }
179
+ this.currentCompositeOp = Operators.OR;
180
+ }
181
+ this.result += Operators.OR;
182
+ return this;
183
+ }
184
+ wrap() {
185
+ this.result = '(' + this.result + ')';
186
+ this.currentCompositeOp = null;
187
+ return this;
188
+ }
189
+ buildPartial() {
190
+ return (this.parent) ? this.parent.buildPartial() + this.result : this.result;
191
+ }
192
+ is(property) {
193
+ const builder = new BuilderChain(this);
194
+ builder.result = property;
195
+ return builder;
196
+ }
197
+ equalTo(value, ...moreValues) {
198
+ return this.condition(Operators.EQ, value, ...moreValues);
199
+ }
200
+ notEqualTo(value) {
201
+ return this.condition(Operators.NEQ, value);
202
+ }
203
+ lessThan(value) {
204
+ return this.condition(Operators.LT, value);
205
+ }
206
+ lessOrEqualTo(value) {
207
+ return this.condition(Operators.LE, value);
208
+ }
209
+ greaterThan(value) {
210
+ return this.condition(Operators.GT, value);
211
+ }
212
+ greaterOrEqualTo(value) {
213
+ return this.condition(Operators.GE, value);
214
+ }
215
+ like(value, mode = MatchMode.START) {
216
+ let wildcardValue;
217
+ switch (mode) {
218
+ case MatchMode.START:
219
+ wildcardValue = `${value}*`;
220
+ break;
221
+ case MatchMode.END:
222
+ wildcardValue = `*${value}`;
223
+ break;
224
+ case MatchMode.ANYWHERE:
225
+ wildcardValue = `*${value}*`;
226
+ break;
227
+ default:
228
+ wildcardValue = value;
229
+ break;
230
+ }
231
+ return this.condition(Operators.EQ, wildcardValue);
232
+ }
233
+ condition(operator, value, ...moreValues) {
234
+ const name = this.result;
235
+ this.result += operator + encodeURI(value);
236
+ if (moreValues.length) {
237
+ moreValues.forEach((next) => {
238
+ this.result += ',' + name + operator + encodeURI(next);
239
+ });
240
+ this.currentCompositeOp = Operators.OR;
241
+ }
242
+ return this;
243
+ }
244
+ }
245
+ /**
246
+ * Builds a FIQL search condition using a fluent interface.
247
+ */
248
+ class Builder {
249
+ /**
250
+ * Create a simple property to be evaulated as a filter condition.
251
+ *
252
+ * @param property the name of the property
253
+ * @returns a Property instance for defining a filter condition
254
+ */
255
+ is(property) {
256
+ return new BuilderChain().is(property);
257
+ }
258
+ /**
259
+ * Create a conjunction (AND) condition from existing conditions.
260
+ *
261
+ * @param condition1 first condition
262
+ * @param condition2 second condition
263
+ * @param conditionN any additional conditions
264
+ * @returns an evaluatable filter condition
265
+ */
266
+ and(condition1, condition2, conditionN) {
267
+ return new BuilderChain().and(condition1, condition2, conditionN);
268
+ }
269
+ /**
270
+ * Create a disjunction (OR) condition from existing conditions.
271
+ *
272
+ * @param condition1 first condition
273
+ * @param condition2 second condition
274
+ * @param conditionN any additional conditions
275
+ * @returns an evaluatable filter condition
276
+ */
277
+ or(condition1, condition2, conditionN) {
278
+ return new BuilderChain().or(condition1, condition2, conditionN);
279
+ }
280
+ }
281
+ Filter.Builder = Builder;
282
+ })(Filter || (Filter = {}));
283
+
284
+ // tslint:disable:variable-name
285
+ class ApiResultService {
286
+ constructor() {
287
+ this._results = [];
288
+ }
289
+ get results() {
290
+ return this._results;
291
+ }
292
+ add(result) {
293
+ this._results = [result, ...this._results.slice(0, 99)];
294
+ }
295
+ clear() {
296
+ this._results = [];
297
+ }
298
+ }
299
+ ApiResultService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: ApiResultService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
300
+ ApiResultService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: ApiResultService });
301
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: ApiResultService, decorators: [{
302
+ type: Injectable
303
+ }] });
304
+ class ApiResult {
305
+ get message() {
306
+ return this._message;
307
+ }
308
+ get succeeded() {
309
+ return this._succeeded;
310
+ }
311
+ get started() {
312
+ return this._started;
313
+ }
314
+ get finished() {
315
+ return this._finished;
316
+ }
317
+ constructor(message, succeeded, started, finished) {
318
+ this._message = message;
319
+ this._succeeded = succeeded;
320
+ this._started = started;
321
+ this._finished = finished;
322
+ }
323
+ }
324
+
325
+ // tslint:disable:variable-name
326
+ class LoggingInterceptor {
327
+ set enabled(enabled) {
328
+ this._enabled = enabled;
329
+ if (this._enabled && this._outputToConsole) {
330
+ console.warn('API logging enabled but no provider found for ApiResultService. Results will be output to the console.');
331
+ }
332
+ }
333
+ constructor(apiResultService) {
334
+ this.apiResultService = apiResultService;
335
+ this._enabled = false;
336
+ this._outputToConsole = !this.apiResultService;
337
+ }
338
+ intercept(req, next) {
339
+ if (!this._enabled) {
340
+ return next.handle(req);
341
+ }
342
+ const started = new Date();
343
+ let succeeded;
344
+ return next.handle(req)
345
+ .pipe(tap(event => succeeded = event instanceof HttpResponse ? true : false, error => succeeded = false), finalize(() => {
346
+ if (this._outputToConsole) {
347
+ console.log(`${req.method} ${req.urlWithParams} completed in ${Date.now() - started.getTime()} ms. Success: ${succeeded}`);
348
+ }
349
+ else {
350
+ this.apiResultService.add(new ApiResult(`${req.method} ${req.urlWithParams}`, succeeded, started, new Date()));
351
+ }
352
+ }));
353
+ }
354
+ }
355
+ LoggingInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: LoggingInterceptor, deps: [{ token: ApiResultService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
356
+ LoggingInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: LoggingInterceptor });
357
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: LoggingInterceptor, decorators: [{
358
+ type: Injectable
359
+ }], ctorParameters: function () {
360
+ return [{ type: ApiResultService, decorators: [{
361
+ type: Optional
362
+ }] }];
363
+ } });
364
+
365
+ /**
366
+ * HTTP Headers
367
+ */
368
+ const HTTP_HEADERS = Object.freeze({
369
+ Authorization: 'Authorization',
370
+ etag: 'etag',
371
+ // Angular is dealing with case sensitive links despite the specification
372
+ // https://github.com/angular/angular/issues/6142
373
+ link: 'link',
374
+ Link: 'Link',
375
+ x_vcloud_authorization: 'x-vcloud-authorization'
376
+ });
377
+
378
+ // tslint:disable:variable-name
379
+ class RequestHeadersInterceptor {
380
+ constructor() {
381
+ this._enabled = true;
382
+ this._version = '';
383
+ this._authenticationHeader = HTTP_HEADERS.Authorization;
384
+ }
385
+ set enabled(_enabled) {
386
+ this._enabled = _enabled;
387
+ }
388
+ set actAs(_actAs) {
389
+ this._actAs = _actAs;
390
+ }
391
+ get version() {
392
+ return this._version;
393
+ }
394
+ set version(_version) {
395
+ this._version = _version;
396
+ }
397
+ set authentication(_authentication) {
398
+ this._authentication = _authentication;
399
+ this._authenticationHeader = (this._authentication && this._authentication.length > 32) ?
400
+ HTTP_HEADERS.Authorization : HTTP_HEADERS.x_vcloud_authorization;
401
+ }
402
+ intercept(req, next) {
403
+ let headers = req.headers;
404
+ if (!headers.has('Accept')) {
405
+ headers = this.setAcceptHeader(headers);
406
+ }
407
+ if (!headers.has('Content-Type')) {
408
+ headers = this.setContentTypeHeader(headers, req.url);
409
+ }
410
+ if (this._authentication && !headers.has(HTTP_HEADERS.Authorization)) {
411
+ headers = headers.set(this._authenticationHeader, this._authentication);
412
+ }
413
+ /**
414
+ * Covers the case where the User set the ActAs token himself
415
+ */
416
+ if (!headers.has('X-VMWARE-VCLOUD-TENANT-CONTEXT') && this._actAs) {
417
+ headers = headers.set('X-VMWARE-VCLOUD-TENANT-CONTEXT', this._actAs);
418
+ }
419
+ const customReq = req.clone({
420
+ headers
421
+ });
422
+ return next.handle(customReq).pipe(map((res) => {
423
+ if (res instanceof HttpResponse) {
424
+ if (!res.body || !res.headers) {
425
+ return res;
426
+ }
427
+ if (res.headers.has(HTTP_HEADERS.link)) {
428
+ res.body.link = parseHeaderHateoasLinks(res.headers.get(HTTP_HEADERS.link));
429
+ }
430
+ if (res.headers.has(HTTP_HEADERS.Link)) {
431
+ res.body.link = parseHeaderHateoasLinks(res.headers.get(HTTP_HEADERS.Link));
432
+ }
433
+ if (res.headers.has(HTTP_HEADERS.etag)) {
434
+ res.body.etag = res.headers.get(HTTP_HEADERS.etag);
435
+ }
436
+ }
437
+ return res;
438
+ }));
439
+ }
440
+ setAcceptHeader(headers) {
441
+ const value = headers.get('_multisite');
442
+ headers = headers.delete('_multisite');
443
+ return headers.set('Accept', [
444
+ `application/*+json;version=${this._version}${value ? `;multisite=${value}` : ''}`,
445
+ `application/json;version=${this._version}${value ? `;multisite=${value}` : ''}`
446
+ ]);
447
+ }
448
+ setContentTypeHeader(headers, url) {
449
+ if (url.indexOf('cloudapi') > -1) {
450
+ return headers.set('Content-Type', 'application/json');
451
+ }
452
+ else {
453
+ return headers.set('Content-Type', 'application/*+json');
454
+ }
455
+ }
456
+ }
457
+ RequestHeadersInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: RequestHeadersInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
458
+ RequestHeadersInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: RequestHeadersInterceptor });
459
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: RequestHeadersInterceptor, decorators: [{
460
+ type: Injectable
461
+ }] });
462
+
463
+ // tslint:disable:jsdoc-format
464
+ /**
465
+ * An interceptor on the response chain that normalizes differences in
466
+ * JSON payloads between vCloud Director version 9.1 and versions
467
+ * greater than 9.1.
468
+ *
469
+ * In 9.1 (API version 30.0) the server serializes JSON and nests the payload in a value field:
470
+ * ```
471
+ {
472
+ "name" : "{http://www.vmware.com/vcloud/versions}SupportedVersions",
473
+ "declaredType" : "com.vmware.vcloud.api.rest.schema.versioning.SupportedVersionsType",
474
+ "scope" : "javax.xml.bind.JAXBElement$GlobalScope",
475
+ "value" : {
476
+ "versionInfo" : [],
477
+ "any" : [],
478
+ "otherAttributes" : {}
479
+ }
480
+ }
481
+ ```
482
+ *
483
+ * That same request in API versions 31.0 and above is represented as:
484
+ * ```
485
+ {
486
+ "versionInfo" : [],
487
+ "any" : [],
488
+ "otherAttributes" : {}
489
+ }
490
+ ```
491
+ * This interceptor should process responses before any other interceptors that rely
492
+ * on consistent API information.
493
+ */
494
+ class ResponseNormalizationInterceptor {
495
+ intercept(req, next) {
496
+ return next.handle(req).pipe(map(response => {
497
+ // While this condition seems awfully specific, the alternative option of examining the 'Content-Type'
498
+ // response header for 'version=30.0' proved to be an unreliable condition in at least one case;
499
+ // returning the same JSON payload as API versions >= 31.0.
500
+ if (response instanceof HttpResponse && response.body && response.body.value && response.body.declaredType && response.body.scope) {
501
+ const body = response.body.value;
502
+ if (response.body.declaredType === ResponseNormalizationInterceptor.QUERY_RESULT_TYPE) {
503
+ body.record = body.record.map(record => record.value);
504
+ }
505
+ return response.clone({ body });
506
+ }
507
+ return response;
508
+ }));
509
+ }
510
+ }
511
+ ResponseNormalizationInterceptor.QUERY_RESULT_TYPE = 'com.vmware.vcloud.api.rest.schema_v1_5.QueryResultRecordsType';
512
+ ResponseNormalizationInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: ResponseNormalizationInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
513
+ ResponseNormalizationInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: ResponseNormalizationInterceptor });
514
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: ResponseNormalizationInterceptor, decorators: [{
515
+ type: Injectable
516
+ }] });
517
+
518
+ /**
519
+ * Angular's HttpInterceptorHandler is not publicly exposed. This is a clone of it.
520
+ */
521
+ class VcdHttpInterceptorHandler {
522
+ constructor(next, interceptor) {
523
+ this.next = next;
524
+ this.interceptor = interceptor;
525
+ }
526
+ handle(req) {
527
+ return this.interceptor.intercept(req, this.next);
528
+ }
529
+ }
530
+ /**
531
+ * This is a specialist subclass of HttpClient. The HttpClient that is defined/imported
532
+ * by HttpClientModule is a singleton from the container, meaning that all extensions would
533
+ * get the same one. We sub-class it so that each extension gets their own instance.
534
+ * Extension consumers should inject this.
535
+ * @see HttpClient
536
+ */
537
+ class VcdHttpClient extends HttpClient {
538
+ /**
539
+ * Create an HttpClient with the logging and header interceptors in the chain.
540
+ * @param httpBackend backend (likely injected from HttpClientModule)
541
+ * @param hateoasHeaderInterceptor the hateoas header interceptor
542
+ * @param loggingInterceptor the logging interceptor
543
+ * @param requestHeadersInterceptor the request header interceptor
544
+ */
545
+ constructor(httpBackend, loggingInterceptor, requestHeadersInterceptor, responseNormalizationInterceptor) {
546
+ const interceptors = [
547
+ loggingInterceptor,
548
+ requestHeadersInterceptor,
549
+ responseNormalizationInterceptor
550
+ ];
551
+ const chain = interceptors.reduceRight((next, interceptor) => new VcdHttpInterceptorHandler(next, interceptor), httpBackend);
552
+ super(chain);
553
+ this.loggingInterceptor = loggingInterceptor;
554
+ this.requestHeadersInterceptor = requestHeadersInterceptor;
555
+ }
556
+ }
557
+ VcdHttpClient.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdHttpClient, deps: [{ token: i1.HttpBackend }, { token: LoggingInterceptor }, { token: RequestHeadersInterceptor }, { token: ResponseNormalizationInterceptor }], target: i0.ɵɵFactoryTarget.Injectable });
558
+ VcdHttpClient.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdHttpClient });
559
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdHttpClient, decorators: [{
560
+ type: Injectable
561
+ }], ctorParameters: function () { return [{ type: i1.HttpBackend }, { type: LoggingInterceptor }, { type: RequestHeadersInterceptor }, { type: ResponseNormalizationInterceptor }]; } });
562
+
563
+ /**
564
+ * This is the currently supported - albeit very minimal - public SDK.
565
+ */
566
+ // Bind straight into the hooks provided by the container.
567
+ if (!window.System || !window.System.registry || !window.System.registry.get) {
568
+ throw new Error('SystemJS registry not found');
569
+ }
570
+ let containerHooks$1 = window.System.registry.get('@vcd/common');
571
+ if (!containerHooks$1) {
572
+ containerHooks$1 = window.System.registry.get('@vcd-ui/common');
573
+ }
574
+ if (!containerHooks$1) {
575
+ throw new Error('VCD UI container hooks not present in SystemJS registry');
576
+ }
577
+ /**
578
+ * Wire in as a string. Gives the root URL for API access (for example, the load balancer URL
579
+ * or the single-cell URL).
580
+ */
581
+ const API_ROOT_URL$1 = containerHooks$1.API_ROOT_URL;
582
+ /**
583
+ * Wire in as a string. Gives the root URL for the legacy Flex application.
584
+ */
585
+ const FLEX_APP_URL$1 = containerHooks$1.API_ROOT_URL;
586
+ /**
587
+ * Wire in as a string. Gives the current scope of the VCD-UI. As of current, this will be
588
+ * either 'tenant' for the tenant portal, or 'service-provider' for the service-provider portal.
589
+ */
590
+ const SESSION_SCOPE$1 = containerHooks$1.SESSION_SCOPE;
591
+ /**
592
+ * Wire in as a string. Gives the unique name (not the display name) of the current tenant
593
+ * organization that the VCD-UI is being used for.
594
+ */
595
+ const SESSION_ORGANIZATION$1 = containerHooks$1.SESSION_ORGANIZATION;
596
+ /**
597
+ * Wire in as a string. Gives the UUID identifier of the current tenant
598
+ * organization that the VCD-UI is being used for.
599
+ */
600
+ const SESSION_ORG_ID$1 = containerHooks$1.SESSION_ORG_ID ? containerHooks$1.SESSION_ORG_ID : '';
601
+ /**
602
+ * Wire in as a string. Gives the full root path for module assets (e.g. images, scripts, text files)
603
+ *
604
+ * ATTENTION!
605
+ * Add || new InjectionToken to workaround the Angular security mechanics which prevent use of injection tokens
606
+ * which potentially are not defiend. The same fix can be applied for the rest tokens if needed.
607
+ */
608
+ const EXTENSION_ASSET_URL$1 = containerHooks$1.EXTENSION_ASSET_URL || new InjectionToken('EXTENSION_ASSET_URL');
609
+ /**
610
+ * Wire in as a string. Gives the Angular 2 route that the module is registered under.
611
+ */
612
+ const EXTENSION_ROUTE$1 = containerHooks$1.EXTENSION_ROUTE;
613
+ /**
614
+ * Wire in as a boolean. True if running under the SDK, false if running in production.
615
+ */
616
+ const SDK_MODE$1 = containerHooks$1.SDK_MODE;
617
+ const AuthTokenHolderService$1 = containerHooks$1.AuthTokenHolderService;
618
+
619
+ /**
620
+ * Default chunk size is 50MiB. This is equal to the chunk size the VCD UI uses for library uploads.
621
+ */
622
+ const MAX_CHUNK_SIZE = 50 * 1024 * 1024;
623
+ /**
624
+ * How many times to retry a chunk upload.
625
+ */
626
+ const MAX_CHUNK_RETRY_COUNT = 5;
627
+ /**
628
+ * A special error thrown by the transfer client. It gives access to the causing error, and the final progress
629
+ * before the error occurred.
630
+ */
631
+ class TransferError extends Error {
632
+ constructor(message, originalError, lastProgress) {
633
+ super(message);
634
+ this.originalError = originalError;
635
+ this.lastProgress = lastProgress;
636
+ }
637
+ }
638
+ /**
639
+ * This is used to upload files to a VCD API transfer URL. It is not suggested to create this class - instead
640
+ * use the startTransfer method in VcdApiClient.
641
+ */
642
+ class VcdTransferClient {
643
+ /**
644
+ * Create a transfer client.
645
+ * @param httpClient the http client to be used
646
+ * @param transferUrl the URL to upload to
647
+ */
648
+ constructor(httpClient, transferUrl, maxChunkSize = MAX_CHUNK_SIZE, maxChunkRetryCount = MAX_CHUNK_RETRY_COUNT) {
649
+ this.httpClient = httpClient;
650
+ this.transferUrl = transferUrl;
651
+ this.maxChunkSize = maxChunkSize;
652
+ this.maxChunkRetryCount = maxChunkRetryCount;
653
+ }
654
+ /**
655
+ * Upload data, optionally listening for progress updates.
656
+ * @param source what to upload.
657
+ * @param progressObserver (optional) this will get progress notifications during the upload
658
+ * @returns fetails of the finished upload.
659
+ * @throws TransferError when a chunk upload fails.
660
+ */
661
+ upload(source, progressObserver) {
662
+ // Cache the client and url so they don't change from under us.
663
+ const { httpClient, transferUrl, maxChunkSize, maxChunkRetryCount } = this;
664
+ // Compute static information used through the upload.
665
+ const filename = source.name || '<blob>';
666
+ const totalChunks = Math.ceil(source.size / maxChunkSize);
667
+ const totalBytes = source.size;
668
+ const startTimeMs = new Date().getTime();
669
+ let retryCount = 0;
670
+ // This helper function creates a TransferProgress object for sending to the progressObserver.
671
+ // It relies on the above static information, hence being nested.
672
+ function createTransferProgress(retryNumber, rtryCount, chunksSent) {
673
+ const chunksRemaining = totalChunks - chunksSent;
674
+ const bytesSent = Math.min(chunksSent * maxChunkSize, totalBytes);
675
+ const bytesRemaining = totalBytes - bytesSent;
676
+ const percent = bytesSent / totalBytes * 100;
677
+ const timeTakenMs = new Date().getTime() - startTimeMs;
678
+ const estimatedTotalTimeMs = (bytesSent / bytesRemaining) * timeTakenMs;
679
+ const estimatedTimeRemainingMs = Math.max(estimatedTotalTimeMs - timeTakenMs, 0);
680
+ return {
681
+ filename, transferUrl, retryNumber, retryCount: rtryCount,
682
+ chunksSent, chunksRemaining, bytesSent, bytesRemaining,
683
+ percent, timeTakenMs, estimatedTimeRemainingMs
684
+ };
685
+ }
686
+ // This is the main chunk upload function
687
+ function transferChunk(chunkIndex) {
688
+ // Calculate chunk details.
689
+ const chunkStart = chunkIndex * maxChunkSize;
690
+ const chunkEnd = Math.min(chunkStart + maxChunkSize, totalBytes);
691
+ const contentRangeHeader = `bytes ${chunkStart}-${chunkEnd - 1}/${totalBytes}`;
692
+ // Dispatch progress
693
+ if (progressObserver) {
694
+ const progress = createTransferProgress(0, retryCount, chunkIndex);
695
+ progressObserver.next(progress);
696
+ }
697
+ // Read in the chunk
698
+ return Observable.create(observer => {
699
+ const chunkSlice = source.slice(chunkStart, chunkEnd);
700
+ const fileReader = new FileReader();
701
+ fileReader.onerror = err => {
702
+ observer.error(err);
703
+ };
704
+ fileReader.onabort = err => {
705
+ observer.error(err);
706
+ };
707
+ fileReader.onload = () => {
708
+ };
709
+ fileReader.onloadend = () => {
710
+ observer.next(fileReader.result);
711
+ observer.complete();
712
+ };
713
+ return fileReader.readAsArrayBuffer(chunkSlice);
714
+ // Transfer the chunk
715
+ }).pipe(
716
+ // Upon read error, abort the upload process. No point retrying read failures.
717
+ catchError((e) => {
718
+ // Abandon the upload and propagate a consumable error.
719
+ const progress = createTransferProgress(0, retryCount, chunkIndex);
720
+ return throwError(() => new TransferError('Read error', e, progress));
721
+ }),
722
+ // Upon successful read, transfer the chunk.
723
+ switchMap((data) => {
724
+ let retryNumber = 0;
725
+ return httpClient.put(transferUrl, data, {
726
+ headers: new HttpHeaders({
727
+ 'Content-Range': contentRangeHeader
728
+ }),
729
+ responseType: 'text'
730
+ }).pipe(
731
+ // This is called upon any chunk upload failure.
732
+ catchError((e) => {
733
+ // Increase the total retry count.
734
+ retryCount++;
735
+ // Increase the current chunk retry number.
736
+ retryNumber++;
737
+ // Dispatch progress (the retry information has changed).
738
+ if (progressObserver) {
739
+ const progress = createTransferProgress(retryNumber, retryCount, chunkIndex);
740
+ progressObserver.next(progress);
741
+ }
742
+ // Rethrow the error so that the "retry" call handles it.
743
+ return throwError(() => e);
744
+ }),
745
+ // Retry the chunk upload up to the limit - this will run the entire chain again.
746
+ retry(maxChunkRetryCount),
747
+ // This is called when all retries for the chunk are exhausted.
748
+ catchError((e) => {
749
+ // Abandon the upload and propagate a consumable error.
750
+ const progress = createTransferProgress(retryNumber, retryCount, chunkIndex);
751
+ return throwError(() => new TransferError('Transfer error', e, progress));
752
+ }));
753
+ }));
754
+ }
755
+ // This creates the final transfer progress, dispatches it, and returns the transfer result.
756
+ function finishUpload() {
757
+ const transferProgress = createTransferProgress(0, retryCount, totalChunks);
758
+ if (progressObserver) {
759
+ progressObserver.next(transferProgress);
760
+ progressObserver.complete();
761
+ }
762
+ const transferResult = {
763
+ filename: transferProgress.filename,
764
+ transferUrl: transferProgress.transferUrl,
765
+ retryCount: transferProgress.retryCount,
766
+ chunksSent: transferProgress.chunksSent,
767
+ bytesSent: transferProgress.bytesSent,
768
+ timeTakenMs: transferProgress.timeTakenMs
769
+ };
770
+ return transferResult;
771
+ }
772
+ // Upload all of the chunks
773
+ let chain = transferChunk(0);
774
+ for (let currentChunk = 1; currentChunk < totalChunks; currentChunk++) {
775
+ chain = chain.pipe(flatMap(() => transferChunk(currentChunk)));
776
+ }
777
+ // Finish transfer
778
+ return chain.pipe(map(finishUpload));
779
+ }
780
+ }
781
+
782
+ /**
783
+ * This is the currently supported - albeit very minimal - public SDK.
784
+ */
785
+ // Bind straight into the hooks provided by the container.
786
+ if (!window.System || !window.System.registry || !window.System.registry.get) {
787
+ throw new Error('SystemJS registry not found');
788
+ }
789
+ let containerHooks = window.System.registry.get('@vcd/common');
790
+ if (!containerHooks) {
791
+ containerHooks = window.System.registry.get('@vcd-ui/common');
792
+ }
793
+ if (!containerHooks) {
794
+ throw new Error('VCD UI container hooks not present in SystemJS registry');
795
+ }
796
+ /**
797
+ * Wire in as a string. Gives the root URL for API access (for example, the load balancer URL
798
+ * or the single-cell URL).
799
+ */
800
+ const API_ROOT_URL = containerHooks.API_ROOT_URL;
801
+ /**
802
+ * Wire in as a string. Gives the root URL for the legacy Flex application.
803
+ */
804
+ const FLEX_APP_URL = containerHooks.API_ROOT_URL;
805
+ /**
806
+ * Wire in as a string. Gives the current scope of the VCD-UI. As of current, this will be
807
+ * either 'tenant' for the tenant portal, or 'service-provider' for the service-provider portal.
808
+ */
809
+ const SESSION_SCOPE = containerHooks.SESSION_SCOPE;
810
+ /**
811
+ * Wire in as a string. Gives the unique name (not the display name) of the current tenant
812
+ * organization that the VCD-UI is being used for.
813
+ */
814
+ const SESSION_ORGANIZATION = containerHooks.SESSION_ORGANIZATION;
815
+ /**
816
+ * Wire in as a string. Gives the UUID identifier of the current tenant
817
+ * organization that the VCD-UI is being used for.
818
+ */
819
+ const SESSION_ORG_ID = containerHooks.SESSION_ORG_ID ? containerHooks.SESSION_ORG_ID : '';
820
+ /**
821
+ * Wire in as a string. Gives the full root path for module assets (e.g. images, scripts, text files)
822
+ *
823
+ * ATTENTION!
824
+ * Add || new InjectionToken to workaround the Angular security mechanics which prevent use of injection tokens
825
+ * which potentially are not defiend. The same fix can be applied for the rest tokens if needed.
826
+ */
827
+ const EXTENSION_ASSET_URL = containerHooks.EXTENSION_ASSET_URL || new InjectionToken('EXTENSION_ASSET_URL');
828
+ /**
829
+ * Wire in as a string. Gives the Angular 2 route that the module is registered under.
830
+ */
831
+ const EXTENSION_ROUTE = containerHooks.EXTENSION_ROUTE;
832
+ /**
833
+ * Wire in as a boolean. True if running under the SDK, false if running in production.
834
+ */
835
+ const SDK_MODE = containerHooks.SDK_MODE;
836
+ const ExtensionNavRegistrationAction = containerHooks.ExtensionNavRegistrationAction;
837
+ const AuthTokenHolderService = containerHooks.AuthTokenHolderService;
838
+ /**
839
+ * Every component referenced by an entity action extension point must inherit from this.
840
+ */
841
+ // tslint:disable-next-line:class-name
842
+ class _EntityActionExtensionComponent {
843
+ }
844
+ const EntityActionExtensionComponent = containerHooks.EntityActionExtensionComponent;
845
+ // tslint:disable-next-line:class-name
846
+ class _WizardExtensionComponent {
847
+ }
848
+ const WizardExtensionComponent = containerHooks.WizardExtensionComponent;
849
+ // tslint:disable-next-line:class-name
850
+ class _WizardExtensionWithValidationComponent extends _WizardExtensionComponent {
851
+ }
852
+ // tslint:disable-next-line:max-line-length
853
+ const WizardExtensionWithValidationComponent = containerHooks.WizardExtensionWithValidationComponent;
854
+
855
+ class PluginModule {
856
+ constructor(appStore) {
857
+ this.appStore = appStore;
858
+ }
859
+ registerExtension(extension) {
860
+ this.appStore.dispatch(new ExtensionNavRegistrationAction(extension));
861
+ }
862
+ }
863
+ /**
864
+ * Config object that is passed on VcdSdkModule init
865
+ * using .forRoot() method. It can be used to store
866
+ * configutration properties that are later used by the Services
867
+ * provided.
868
+ */
869
+ class VcdSdkConfig {
870
+ }
871
+
872
+ const TRANSFER_LINK_REL = 'upload:default';
873
+ const HATEOAS_HEADER = 'Link';
874
+ // tslint:disable:variable-name
875
+ /**
876
+ * Parse out Link headers using a very lazily implemented pull parser
877
+ * @param header '<url1>;name1="value1",name2="value2",<url2>;name3="value3,value4"'
878
+ * @returns parsed link headers
879
+ */
880
+ function parseHeaderHateoasLinks(header) {
881
+ const results = [];
882
+ if (!header) {
883
+ return results;
884
+ }
885
+ const headerFieldMappings = {
886
+ href: 'href',
887
+ model: 'type',
888
+ title: 'id',
889
+ rel: 'rel'
890
+ };
891
+ let tokenIndex = -1;
892
+ function peek(token) {
893
+ return header.indexOf(token, tokenIndex + 1);
894
+ }
895
+ function next(token) {
896
+ const nextIndex = peek(token);
897
+ if (nextIndex === -1) {
898
+ throw new Error(JSON.stringify({ header, token, tokenIndex }));
899
+ }
900
+ tokenIndex = nextIndex;
901
+ return tokenIndex;
902
+ }
903
+ while (peek('<') > -1) {
904
+ try {
905
+ const hrefStart = next('<');
906
+ const hrefEnd = next('>');
907
+ const href = header.substring(hrefStart + 1, hrefEnd);
908
+ const result = { href, type: null, id: null, rel: null, vCloudExtension: [] };
909
+ let comma = peek(',');
910
+ let semicolon = peek(';');
911
+ while ((semicolon > -1 && comma > -1 && semicolon < comma) || (semicolon > -1 && comma === -1)) {
912
+ const nameStart = next(';');
913
+ const nameEnd = next('=');
914
+ const name = header.substring(nameStart + 1, nameEnd).trim().toLowerCase();
915
+ const valueStart = next('"');
916
+ const valueEnd = next('"');
917
+ const value = header.substring(valueStart + 1, valueEnd);
918
+ const mappedName = headerFieldMappings[name];
919
+ if (mappedName) {
920
+ // @ts-ignore
921
+ result[mappedName] = decodeURIComponent(value);
922
+ }
923
+ comma = peek(',');
924
+ semicolon = peek(';');
925
+ }
926
+ results.push(result);
927
+ }
928
+ catch (error) { // We will try the next one...
929
+ console.log(error);
930
+ }
931
+ }
932
+ return results;
933
+ }
934
+ var LinkRelType;
935
+ (function (LinkRelType) {
936
+ LinkRelType["add"] = "add";
937
+ LinkRelType["remove"] = "remove";
938
+ LinkRelType["edit"] = "edit";
939
+ })(LinkRelType || (LinkRelType = {}));
940
+ /**
941
+ * A basic client for interacting with the VMware Cloud Director APIs.
942
+ *
943
+ * A VMware Cloud Director plugin can get a reference to this client by using angular injection.
944
+ * ```
945
+ * constructor(private vcdApi: VcdApiClient) {}
946
+ * ```
947
+ *
948
+ * VcdApiClient reuses the authentication from the VCD platform so in general there is
949
+ * no need of an explicit authentication/login.
950
+ *
951
+ * When dealing with the session management there are two APIs:
952
+ * 1. Deprecated legacy API that is using the `api/session` endpoint and the corresponding models
953
+ * 2. Newly added API that is using the `cloudapi` endpoint and the corresponding models
954
+ *
955
+ * Note that if a plugin performs an explicit cloud api authentication call through
956
+ * {@link VcdApiClient#setCloudApiAuthentication} or {@link VcdApiClient#cloudApiLogin}
957
+ * from that moment on the VcdApiClient uses only cloud api session management.
958
+ * This means calls to {@link VcdApiClient#setAuthentication} or {@link VcdApiClient#login} have no effect.
959
+ */
960
+ class VcdApiClient {
961
+ set baseUrl(_baseUrl) {
962
+ this._baseUrl = _baseUrl;
963
+ }
964
+ get version() {
965
+ return this.http.requestHeadersInterceptor.version;
966
+ }
967
+ constructor(http, injector, config) {
968
+ var _a;
969
+ this.http = http;
970
+ this.injector = injector;
971
+ this.config = config;
972
+ /**
973
+ * @deprecated Use {@link VcdApiClient#_cloudApiSession}
974
+ */
975
+ this._session = new BehaviorSubject(null);
976
+ this._sessionObservable = this._session.asObservable()
977
+ .pipe(skipWhile(session => !session));
978
+ /**
979
+ * CloudApi Session
980
+ */
981
+ this._cloudApiSession = new BehaviorSubject(null);
982
+ this._cloudApiSessionObservable = this._cloudApiSession.asObservable()
983
+ .pipe(skipWhile(session => !session));
984
+ this._cloudApiSessionLinks = new BehaviorSubject([]);
985
+ /**
986
+ * This property determines if it is an explicit cloud api login.
987
+ * In this case the old API (/api/session) should not be used at all.
988
+ */
989
+ this._isCloudApiLogin = false;
990
+ this._baseUrl = this.injector.get(API_ROOT_URL$1);
991
+ let negotiatedVersion;
992
+ if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.apiVersion) {
993
+ negotiatedVersion = of(this.config.apiVersion).pipe(map((version) => {
994
+ this.setVersion(version);
995
+ return version;
996
+ }));
997
+ }
998
+ else {
999
+ negotiatedVersion = this.http.get(`${this._baseUrl}/api/versions`).pipe(map(versions => this.negotiateVersion(versions)), tap(version => this.setVersion(version)));
1000
+ }
1001
+ this._negotiateVersion = negotiatedVersion.pipe(share({ connector: () => new ReplaySubject(1) }));
1002
+ const tokenHolder = this.injector.get(AuthTokenHolderService$1, { token: '' });
1003
+ const token = tokenHolder.jwt ? `Bearer ${tokenHolder.jwt}` : tokenHolder.token;
1004
+ this._getSession = this.setAuthentication(token)
1005
+ .pipe(share({ connector: () => new ReplaySubject(1) }));
1006
+ this._getCloudApiSession = this.setCloudApiAuthentication(token)
1007
+ .pipe(share({ connector: () => new ReplaySubject(1) }));
1008
+ // This is not an explicit cloud api login
1009
+ this._isCloudApiLogin = false;
1010
+ }
1011
+ negotiateVersion(serverVersions) {
1012
+ const supportedVersions = serverVersions.versionInfo.map(versionInfo => versionInfo.version);
1013
+ // Default API Version used is the Latest API Version in VMware Cloud Director
1014
+ return supportedVersions[supportedVersions.length - 1];
1015
+ }
1016
+ /**
1017
+ * The purpose of this function is to ensure that prior to sending any call to the backend
1018
+ * the version has been set and the current session has been retrieved.
1019
+ * Note that this is important during the automatic authentication that is done during the
1020
+ * constructor initialization, when the plugin is not required to perform its own explicit authentication
1021
+ * but rather the ones from the underlying framework is used.
1022
+ */
1023
+ validateRequestContext() {
1024
+ return (this.version ? of(this.version) : this._negotiateVersion)
1025
+ .pipe(
1026
+ // In case of a cloud api login we are not interested in the /api/session session
1027
+ concatMap(() => this._isCloudApiLogin ? of(null) : this._getSession), concatMap(() => this._getCloudApiSession
1028
+ // In case of cloud api failure we do not want to prevent further execution
1029
+ // for backward compatibility considerations since this may be a case
1030
+ // when cloud api is not supported at all for the specified version
1031
+ .pipe(catchError((e) => of(true)))), map(() => true));
1032
+ }
1033
+ /**
1034
+ *
1035
+ * For use cases wich solely depends on cloudapi without any backward compatibility
1036
+ * there should be no dependence on the old /api endpoint at all
1037
+ */
1038
+ validateRequestContextCloudApiOnly() {
1039
+ return (this.version ? of(this.version) : this._negotiateVersion).pipe(concatMap(() => this._getCloudApiSession));
1040
+ }
1041
+ setVersion(_version) {
1042
+ this.http.requestHeadersInterceptor.version = _version;
1043
+ return this;
1044
+ }
1045
+ /**
1046
+ * Global configuration for the service, that allows a provider user to execute API requests
1047
+ * in the scope of a specific tenant.
1048
+ *
1049
+ * If you want to execute single API request in scope of specific tenant you can do it
1050
+ * by passing "X-VMWARE-VCLOUD-TENANT-CONTEXT" header to the specific API Request.
1051
+ *
1052
+ * This scoping is available to query-based API calls and to bulk GET calls in the
1053
+ * /cloudapi space.
1054
+ *
1055
+ * @param actAs an entityRef of the tenant (organization) to scope subsequent calls to in
1056
+ * the VcdApiClient, or null/no parameter to remove tenant-specific scoping
1057
+ * @returns the current VcdApiClient instance (for chaining)
1058
+ */
1059
+ actAs(actAs = null) {
1060
+ this.http.requestHeadersInterceptor.actAs = !actAs ? null : actAs.id;
1061
+ return this;
1062
+ }
1063
+ /**
1064
+ * @deprecated Use {@link VcdApiClient#setCloudApiAuthentication}
1065
+ *
1066
+ * Sets the authentication token to use for the VcdApiClient.
1067
+ *
1068
+ * After setting the token, the client will get the current session
1069
+ * information associated with the authenticated token.
1070
+ *
1071
+ * @param authentication the authentication string (to be used in either the 'Authorization'
1072
+ * or 'x-vcloud-authorization' header)
1073
+ * @returns the session associated with the authentication token
1074
+ */
1075
+ setAuthentication(authentication) {
1076
+ if (this._isCloudApiLogin) {
1077
+ return throwError('Only cloud api auth is allowed since it was already used');
1078
+ }
1079
+ this.http.requestHeadersInterceptor.authentication = authentication;
1080
+ return this.http.get(`${this._baseUrl}/api/session`).pipe(tap(session => {
1081
+ // automatically set actAs for provider in tenant scope
1082
+ if (session.org === 'System' && this.injector.get(SESSION_SCOPE$1) === 'tenant') {
1083
+ // Automatic actAs only works in versions >=9.5
1084
+ try {
1085
+ this.actAs({ id: this.injector.get(SESSION_ORG_ID$1) });
1086
+ }
1087
+ catch (e) {
1088
+ console.warn('No SESSION_ORG_ID set in container. Automatic actAs is disabled.');
1089
+ }
1090
+ }
1091
+ }), tap(session => this._session.next(session)));
1092
+ }
1093
+ /**
1094
+ * Sets the authentication token to use for the VcdApiClient.
1095
+ *
1096
+ * After setting the token, the client will get the current session
1097
+ * information associated with the authenticated token.
1098
+ *
1099
+ * @param authentication the authentication string (to be used in either the 'Authorization'
1100
+ * or 'x-vcloud-authorization' header)
1101
+ *
1102
+ * @returns session observable associated with the authentication token
1103
+ */
1104
+ setCloudApiAuthentication(authentication) {
1105
+ this.onBeforeCloudApiAuthentication();
1106
+ return of(true)
1107
+ .pipe(
1108
+ // Set the authentication as part of the observable in order to ensure the caller has subscribed to the observable
1109
+ tap(() => this.http.requestHeadersInterceptor.authentication = authentication), switchMap(() => this.http.get(`${this._baseUrl}/cloudapi/1.0.0/sessions/current`, { observe: 'response' })))
1110
+ .pipe(this.onCloudApiAuthentication());
1111
+ }
1112
+ enableLogging() {
1113
+ this.http.loggingInterceptor.enabled = true;
1114
+ return this;
1115
+ }
1116
+ /**
1117
+ * @deprecated Use {@link VcdApiClient#cloudApiLogin}
1118
+ *
1119
+ * Creates an authenticated session for the specified credential data.
1120
+ *
1121
+ * @param username the name of the user to authenticate
1122
+ * @param tenant the organization the user belongs to
1123
+ * @param password the password for the user
1124
+ * @returns an authenticated session for the given credentials
1125
+ */
1126
+ login(username, tenant, password) {
1127
+ if (this._isCloudApiLogin) {
1128
+ return throwError('Only cloud api auth is allowed since it was already used');
1129
+ }
1130
+ const authString = btoa(`${username}@${tenant}:${password}`);
1131
+ return this.http.post(`${this._baseUrl}/api/sessions`, null, {
1132
+ observe: 'response',
1133
+ headers: new HttpHeaders({ Authorization: `Basic ${authString}` })
1134
+ })
1135
+ .pipe(tap((response) =>
1136
+ // tslint:disable-next-line:max-line-length
1137
+ this.http.requestHeadersInterceptor.authentication = `${response.headers.get('x-vmware-vcloud-token-type')} ${response.headers.get('x-vmware-vcloud-access-token')}`), map(response => response.body), tap(session => this._session.next(session)));
1138
+ }
1139
+ /**
1140
+ * Creates an authenticated session for the specified credential data using cloud api endpoint.
1141
+ *
1142
+ * @param username the name of the user to authenticate
1143
+ * @param tenant the organization the user belongs to
1144
+ * @param password the password for the user
1145
+ * @returns an authenticated session for the given credentials
1146
+ */
1147
+ cloudApiLogin(username, tenant, password) {
1148
+ this.onBeforeCloudApiAuthentication();
1149
+ const authString = btoa(`${username}@${tenant}:${password}`);
1150
+ let url = `${this._baseUrl}/cloudapi/1.0.0/sessions`;
1151
+ if (tenant.toLowerCase() === 'system') {
1152
+ url += '/provider';
1153
+ }
1154
+ return this.http.post(url, null, {
1155
+ observe: 'response',
1156
+ headers: new HttpHeaders({ [HTTP_HEADERS.Authorization]: `Basic ${authString}` })
1157
+ }).pipe(tap((response) => {
1158
+ // tslint:disable-next-line:max-line-length
1159
+ const token = `${response.headers.get('x-vmware-vcloud-token-type')} ${response.headers.get('x-vmware-vcloud-access-token')}`;
1160
+ this.http.requestHeadersInterceptor.authentication = token;
1161
+ }), this.onCloudApiAuthentication());
1162
+ }
1163
+ /**
1164
+ * It is necessary to know if an explicit cloud api auth request was done.
1165
+ * This function handles this by setting the corresponding flags, properties etc.
1166
+ */
1167
+ onBeforeCloudApiAuthentication() {
1168
+ // In case of an explicit cloud api auth request:
1169
+ // Set the flag _isCloudApiLogin in order to know that explicit cloud api authentication is done
1170
+ // This will help us skip code related to the old api, i.e. we should not allow explicit mix of both the api-s
1171
+ this._isCloudApiLogin = true;
1172
+ // In case of an explicit cloud api auth request:
1173
+ // There is no need of _getCloudApiSession observable which is needed in the automatic login during the constructor initialization.
1174
+ // The explicit cloud api auth request will retrieve the session.
1175
+ this._getCloudApiSession = of(null);
1176
+ }
1177
+ /**
1178
+ * Handle authentication.
1179
+ * This includes getting HATEOAS links, setting the session, handling errors etc.
1180
+ */
1181
+ onCloudApiAuthentication() {
1182
+ return (source) => source.pipe(tap((resp) => {
1183
+ // Get HATEOAS links
1184
+ try {
1185
+ this.setCloudApiSessionLinks(parseHeaderHateoasLinks(resp.headers.get(HATEOAS_HEADER)));
1186
+ }
1187
+ catch (e) {
1188
+ console.log('Error when parsing session HATEOAS links:', e);
1189
+ }
1190
+ }), map(resp => resp.body), tap((session) => {
1191
+ // Clear previous actAs
1192
+ this.actAs(null);
1193
+ // automatically set actAs for provider in tenant scope
1194
+ if (session.org && session.org.name === 'System' && this.injector.get(SESSION_SCOPE$1) === 'tenant') {
1195
+ // Automatic actAs only works in versions >=9.5
1196
+ try {
1197
+ this.actAs({ id: this.injector.get(SESSION_ORG_ID$1) });
1198
+ }
1199
+ catch (e) {
1200
+ console.warn('No SESSION_ORG_ID set in container. Automatic actAs is disabled.');
1201
+ }
1202
+ }
1203
+ }), tap((session) => this._cloudApiSession.next(session)), catchError((e) => {
1204
+ this.onCloudApiAuthenticationError();
1205
+ return throwError(e);
1206
+ }));
1207
+ }
1208
+ onCloudApiAuthenticationError() {
1209
+ // Clear the authentication so that any subsequent backend calls are not authenticated
1210
+ this.http.requestHeadersInterceptor.authentication = '';
1211
+ // _getCloudApiSession is in the center of any backend call, nullify it in order not to prevent those calls
1212
+ // since it is easier to troubleshoot failing backend rather than no call
1213
+ this._getCloudApiSession = of(null);
1214
+ // Clear the links
1215
+ this._cloudApiSessionLinks.next([]);
1216
+ // Clear the session
1217
+ this._cloudApiSession.next(null);
1218
+ }
1219
+ setCloudApiSessionLinks(links) {
1220
+ this._cloudApiAccessibleLocations = null;
1221
+ this._cloudApiSessionLinks.next(links || []);
1222
+ }
1223
+ get(endpoint, options) {
1224
+ return this.validateRequestContext().pipe(concatMap(() => this.http.get(this.buildEndpointUrl(endpoint), Object.assign({}, options))));
1225
+ }
1226
+ list(endpoint, queryBuilder, multisite, options) {
1227
+ let url = this.buildEndpointUrl(endpoint);
1228
+ if (queryBuilder) {
1229
+ url = `${url}${queryBuilder.getCloudAPI()}`;
1230
+ }
1231
+ if (multisite) {
1232
+ if (!options) {
1233
+ return this.http.get(url, { headers: new HttpHeaders({ _multisite: this.parseMultisiteValue(multisite) }) });
1234
+ }
1235
+ else if (options === null || options === void 0 ? void 0 : options.headers) {
1236
+ options.headers.append("_multisite", this.parseMultisiteValue(multisite));
1237
+ return this.http.get(url, Object.assign({}, options));
1238
+ }
1239
+ }
1240
+ return this.validateRequestContext().pipe(concatMap(() => this.http.get(url, Object.assign({}, options))));
1241
+ }
1242
+ createSync(endpoint, item, options) {
1243
+ return this.validateRequestContext().pipe(concatMap(() => this.http.post(this.buildEndpointUrl(endpoint), item, Object.assign({}, options))));
1244
+ }
1245
+ createAsync(endpoint, item, options) {
1246
+ return this.validateRequestContext().pipe(concatMap(() => this.http.post(this.buildEndpointUrl(endpoint), item, Object.assign(Object.assign({}, options), { observe: 'response' }))), concatMap(response => this.mapResponseToTask(response, 'POST')));
1247
+ }
1248
+ getTransferLink(endpoint, item, transferRel = TRANSFER_LINK_REL) {
1249
+ return this.http
1250
+ .post(this.buildEndpointUrl(endpoint), item, { observe: 'response' })
1251
+ .pipe(map((res) => {
1252
+ const headerLinks = res.headers.has(HATEOAS_HEADER)
1253
+ ? parseHeaderHateoasLinks(res.headers.get(HATEOAS_HEADER))
1254
+ : [];
1255
+ const links = res.body ? (res.body.link || []) : [];
1256
+ const link = [...headerLinks, ...links]
1257
+ .find((l) => l.rel === transferRel);
1258
+ if (!link) {
1259
+ throw new Error(`Response from ${endpoint} did not contain a transfer link`);
1260
+ }
1261
+ return link.href;
1262
+ }));
1263
+ }
1264
+ startTransfer(endpoint, item, transferRel = TRANSFER_LINK_REL) {
1265
+ return this.getTransferLink(endpoint, item, transferRel)
1266
+ .pipe(map((transferUrl) => new VcdTransferClient(this.http, transferUrl)));
1267
+ }
1268
+ updateSync(endpoint, item, options) {
1269
+ return this.validateRequestContext().pipe(concatMap(() => this.http.put(this.buildEndpointUrl(endpoint), item, Object.assign({}, options))));
1270
+ }
1271
+ updateAsync(endpoint, item, options) {
1272
+ return this.validateRequestContext().pipe(concatMap(() => this.http.put(this.buildEndpointUrl(endpoint), item, Object.assign(Object.assign({}, options), { observe: 'response' }))), concatMap(response => this.mapResponseToTask(response, 'PUT')));
1273
+ }
1274
+ deleteSync(endpoint, options) {
1275
+ return this.validateRequestContext().pipe(concatMap(() => this.http.delete(this.buildEndpointUrl(endpoint), Object.assign({}, options))));
1276
+ }
1277
+ deleteAsync(endpoint, options) {
1278
+ return this.validateRequestContext().pipe(concatMap(() => this.http.delete(this.buildEndpointUrl(endpoint), Object.assign(Object.assign({}, options), { observe: 'response' }))), concatMap(response => this.mapResponseToTask(response, 'DELETE')));
1279
+ }
1280
+ mapResponseToTask(response, httpVerb) {
1281
+ if (response.headers.has('Location') && response.status === 202) {
1282
+ return this.http.get(response.headers.get('Location'));
1283
+ }
1284
+ else if (response.body && response.body.type.startsWith('application/vnd.vmware.vcloud.task+')) {
1285
+ const task = Object.assign(new TaskType(), response.body);
1286
+ return of(task);
1287
+ }
1288
+ return throwError(() => new Error(`An asynchronous request was made to [${httpVerb} ${response.url}], but no task was returned. The operation may still have been successful.`));
1289
+ }
1290
+ getEntity(entityRefOrUrn) {
1291
+ const entityResolver = typeof entityRefOrUrn === 'string' ?
1292
+ this.http.get(`${this._baseUrl}/api/entity/${entityRefOrUrn}`) :
1293
+ this.http.get(`${this._baseUrl}/api/entity/urn:vcloud:${entityRefOrUrn.type}:${entityRefOrUrn.id}`);
1294
+ return this.validateRequestContext().pipe(concatMap(() => entityResolver), concatMap(entity => this.http.get(`${entity.link[0].href}`)));
1295
+ }
1296
+ updateTask(task, options) {
1297
+ return this.validateRequestContext().pipe(concatMap(() => this.http.get(task.href, Object.assign({}, options))));
1298
+ }
1299
+ isTaskComplete(task) {
1300
+ return ['success', 'error', 'canceled', 'aborted'].indexOf(task.status) > -1;
1301
+ }
1302
+ removeItem(item, options) {
1303
+ const link = this.findLink(item, 'remove', null);
1304
+ if (!link) {
1305
+ return throwError(() => new Error(`No 'remove' link for specified resource.`));
1306
+ }
1307
+ return this.validateRequestContext().pipe(concatMap(() => this.http.delete(link.href, Object.assign({}, options))));
1308
+ }
1309
+ query(builder, multisite, options) {
1310
+ return this.getQueryPage(`${this._baseUrl}/api/query${builder.get()}`, multisite, options);
1311
+ }
1312
+ firstPage(result, multisite, options) {
1313
+ const link = this.findLink(result, 'firstPage', result.type);
1314
+ if (!link) {
1315
+ return throwError(() => new Error(`No 'firstPage' link for specified query.`));
1316
+ }
1317
+ return this.getQueryPage(link.href, multisite, options);
1318
+ }
1319
+ hasFirstPage(result) {
1320
+ return !!this.findLink(result, 'firstPage', result.type);
1321
+ }
1322
+ previousPage(result, multisite, options) {
1323
+ const link = this.findLink(result, 'previousPage', result.type);
1324
+ if (!link) {
1325
+ return throwError(() => new Error(`No 'previousPage' link for specified query.`));
1326
+ }
1327
+ return this.getQueryPage(link.href, multisite, options);
1328
+ }
1329
+ hasPreviousPage(result) {
1330
+ return !!this.findLink(result, 'previousPage', result.type);
1331
+ }
1332
+ nextPage(result, multisite, options) {
1333
+ const link = this.findLink(result, 'nextPage', result.type);
1334
+ if (!link) {
1335
+ return throwError(() => new Error(`No 'nextPage' link for specified query.`));
1336
+ }
1337
+ return this.getQueryPage(link.href, multisite, options);
1338
+ }
1339
+ hasNextPage(result) {
1340
+ return !!this.findLink(result, 'nextPage', result.type);
1341
+ }
1342
+ lastPage(result, multisite, options) {
1343
+ const link = this.findLink(result, 'lastPage', result.type);
1344
+ if (!link) {
1345
+ return throwError(() => new Error(`No 'lastPage' link for specified query.`));
1346
+ }
1347
+ return this.getQueryPage(link.href, multisite, options);
1348
+ }
1349
+ hasLastPage(result) {
1350
+ return !!this.findLink(result, 'lastPage', result.type);
1351
+ }
1352
+ getQueryPage(href, multisite, options) {
1353
+ if (multisite) {
1354
+ if (!options) {
1355
+ return this.http.get(href, { headers: new HttpHeaders({ _multisite: this.parseMultisiteValue(multisite) }) });
1356
+ }
1357
+ else if (options === null || options === void 0 ? void 0 : options.headers) {
1358
+ options.headers.append("_multisite", this.parseMultisiteValue(multisite));
1359
+ return this.http.get(href, Object.assign({}, options));
1360
+ }
1361
+ }
1362
+ return this.validateRequestContext().pipe(concatMap(() => this.http.get(href, Object.assign({}, options))));
1363
+ }
1364
+ /**
1365
+ * Use to perform action availability check before calling the API
1366
+ * @param item - the navigable item (containing link collection)
1367
+ * @param linkRelType - the link rel type, pass either LinkRelType or string
1368
+ * @param entityRefType - the entity reference type
1369
+ */
1370
+ canPerformAction(item, linkRelType, entityRefType) {
1371
+ return !!this.findLink(item, linkRelType, entityRefType);
1372
+ }
1373
+ findLink(item, rel, type) {
1374
+ if (!item || !item.link) {
1375
+ return undefined;
1376
+ }
1377
+ return item.link.find((link) => {
1378
+ if (type) {
1379
+ return link.rel.includes(rel) && link.type === type;
1380
+ }
1381
+ return link.rel.includes(rel);
1382
+ });
1383
+ }
1384
+ parseMultisiteValue(multisite) {
1385
+ return typeof multisite === 'boolean' ? (multisite ? 'global' : 'local') : multisite.map(site => site.locationId).join(',');
1386
+ }
1387
+ /**
1388
+ * @deprecated Use cloudApiSession
1389
+ */
1390
+ get session() {
1391
+ return this.validateRequestContext().pipe(concatMap(() => this._sessionObservable));
1392
+ }
1393
+ /**
1394
+ * Get Session observable
1395
+ */
1396
+ get cloudApiSession() {
1397
+ return this.validateRequestContextCloudApiOnly().pipe(concatMap(() => this._cloudApiSessionObservable));
1398
+ }
1399
+ get username() {
1400
+ return merge(this.cloudApiSession.pipe(filter(() => this._isCloudApiLogin), map(session => session && session.user && session.user.name)), this.session.pipe(filter(() => !this._isCloudApiLogin), map(session => session && session.user)));
1401
+ }
1402
+ get organization() {
1403
+ return merge(this.cloudApiSession.pipe(filter(() => this._isCloudApiLogin), map(session => session && session.org && session.org.name)), this.session.pipe(filter(() => !this._isCloudApiLogin), map(session => session && session.org)));
1404
+ }
1405
+ /**
1406
+ * @deprecated Use cloudApiLocation
1407
+ */
1408
+ get location() {
1409
+ return this.session.pipe(map(session => session.authorizedLocations.location.find(location => location.locationId === session.locationId)));
1410
+ }
1411
+ /**
1412
+ * Gets the location corresponding to the current session
1413
+ */
1414
+ get cloudApiLocation() {
1415
+ return this.cloudApiSession.pipe(switchMap(() => {
1416
+ if (!this._cloudApiAccessibleLocations) {
1417
+ // Ensure caching for getting AccessibleLocations
1418
+ this._cloudApiAccessibleLocations = this._cloudApiSessionLinks
1419
+ .pipe(
1420
+ // Get the AccessibleLocations link
1421
+ map((links) => this.findLink({ link: links }, 'down', 'AccessibleLocations')),
1422
+ // Fetch AccessibleLocations from the backend
1423
+ switchMap((link) => link ? this.http.get(link.href) : of(null)),
1424
+ // Get the array with all locations (what if there are many pages)
1425
+ map((accessibleLocations) => accessibleLocations && accessibleLocations.values))
1426
+ .pipe(share({ connector: () => new ReplaySubject(1) }));
1427
+ }
1428
+ return this._cloudApiAccessibleLocations;
1429
+ }),
1430
+ // Need to have the session in order to get its location
1431
+ withLatestFrom(this.cloudApiSession),
1432
+ // Find the location that corresponds to this session
1433
+ map(([accessibleLocations, session]) => {
1434
+ if (!accessibleLocations || !session) {
1435
+ return null;
1436
+ }
1437
+ const sessionLocation = session.location;
1438
+ if (!sessionLocation) {
1439
+ return null;
1440
+ }
1441
+ return accessibleLocations.find(location => location.locationId === sessionLocation);
1442
+ }));
1443
+ }
1444
+ getLocation(session) {
1445
+ return session.authorizedLocations.location.find(location => location.locationId === session.locationId);
1446
+ }
1447
+ /**
1448
+ * Build the endpoint url. If the provided endpoint is already an absolute URL, then return it as it is without
1449
+ * any modifications, otherwise consider it as a relative one and prepend the baseUrl as defined by the host application.
1450
+ */
1451
+ buildEndpointUrl(endpoint) {
1452
+ return endpoint.indexOf('://') > -1 ? endpoint : `${this._baseUrl}/${endpoint}`;
1453
+ }
1454
+ }
1455
+ VcdApiClient.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdApiClient, deps: [{ token: VcdHttpClient }, { token: i0.Injector }, { token: VcdSdkConfig, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1456
+ VcdApiClient.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdApiClient });
1457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdApiClient, decorators: [{
1458
+ type: Injectable
1459
+ }], ctorParameters: function () {
1460
+ return [{ type: VcdHttpClient }, { type: i0.Injector }, { type: VcdSdkConfig, decorators: [{
1461
+ type: Optional
1462
+ }] }];
1463
+ } });
1464
+
1465
+ /**
1466
+ * Extensions should import this module.
1467
+ * They can then wire in SDK components as desired.
1468
+ */
1469
+ class VcdSdkModule {
1470
+ static forRoot(config) {
1471
+ return {
1472
+ ngModule: VcdSdkModule,
1473
+ providers: [
1474
+ RequestHeadersInterceptor,
1475
+ LoggingInterceptor,
1476
+ ResponseNormalizationInterceptor,
1477
+ VcdHttpClient,
1478
+ VcdApiClient,
1479
+ {
1480
+ provide: VcdSdkConfig,
1481
+ useValue: config || {}
1482
+ },
1483
+ ]
1484
+ };
1485
+ }
1486
+ }
1487
+ VcdSdkModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdSdkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1488
+ VcdSdkModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.0", ngImport: i0, type: VcdSdkModule, imports: [HttpClientModule,
1489
+ CommonModule] });
1490
+ VcdSdkModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdSdkModule, imports: [HttpClientModule,
1491
+ CommonModule] });
1492
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdSdkModule, decorators: [{
1493
+ type: NgModule,
1494
+ args: [{
1495
+ imports: [
1496
+ HttpClientModule,
1497
+ CommonModule,
1498
+ ],
1499
+ declarations: [],
1500
+ exports: [],
1501
+ }]
1502
+ }] });
1503
+
1504
+ /*
1505
+ * Public API Surface of sdk
1506
+ */
1507
+
1508
+ /**
1509
+ * Generated bundle index. Do not edit.
1510
+ */
1511
+
1512
+ export { API_ROOT_URL, ApiResult, ApiResultService, AuthTokenHolderService, EXTENSION_ASSET_URL, EXTENSION_ROUTE, EntityActionExtensionComponent, ExtensionNavRegistrationAction, FLEX_APP_URL, Filter, HATEOAS_HEADER, LinkRelType, LoggingInterceptor, MAX_CHUNK_RETRY_COUNT, MAX_CHUNK_SIZE, PluginModule, Query, RequestHeadersInterceptor, ResponseNormalizationInterceptor, SDK_MODE, SESSION_ORGANIZATION, SESSION_ORG_ID, SESSION_SCOPE, TRANSFER_LINK_REL, TransferError, VcdApiClient, VcdHttpClient, VcdSdkConfig, VcdSdkModule, VcdTransferClient, WizardExtensionComponent, WizardExtensionWithValidationComponent, _EntityActionExtensionComponent, _WizardExtensionComponent, _WizardExtensionWithValidationComponent, parseHeaderHateoasLinks };
1513
+ //# sourceMappingURL=vcd-sdk.mjs.map