@c8y/ngx-components 1017.0.338 → 1017.0.345
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/common/date.pipe.d.ts +2 -2
- package/core/common/stringify-object.pipe.d.ts +2 -1
- package/ecosystem/packages/deploy-application/deploy-application.component.d.ts +6 -5
- package/ecosystem/shared/ecosystem.constants.d.ts +2 -0
- package/ecosystem/shared/ecosystem.model.d.ts +3 -1
- package/ecosystem/shared/ecosystem.service.d.ts +11 -5
- package/esm2020/core/common/date.pipe.mjs +12 -7
- package/esm2020/core/common/stringify-object.pipe.mjs +11 -8
- package/esm2020/ecosystem/application-properties/application-properties.component.mjs +3 -3
- package/esm2020/ecosystem/applications/install-from-package/install-from-package.component.mjs +2 -2
- package/esm2020/ecosystem/packages/deploy-application/deploy-application.component.mjs +26 -81
- package/esm2020/ecosystem/shared/ecosystem.constants.mjs +5 -3
- package/esm2020/ecosystem/shared/ecosystem.model.mjs +3 -1
- package/esm2020/ecosystem/shared/ecosystem.service.mjs +121 -24
- package/fesm2015/c8y-ngx-components-ecosystem-shared.mjs +139 -27
- package/fesm2015/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
- package/fesm2015/c8y-ngx-components-ecosystem.mjs +23 -77
- package/fesm2015/c8y-ngx-components-ecosystem.mjs.map +1 -1
- package/fesm2015/c8y-ngx-components.mjs +20 -13
- package/fesm2015/c8y-ngx-components.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components-ecosystem-shared.mjs +126 -25
- package/fesm2020/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components-ecosystem.mjs +23 -78
- package/fesm2020/c8y-ngx-components-ecosystem.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components.mjs +20 -13
- package/fesm2020/c8y-ngx-components.mjs.map +1 -1
- package/locales/locales.pot +15 -3
- package/package.json +2 -2
|
@@ -10,7 +10,7 @@ import { __awaiter } from 'tslib';
|
|
|
10
10
|
import * as i3 from '@c8y/client';
|
|
11
11
|
import { ApplicationAvailability, ApplicationType } from '@c8y/client';
|
|
12
12
|
import { saveAs } from 'file-saver';
|
|
13
|
-
import { groupBy, uniqBy, get, pick, kebabCase, cloneDeep } from 'lodash-es';
|
|
13
|
+
import { groupBy, uniqBy, get, pick, omit, isUndefined, kebabCase, cloneDeep } from 'lodash-es';
|
|
14
14
|
import { BehaviorSubject, defer, merge, combineLatest } from 'rxjs';
|
|
15
15
|
import { map, shareReplay, debounceTime, take, distinctUntilKeyChanged, tap, filter, switchMap } from 'rxjs/operators';
|
|
16
16
|
import { gt, coerce } from 'semver';
|
|
@@ -33,6 +33,7 @@ var ERROR_TYPE;
|
|
|
33
33
|
(function (ERROR_TYPE) {
|
|
34
34
|
ERROR_TYPE["TYPE_VALIDATION"] = "TYPE_VALIDATION";
|
|
35
35
|
ERROR_TYPE["ALREADY_SUBSCRIBED"] = "ALREADY_SUBSCRIBED";
|
|
36
|
+
ERROR_TYPE["ALREADY_EXIST"] = "ALREADY_EXIST";
|
|
36
37
|
ERROR_TYPE["INTERNAL_ERROR"] = "INTERNAL_ERROR";
|
|
37
38
|
ERROR_TYPE["NO_MANIFEST_FILE"] = "NO_MANIFEST_FILE";
|
|
38
39
|
ERROR_TYPE["INVALID_PACKAGE"] = "INVALID_PACKAGE";
|
|
@@ -40,6 +41,7 @@ var ERROR_TYPE;
|
|
|
40
41
|
ERROR_TYPE["MICROSERVICE_NAME_TOO_LONG"] = "MICROSERVICE_NAME_TOO_LONG";
|
|
41
42
|
ERROR_TYPE["APPLICATION_CREATION_FAILED"] = "APPLICATION_CREATION_FAILED";
|
|
42
43
|
ERROR_TYPE["KEY_OR_CONTEXT_PATH_MISMATCH"] = "KEY_OR_CONTEXT_PATH_MISMATCH";
|
|
44
|
+
ERROR_TYPE["VERSION_NOT_FOUND"] = "VERSION_NOT_FOUND";
|
|
43
45
|
})(ERROR_TYPE || (ERROR_TYPE = {}));
|
|
44
46
|
const PRODUCT_EXPERIENCE = {
|
|
45
47
|
APPLICATIONS: {
|
|
@@ -92,6 +94,7 @@ const PRODUCT_EXPERIENCE = {
|
|
|
92
94
|
};
|
|
93
95
|
|
|
94
96
|
const ERROR_MESSAGES = {
|
|
97
|
+
[ERROR_TYPE.ALREADY_EXIST]: gettext('Could not deploy the application, as the application with the same name, context-path or key exist already.'),
|
|
95
98
|
[ERROR_TYPE.TYPE_VALIDATION]: gettext('Wrong file format. Expected a *.zip file with a valid manifest.'),
|
|
96
99
|
[ERROR_TYPE.ALREADY_SUBSCRIBED]: gettext('Could not subscribe to the microservice because another application with the same context path is already subscribed.'),
|
|
97
100
|
[ERROR_TYPE.NO_MANIFEST_FILE]: gettext('Could not find a manifest.'),
|
|
@@ -100,7 +103,8 @@ const ERROR_MESSAGES = {
|
|
|
100
103
|
[ERROR_TYPE.INTERNAL_ERROR]: gettext('An internal error occurred, try to upload again.'),
|
|
101
104
|
[ERROR_TYPE.MICROSERVICE_NAME_TOO_LONG]: gettext('Microservice name "{{ name }}" must not be longer than {{ maxChars }} characters.'),
|
|
102
105
|
[ERROR_TYPE.APPLICATION_CREATION_FAILED]: gettext('Application creation failed.'),
|
|
103
|
-
[ERROR_TYPE.KEY_OR_CONTEXT_PATH_MISMATCH]: gettext('The contextPath or key of the uploaded archive do not match with the existing
|
|
106
|
+
[ERROR_TYPE.KEY_OR_CONTEXT_PATH_MISMATCH]: gettext('The "contextPath`KEEP_ORIGINAL`" or "key`KEEP_ORIGINAL`" of the uploaded archive do not match with the existing application.'),
|
|
107
|
+
[ERROR_TYPE.VERSION_NOT_FOUND]: gettext('The selected version was not found on the server.')
|
|
104
108
|
};
|
|
105
109
|
const APP_STATE = {
|
|
106
110
|
SUBSCRIBED: {
|
|
@@ -130,7 +134,7 @@ const APP_STATE = {
|
|
|
130
134
|
};
|
|
131
135
|
const packageProperties = [
|
|
132
136
|
{
|
|
133
|
-
label: gettext('
|
|
137
|
+
label: gettext('Latest version'),
|
|
134
138
|
key: 'version'
|
|
135
139
|
},
|
|
136
140
|
{
|
|
@@ -273,6 +277,18 @@ class EcosystemService {
|
|
|
273
277
|
});
|
|
274
278
|
}
|
|
275
279
|
getPackageApplications(customFilter = {}) {
|
|
280
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
281
|
+
const filterCallback = app => this.isPackage(app);
|
|
282
|
+
return this.getApplicationsFiltered(customFilter, filterCallback);
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
getHostedAndPackageApplications(customFilter = {}) {
|
|
286
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
287
|
+
const filterCallback = app => this.isPackage(app) || this.isApplication(app);
|
|
288
|
+
return this.getApplicationsFiltered(customFilter, filterCallback);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
getApplicationsFiltered(customFilter = {}, filterCallback = (app) => !!app) {
|
|
276
292
|
return __awaiter(this, void 0, void 0, function* () {
|
|
277
293
|
const filter = Object.assign({}, customFilter);
|
|
278
294
|
const sharedFilter = Object.assign({
|
|
@@ -284,7 +300,7 @@ class EcosystemService {
|
|
|
284
300
|
this.getApplications(filter),
|
|
285
301
|
this.applicationService.list(sharedFilter)
|
|
286
302
|
]);
|
|
287
|
-
const webApps = [...apps, ...shared].filter(
|
|
303
|
+
const webApps = [...apps, ...shared].filter(filterCallback);
|
|
288
304
|
// an app could be subscribed to a tenant, but also have it's availability set to SHARED, in that case it would occur twice.
|
|
289
305
|
const uniqWebApps = uniqBy(webApps, (app) => app.id);
|
|
290
306
|
return uniqWebApps.sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -370,20 +386,6 @@ class EcosystemService {
|
|
|
370
386
|
availability });
|
|
371
387
|
return config;
|
|
372
388
|
}
|
|
373
|
-
updateAppManifest(application, sourcePackage) {
|
|
374
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
375
|
-
const { id } = application;
|
|
376
|
-
const cleanedApp = this.removeAppProperties(application);
|
|
377
|
-
if (!cleanedApp.manifest) {
|
|
378
|
-
cleanedApp.manifest = {};
|
|
379
|
-
}
|
|
380
|
-
cleanedApp.manifest.isPackage = false;
|
|
381
|
-
cleanedApp.manifest.source = sourcePackage.id;
|
|
382
|
-
return yield this.applicationService
|
|
383
|
-
.binary(id)
|
|
384
|
-
.updateFiles([{ path: CUMULOCITY_JSON, contents: JSON.stringify(cleanedApp) }]);
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
389
|
listArchives(appId) {
|
|
388
390
|
return __awaiter(this, void 0, void 0, function* () {
|
|
389
391
|
const filter = {
|
|
@@ -617,6 +619,85 @@ class EcosystemService {
|
|
|
617
619
|
}
|
|
618
620
|
});
|
|
619
621
|
}
|
|
622
|
+
deployApp(selectedPackage, formGroupValue, model) {
|
|
623
|
+
var _a;
|
|
624
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
625
|
+
// Create new app config
|
|
626
|
+
const config = this.createConfig(selectedPackage, formGroupValue);
|
|
627
|
+
const requestedVersion = model.selected.version;
|
|
628
|
+
let cleanManifest;
|
|
629
|
+
try {
|
|
630
|
+
const manifest = yield this.applicationService.getAppManifest(selectedPackage, requestedVersion);
|
|
631
|
+
cleanManifest = omit(manifest, ['name', 'contextPath', 'key']);
|
|
632
|
+
}
|
|
633
|
+
catch (ex) {
|
|
634
|
+
throw new EcosystemError(ERROR_TYPE.VERSION_NOT_FOUND);
|
|
635
|
+
}
|
|
636
|
+
config.isSetup = true;
|
|
637
|
+
config.manifest = cleanManifest;
|
|
638
|
+
config.availability = ApplicationAvailability.PRIVATE;
|
|
639
|
+
config.manifest.isPackage = false;
|
|
640
|
+
config.manifest.source = selectedPackage.id;
|
|
641
|
+
config.manifest.package = 'blueprint';
|
|
642
|
+
// because of a issue with SHARED availability we always should check again
|
|
643
|
+
// if the app not exist already
|
|
644
|
+
const allExistingApps = yield this.getHostedAndPackageApplications();
|
|
645
|
+
const doesAppKeyOrContextPathExist = this.checkIfAppNameKeyPathExists(allExistingApps, config);
|
|
646
|
+
if (doesAppKeyOrContextPathExist) {
|
|
647
|
+
throw new EcosystemError(ERROR_TYPE.ALREADY_EXIST);
|
|
648
|
+
}
|
|
649
|
+
// Create new app
|
|
650
|
+
const newApp = (yield this.applicationService.create(config)).data;
|
|
651
|
+
try {
|
|
652
|
+
// Binary upload can fail if SHARED package
|
|
653
|
+
// in this case, catch error and fall back to
|
|
654
|
+
// clone API.
|
|
655
|
+
yield this.uploadBinaryFromOtherPackage(selectedPackage, newApp, model.selected.binaryId, requestedVersion);
|
|
656
|
+
}
|
|
657
|
+
catch (error) {
|
|
658
|
+
if (((_a = error === null || error === void 0 ? void 0 : error.res) === null || _a === void 0 ? void 0 : _a.status) === 404) {
|
|
659
|
+
yield this.fallbackToClone(newApp, selectedPackage, requestedVersion);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return newApp;
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
fallbackToClone(application, selectedPackage, requestedVersion) {
|
|
666
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
667
|
+
let wasSuccess = true;
|
|
668
|
+
let clonedPkg;
|
|
669
|
+
try {
|
|
670
|
+
clonedPkg = (yield this.applicationService.clone(selectedPackage, requestedVersion)).data;
|
|
671
|
+
yield this.uploadBinaryFromOtherPackage(selectedPackage, application, clonedPkg.activeVersionId, requestedVersion, clonedPkg);
|
|
672
|
+
}
|
|
673
|
+
catch (error) {
|
|
674
|
+
this.alertError(error);
|
|
675
|
+
wasSuccess = false;
|
|
676
|
+
}
|
|
677
|
+
finally {
|
|
678
|
+
yield this.deleteApp(clonedPkg, true);
|
|
679
|
+
}
|
|
680
|
+
return wasSuccess;
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
uploadBinaryFromOtherPackage(selectedPackage, applicationToUploadBinaryTo, binaryId, requestedVersion, useBinariesFrom) {
|
|
684
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
685
|
+
const { data: binaryDetails } = yield this.inventoryService.detail(binaryId);
|
|
686
|
+
// Get binary from specific package version
|
|
687
|
+
const binary = yield this.getBinary(useBinariesFrom || selectedPackage, {
|
|
688
|
+
id: binaryId
|
|
689
|
+
});
|
|
690
|
+
// Create zip
|
|
691
|
+
const fileBinary = new Blob([binary], { type: binaryDetails.contentType });
|
|
692
|
+
const file = new File([fileBinary], binaryDetails.name, {
|
|
693
|
+
type: binaryDetails.contentType
|
|
694
|
+
});
|
|
695
|
+
// Upload binary to new app
|
|
696
|
+
yield this.uploadArchiveToApp(file, applicationToUploadBinaryTo);
|
|
697
|
+
// update the app manifest
|
|
698
|
+
yield this.updateAppManifest(applicationToUploadBinaryTo, selectedPackage, requestedVersion);
|
|
699
|
+
});
|
|
700
|
+
}
|
|
620
701
|
getAppState(app) {
|
|
621
702
|
if (!this.isOwner(app)) {
|
|
622
703
|
return APP_STATE.SUBSCRIBED;
|
|
@@ -709,6 +790,45 @@ class EcosystemService {
|
|
|
709
790
|
}
|
|
710
791
|
});
|
|
711
792
|
}
|
|
793
|
+
filterContainString(name, filterTerm) {
|
|
794
|
+
const term = filterTerm.toLowerCase().trim();
|
|
795
|
+
return name && name.toLowerCase().indexOf(term) > -1;
|
|
796
|
+
}
|
|
797
|
+
updateAppManifest(application, selectedPackage, requestedVersion) {
|
|
798
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
799
|
+
const { id } = application;
|
|
800
|
+
const cleanedApp = this.removeAppProperties(application);
|
|
801
|
+
let manifest = selectedPackage.manifest || {};
|
|
802
|
+
if (requestedVersion) {
|
|
803
|
+
try {
|
|
804
|
+
const versionedAppManifest = yield this.applicationService.getAppManifest(selectedPackage, requestedVersion);
|
|
805
|
+
manifest = versionedAppManifest;
|
|
806
|
+
}
|
|
807
|
+
catch (ex) {
|
|
808
|
+
throw new EcosystemError(ERROR_TYPE.VERSION_NOT_FOUND);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
cleanedApp.manifest = manifest;
|
|
812
|
+
cleanedApp.manifest.isPackage = false;
|
|
813
|
+
cleanedApp.manifest.source = selectedPackage.id;
|
|
814
|
+
return yield this.applicationService
|
|
815
|
+
.binary(id)
|
|
816
|
+
.updateFiles([{ path: CUMULOCITY_JSON, contents: JSON.stringify(cleanedApp) }]);
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
checkIfAppNameKeyPathExists(existingApps, app, retryNo) {
|
|
820
|
+
if (isUndefined(retryNo)) {
|
|
821
|
+
return existingApps.find(existingApp => existingApp.name === app.name ||
|
|
822
|
+
existingApp.key === app.key ||
|
|
823
|
+
existingApp.contextPath === app.contextPath);
|
|
824
|
+
}
|
|
825
|
+
return existingApps.find(existingApp => existingApp.name === app.name ||
|
|
826
|
+
existingApp.key === app.key ||
|
|
827
|
+
existingApp.contextPath === app.contextPath ||
|
|
828
|
+
existingApp.name === [app.name, retryNo].join('-') ||
|
|
829
|
+
existingApp.key === [app.key, retryNo].join('-') ||
|
|
830
|
+
existingApp.contextPath === [app.contextPath, retryNo].join('-'));
|
|
831
|
+
}
|
|
712
832
|
getAppKey(appModel, name) {
|
|
713
833
|
let key = appModel === null || appModel === void 0 ? void 0 : appModel.key;
|
|
714
834
|
if (!key) {
|
|
@@ -745,17 +865,9 @@ class EcosystemService {
|
|
|
745
865
|
}
|
|
746
866
|
return baseName;
|
|
747
867
|
}
|
|
748
|
-
checkIfAppNameKeyPathExists(existingApps, app, retryNo) {
|
|
749
|
-
return existingApps.find(existingApp => existingApp.name === app.name ||
|
|
750
|
-
existingApp.key === app.key ||
|
|
751
|
-
existingApp.contextPath === app.contextPath ||
|
|
752
|
-
existingApp.name === [app.name, retryNo].join('-') ||
|
|
753
|
-
existingApp.key === [app.key, retryNo].join('-') ||
|
|
754
|
-
existingApp.contextPath === [app.contextPath, retryNo].join('-'));
|
|
755
|
-
}
|
|
756
868
|
removeAppProperties(app) {
|
|
757
869
|
const tempApp = cloneDeep(app);
|
|
758
|
-
const propertiesToRemove = ['id', 'owner', 'activeVersionId', 'self'];
|
|
870
|
+
const propertiesToRemove = ['id', 'owner', 'activeVersionId', 'self', 'type'];
|
|
759
871
|
propertiesToRemove.forEach(prop => delete tempApp[prop]);
|
|
760
872
|
return tempApp;
|
|
761
873
|
}
|