kuzzle-device-manager 2.11.0 → 3.0.0-3-dev.2
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/modules/asset/AssetModule.d.ts +1 -4
- package/dist/lib/modules/asset/AssetModule.js +0 -13
- package/dist/lib/modules/asset/AssetModule.js.map +1 -1
- package/dist/lib/modules/asset/AssetService.d.ts +7 -4
- package/dist/lib/modules/asset/AssetService.js +119 -50
- package/dist/lib/modules/asset/AssetService.js.map +1 -1
- package/dist/lib/modules/asset/AssetsController.d.ts +25 -7
- package/dist/lib/modules/asset/AssetsController.js +123 -36
- package/dist/lib/modules/asset/AssetsController.js.map +1 -1
- package/dist/lib/modules/asset/collections/assetsMappings.js +10 -15
- package/dist/lib/modules/asset/collections/assetsMappings.js.map +1 -1
- package/dist/lib/modules/asset/exports.d.ts +0 -4
- package/dist/lib/modules/asset/exports.js +0 -4
- package/dist/lib/modules/asset/exports.js.map +1 -1
- package/dist/lib/modules/asset/index.d.ts +1 -3
- package/dist/lib/modules/asset/index.js +1 -3
- package/dist/lib/modules/asset/index.js.map +1 -1
- package/dist/lib/modules/asset/model/AssetSerializer.js +0 -1
- package/dist/lib/modules/asset/model/AssetSerializer.js.map +1 -1
- package/dist/lib/modules/asset/roles/RoleAssetsAdmin.js +1 -1
- package/dist/lib/modules/asset/roles/RoleAssetsAdmin.js.map +1 -1
- package/dist/lib/modules/asset/types/AssetApi.d.ts +124 -9
- package/dist/lib/modules/asset/types/AssetContent.d.ts +9 -16
- package/dist/lib/modules/asset/types/AssetHistoryContent.d.ts +4 -11
- package/dist/lib/modules/decoder/DecodedPayload.d.ts +2 -0
- package/dist/lib/modules/decoder/DecodedPayload.js +13 -2
- package/dist/lib/modules/decoder/DecodedPayload.js.map +1 -1
- package/dist/lib/modules/decoder/Decoder.d.ts +1 -1
- package/dist/lib/modules/decoder/Decoder.js.map +1 -1
- package/dist/lib/modules/decoder/DecoderModule.js.map +1 -1
- package/dist/lib/modules/decoder/DecodersController.d.ts +4 -1
- package/dist/lib/modules/decoder/DecodersController.js +3 -0
- package/dist/lib/modules/decoder/DecodersController.js.map +1 -1
- package/dist/lib/modules/decoder/DecodersRegister.js +4 -1
- package/dist/lib/modules/decoder/DecodersRegister.js.map +1 -1
- package/dist/lib/modules/decoder/PayloadService.d.ts +1 -0
- package/dist/lib/modules/decoder/PayloadService.js +136 -26
- package/dist/lib/modules/decoder/PayloadService.js.map +1 -1
- package/dist/lib/modules/decoder/PayloadsController.js +1 -1
- package/dist/lib/modules/decoder/PayloadsController.js.map +1 -1
- package/dist/lib/modules/device/DeviceService.d.ts +6 -47
- package/dist/lib/modules/device/DeviceService.js +157 -291
- package/dist/lib/modules/device/DeviceService.js.map +1 -1
- package/dist/lib/modules/device/DevicesController.d.ts +5 -5
- package/dist/lib/modules/device/DevicesController.js +35 -23
- package/dist/lib/modules/device/DevicesController.js.map +1 -1
- package/dist/lib/modules/device/collections/deviceMappings.d.ts +6 -0
- package/dist/lib/modules/device/collections/deviceMappings.js +76 -6
- package/dist/lib/modules/device/collections/deviceMappings.js.map +1 -1
- package/dist/lib/modules/device/roles/RoleDevicesAdmin.d.ts +2 -2
- package/dist/lib/modules/device/roles/RoleDevicesAdmin.js +7 -4
- package/dist/lib/modules/device/roles/RoleDevicesAdmin.js.map +1 -1
- package/dist/lib/modules/device/roles/specificRoles/RoleDevicesAssetAssociation.js +4 -1
- package/dist/lib/modules/device/roles/specificRoles/RoleDevicesAssetAssociation.js.map +1 -1
- package/dist/lib/modules/device/types/DeviceApi.d.ts +69 -41
- package/dist/lib/modules/device/types/DeviceContent.d.ts +56 -5
- package/dist/lib/modules/device/types/DeviceEvents.d.ts +9 -24
- package/dist/lib/modules/group/GroupsController.d.ts +37 -0
- package/dist/lib/modules/group/GroupsController.js +472 -0
- package/dist/lib/modules/group/GroupsController.js.map +1 -0
- package/dist/lib/modules/group/GroupsModule.d.ts +10 -0
- package/dist/lib/modules/group/GroupsModule.js +25 -0
- package/dist/lib/modules/group/GroupsModule.js.map +1 -0
- package/dist/lib/modules/group/GroupsService.d.ts +118 -0
- package/dist/lib/modules/group/GroupsService.js +518 -0
- package/dist/lib/modules/group/GroupsService.js.map +1 -0
- package/dist/lib/modules/group/collections/groupsMappings.d.ts +2 -0
- package/dist/lib/modules/{asset/collections/assetsGroupsMapping.js → group/collections/groupsMappings.js} +4 -12
- package/dist/lib/modules/group/collections/groupsMappings.js.map +1 -0
- package/dist/lib/modules/group/exports.d.ts +5 -0
- package/dist/lib/modules/group/exports.js +22 -0
- package/dist/lib/modules/group/exports.js.map +1 -0
- package/dist/lib/modules/group/index.d.ts +4 -0
- package/dist/lib/modules/{measure/measures → group}/index.js +4 -5
- package/dist/lib/modules/group/index.js.map +1 -0
- package/dist/lib/modules/{asset/roles/RoleAssetsGroupsAdmin.d.ts → group/roles/RoleGroupsAdmin.d.ts} +3 -3
- package/dist/lib/modules/{asset/roles/RoleAssetsGroupsAdmin.js → group/roles/RoleGroupsAdmin.js} +7 -7
- package/dist/lib/modules/group/roles/RoleGroupsAdmin.js.map +1 -0
- package/dist/lib/modules/{asset/roles/RoleAssetsGroupsReader.d.ts → group/roles/RoleGroupsReader.d.ts} +3 -3
- package/dist/lib/modules/{asset/roles/RoleAssetsGroupsReader.js → group/roles/RoleGroupsReader.js} +7 -7
- package/dist/lib/modules/group/roles/RoleGroupsReader.js.map +1 -0
- package/dist/lib/modules/group/types/GroupContent.d.ts +10 -0
- package/dist/lib/modules/{asset/types/AssetGroupsApi.js → group/types/GroupContent.js} +1 -1
- package/dist/lib/modules/group/types/GroupContent.js.map +1 -0
- package/dist/lib/modules/group/types/GroupsApi.d.ts +141 -0
- package/dist/lib/modules/{asset/types/AssetGroupContent.js → group/types/GroupsApi.js} +1 -1
- package/dist/lib/modules/group/types/GroupsApi.js.map +1 -0
- package/dist/lib/modules/measure/MeasureExporter.js +14 -6
- package/dist/lib/modules/measure/MeasureExporter.js.map +1 -1
- package/dist/lib/modules/measure/MeasureService.d.ts +11 -43
- package/dist/lib/modules/measure/MeasureService.js +86 -375
- package/dist/lib/modules/measure/MeasureService.js.map +1 -1
- package/dist/lib/modules/measure/MeasureSourcesBuilder.d.ts +1 -2
- package/dist/lib/modules/measure/MeasureSourcesBuilder.js +5 -15
- package/dist/lib/modules/measure/MeasureSourcesBuilder.js.map +1 -1
- package/dist/lib/modules/measure/MeasureTargetBuilder.d.ts +1 -1
- package/dist/lib/modules/measure/MeasureTargetBuilder.js +2 -2
- package/dist/lib/modules/measure/MeasureTargetBuilder.js.map +1 -1
- package/dist/lib/modules/measure/collections/measuresMappings.d.ts +2 -91
- package/dist/lib/modules/measure/collections/measuresMappings.js +7 -11
- package/dist/lib/modules/measure/collections/measuresMappings.js.map +1 -1
- package/dist/lib/modules/measure/exports.d.ts +0 -1
- package/dist/lib/modules/measure/exports.js +0 -1
- package/dist/lib/modules/measure/exports.js.map +1 -1
- package/dist/lib/modules/measure/index.d.ts +0 -1
- package/dist/lib/modules/measure/index.js +0 -1
- package/dist/lib/modules/measure/index.js.map +1 -1
- package/dist/lib/modules/measure/types/MeasureContent.d.ts +9 -2
- package/dist/lib/modules/measure/types/MeasureEvents.d.ts +6 -149
- package/dist/lib/modules/measure/types/MeasureSources.d.ts +5 -0
- package/dist/lib/modules/measure/types/MeasureSources.js.map +1 -1
- package/dist/lib/modules/measure/types/MeasureTarget.d.ts +1 -1
- package/dist/lib/modules/measure/types/MeasureTarget.js +1 -1
- package/dist/lib/modules/measure/types/MeasureTarget.js.map +1 -1
- package/dist/lib/modules/model/ModelModule.js.map +1 -1
- package/dist/lib/modules/model/ModelSerializer.js +29 -0
- package/dist/lib/modules/model/ModelSerializer.js.map +1 -1
- package/dist/lib/modules/model/ModelService.d.ts +20 -14
- package/dist/lib/modules/model/ModelService.js +354 -117
- package/dist/lib/modules/model/ModelService.js.map +1 -1
- package/dist/lib/modules/model/ModelsController.d.ts +1 -1
- package/dist/lib/modules/model/ModelsController.js +33 -19
- package/dist/lib/modules/model/ModelsController.js.map +1 -1
- package/dist/lib/modules/model/ModelsRegister.d.ts +6 -5
- package/dist/lib/modules/model/ModelsRegister.js +10 -8
- package/dist/lib/modules/model/ModelsRegister.js.map +1 -1
- package/dist/lib/modules/model/collections/modelsMappings.js +20 -1
- package/dist/lib/modules/model/collections/modelsMappings.js.map +1 -1
- package/dist/lib/modules/model/types/ModelApi.d.ts +15 -9
- package/dist/lib/modules/model/types/ModelContent.d.ts +35 -3
- package/dist/lib/modules/model/types/ModelContent.js.map +1 -1
- package/dist/lib/modules/model/types/ModelDefinition.d.ts +6 -2
- package/dist/lib/modules/model/types/ModelEvents.d.ts +3 -1
- package/dist/lib/modules/plugin/DeviceManagerEngine.d.ts +15 -6
- package/dist/lib/modules/plugin/DeviceManagerEngine.js +151 -54
- package/dist/lib/modules/plugin/DeviceManagerEngine.js.map +1 -1
- package/dist/lib/modules/plugin/DeviceManagerPlugin.d.ts +10 -8
- package/dist/lib/modules/plugin/DeviceManagerPlugin.js +41 -44
- package/dist/lib/modules/plugin/DeviceManagerPlugin.js.map +1 -1
- package/dist/lib/modules/plugin/types/DeviceManagerConfiguration.d.ts +9 -14
- package/dist/lib/modules/plugin/types/InternalCollection.d.ts +1 -1
- package/dist/lib/modules/plugin/types/InternalCollection.js +1 -1
- package/dist/lib/modules/plugin/types/InternalCollection.js.map +1 -1
- package/dist/lib/modules/plugin/types/exports.d.ts +1 -0
- package/dist/lib/modules/plugin/types/exports.js +1 -0
- package/dist/lib/modules/plugin/types/exports.js.map +1 -1
- package/dist/lib/modules/shared/services/AbstractExporter.d.ts +3 -1
- package/dist/lib/modules/shared/services/AbstractExporter.js +7 -3
- package/dist/lib/modules/shared/services/AbstractExporter.js.map +1 -1
- package/dist/lib/modules/shared/services/BaseService.js.map +1 -1
- package/dist/lib/modules/shared/services/DigitalTwinExporter.d.ts +6 -1
- package/dist/lib/modules/shared/services/DigitalTwinExporter.js +49 -7
- package/dist/lib/modules/shared/services/DigitalTwinExporter.js.map +1 -1
- package/dist/lib/modules/shared/services/DigitalTwinService.d.ts +70 -2
- package/dist/lib/modules/shared/services/DigitalTwinService.js +309 -1
- package/dist/lib/modules/shared/services/DigitalTwinService.js.map +1 -1
- package/dist/lib/modules/shared/types/DigitalTwinContent.d.ts +4 -5
- package/dist/lib/modules/shared/types/DigitalTwinEvents.d.ts +30 -0
- package/package.json +15 -9
- package/dist/lib/modules/asset/AssetsGroupsController.d.ts +0 -24
- package/dist/lib/modules/asset/AssetsGroupsController.js +0 -239
- package/dist/lib/modules/asset/AssetsGroupsController.js.map +0 -1
- package/dist/lib/modules/asset/AssetsGroupsService.d.ts +0 -49
- package/dist/lib/modules/asset/AssetsGroupsService.js +0 -172
- package/dist/lib/modules/asset/AssetsGroupsService.js.map +0 -1
- package/dist/lib/modules/asset/collections/assetsGroupsMapping.d.ts +0 -2
- package/dist/lib/modules/asset/collections/assetsGroupsMapping.js.map +0 -1
- package/dist/lib/modules/asset/roles/RoleAssetsGroupsAdmin.js.map +0 -1
- package/dist/lib/modules/asset/roles/RoleAssetsGroupsReader.js.map +0 -1
- package/dist/lib/modules/asset/types/AssetGroupContent.d.ts +0 -11
- package/dist/lib/modules/asset/types/AssetGroupContent.js.map +0 -1
- package/dist/lib/modules/asset/types/AssetGroupsApi.d.ts +0 -59
- package/dist/lib/modules/asset/types/AssetGroupsApi.js.map +0 -1
- package/dist/lib/modules/measure/measures/BatteryMeasure.d.ts +0 -5
- package/dist/lib/modules/measure/measures/BatteryMeasure.js +0 -19
- package/dist/lib/modules/measure/measures/BatteryMeasure.js.map +0 -1
- package/dist/lib/modules/measure/measures/HumidityMeasure.d.ts +0 -5
- package/dist/lib/modules/measure/measures/HumidityMeasure.js +0 -19
- package/dist/lib/modules/measure/measures/HumidityMeasure.js.map +0 -1
- package/dist/lib/modules/measure/measures/MovementMeasure.d.ts +0 -5
- package/dist/lib/modules/measure/measures/MovementMeasure.js +0 -17
- package/dist/lib/modules/measure/measures/MovementMeasure.js.map +0 -1
- package/dist/lib/modules/measure/measures/PositionMeasure.d.ts +0 -10
- package/dist/lib/modules/measure/measures/PositionMeasure.js +0 -43
- package/dist/lib/modules/measure/measures/PositionMeasure.js.map +0 -1
- package/dist/lib/modules/measure/measures/TemperatureMeasure.d.ts +0 -5
- package/dist/lib/modules/measure/measures/TemperatureMeasure.js +0 -19
- package/dist/lib/modules/measure/measures/TemperatureMeasure.js.map +0 -1
- package/dist/lib/modules/measure/measures/index.d.ts +0 -5
- package/dist/lib/modules/measure/measures/index.js.map +0 -1
|
@@ -18,8 +18,8 @@ class ModelService extends shared_1.BaseService {
|
|
|
18
18
|
this.registerAskEvents();
|
|
19
19
|
}
|
|
20
20
|
registerAskEvents() {
|
|
21
|
-
(0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:model:asset:get", async ({
|
|
22
|
-
const assetModel = await this.getAsset(
|
|
21
|
+
(0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:model:asset:get", async ({ engineGroups, engineId, model }) => {
|
|
22
|
+
const assetModel = await this.getAsset(engineGroups, engineId, model);
|
|
23
23
|
return assetModel._source;
|
|
24
24
|
});
|
|
25
25
|
(0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:model:device:get", async ({ model }) => {
|
|
@@ -30,13 +30,13 @@ class ModelService extends shared_1.BaseService {
|
|
|
30
30
|
const groupModel = await this.getGroup(model);
|
|
31
31
|
return groupModel._source;
|
|
32
32
|
});
|
|
33
|
-
(0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:model:measure:get", async ({ type }) => {
|
|
34
|
-
const measureModel = await this.getMeasure(type);
|
|
33
|
+
(0, kuzzle_plugin_commons_1.onAsk)("ask:device-manager:model:measure:get", async ({ type, engineId }) => {
|
|
34
|
+
const measureModel = await this.getMeasure(type, engineId);
|
|
35
35
|
return measureModel._source;
|
|
36
36
|
});
|
|
37
37
|
const genericModelsHandler = async (documents, request) => {
|
|
38
38
|
const { index, collection } = request.input.args;
|
|
39
|
-
if (index === this.config.
|
|
39
|
+
if (index === this.config.platformIndex && collection === "models") {
|
|
40
40
|
const models = documents.map((elt) => {
|
|
41
41
|
return elt._source;
|
|
42
42
|
});
|
|
@@ -48,7 +48,7 @@ class ModelService extends shared_1.BaseService {
|
|
|
48
48
|
this.app.pipe.register("generic:document:beforeUpdate", genericModelsHandler);
|
|
49
49
|
this.app.hook.register("generic:document:afterUpdate", async (documents, request) => {
|
|
50
50
|
const { index, collection } = request.input.args;
|
|
51
|
-
if (index === this.config.
|
|
51
|
+
if (index === this.config.platformIndex && collection === "models") {
|
|
52
52
|
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:updateAll");
|
|
53
53
|
}
|
|
54
54
|
});
|
|
@@ -105,7 +105,57 @@ class ModelService extends shared_1.BaseService {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
checkDefaultValues(metadataMappings, defaultMetadata) {
|
|
109
|
+
const flattenedMetadataMappings = (0, shared_1.flattenObject)(metadataMappings);
|
|
110
|
+
const metadata = Object.keys(JSON.parse(JSON.stringify(flattenedMetadataMappings)
|
|
111
|
+
.replace(/properties\./g, "")
|
|
112
|
+
.replace(/\.type/g, "")));
|
|
113
|
+
const values = Object.keys((0, shared_1.flattenObject)(defaultMetadata));
|
|
114
|
+
for (let i = 0; i < values.length; i++) {
|
|
115
|
+
const key = values[i];
|
|
116
|
+
// ? Check if the exact key exists in the metadata
|
|
117
|
+
if (!metadata.includes(key)) {
|
|
118
|
+
// ? Extract base key for complex types like geo_point or geo_shape
|
|
119
|
+
const baseKey = key.includes(".") ? key.split(".")[0] : key;
|
|
120
|
+
// ? Check if the base key is in the metadata
|
|
121
|
+
if (!metadata.includes(baseKey)) {
|
|
122
|
+
throw new kuzzle_1.BadRequestError(`The default value "${key}" is not in the metadata mappings.`);
|
|
123
|
+
}
|
|
124
|
+
// ? Accept nested properties for geo_point or geo_shape
|
|
125
|
+
const baseKeyMetadata = flattenedMetadataMappings[`${baseKey}.type`];
|
|
126
|
+
if (baseKeyMetadata === "geo_point" ||
|
|
127
|
+
baseKeyMetadata === "geo_shape") {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
throw new kuzzle_1.BadRequestError(`The default value "${values[i]}" is not in the metadata mappings.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
checkGroupAffinity(affinity) {
|
|
135
|
+
const { type, strict, models } = affinity;
|
|
136
|
+
if (!type || strict === undefined || !models) {
|
|
137
|
+
throw new kuzzle_1.BadRequestError(`The group affinity must specify a type array, models and strictness`);
|
|
138
|
+
}
|
|
139
|
+
if (!Array.isArray(type) ||
|
|
140
|
+
type.length > 2 ||
|
|
141
|
+
type.length < 1 ||
|
|
142
|
+
!type.every((t) => ["assets", "devices"].includes(t))) {
|
|
143
|
+
throw new kuzzle_1.BadRequestError(`The group type must be an array containing "assets" and/or "devices"`);
|
|
144
|
+
}
|
|
145
|
+
if (typeof strict !== "boolean") {
|
|
146
|
+
throw new kuzzle_1.BadRequestError(`The group affinity strict field must be a boolean`);
|
|
147
|
+
}
|
|
148
|
+
for (const t of type) {
|
|
149
|
+
if (!models[t] || !Array.isArray(models[t])) {
|
|
150
|
+
throw new kuzzle_1.BadRequestError(`The group affinity must contain an array for every present type`);
|
|
151
|
+
}
|
|
152
|
+
if (!models[t].every((model) => typeof model === "string")) {
|
|
153
|
+
throw new kuzzle_1.BadRequestError(`The group affinity models must be an array of models id`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { models, strict, type };
|
|
157
|
+
}
|
|
158
|
+
async writeAsset(engineGroups, model, metadataMappings, defaultMetadata, metadataDetails, metadataGroups, measures, tooltipModels, locales, engineIds) {
|
|
109
159
|
if (kuzzle_1.Inflector.pascalCase(model) !== model) {
|
|
110
160
|
throw new kuzzle_1.BadRequestError(`Asset model "${model}" must be PascalCase.`);
|
|
111
161
|
}
|
|
@@ -113,6 +163,55 @@ class ModelService extends shared_1.BaseService {
|
|
|
113
163
|
if (duplicates.length > 0) {
|
|
114
164
|
throw new MeasuresNamesDuplicatesError_1.MeasuresNamesDuplicatesError("Asset model measures contain one or multiple duplicate measure name", duplicates);
|
|
115
165
|
}
|
|
166
|
+
const normalizedEngineGroups = engineGroups.includes("commons")
|
|
167
|
+
? ["commons"]
|
|
168
|
+
: engineGroups;
|
|
169
|
+
// Anti-shadowing: reject if a model with the same name exists at a different scope level
|
|
170
|
+
const isGlobal = normalizedEngineGroups.includes("commons") &&
|
|
171
|
+
(!engineIds || engineIds.length === 0);
|
|
172
|
+
const isTenantScoped = engineIds && engineIds.length > 0;
|
|
173
|
+
const isGroupScoped = !isGlobal && !isTenantScoped;
|
|
174
|
+
await this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.MODELS);
|
|
175
|
+
const existing = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, {
|
|
176
|
+
query: {
|
|
177
|
+
bool: {
|
|
178
|
+
must: [
|
|
179
|
+
{ term: { type: "asset" } },
|
|
180
|
+
{ term: { "asset.model": model } },
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
}, { size: 10 });
|
|
185
|
+
for (const hit of existing.hits) {
|
|
186
|
+
const doc = hit._source;
|
|
187
|
+
const docIsGlobal = doc.engineGroups?.includes("commons") &&
|
|
188
|
+
(!doc.engineIds || doc.engineIds.length === 0);
|
|
189
|
+
const docIsTenantScoped = doc.engineIds && doc.engineIds.length > 0;
|
|
190
|
+
const docIsGroupScoped = !docIsGlobal && !docIsTenantScoped;
|
|
191
|
+
// Same scope level: allow overwrite
|
|
192
|
+
if (isGlobal && docIsGlobal) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (isTenantScoped && docIsTenantScoped) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (isGroupScoped && docIsGroupScoped) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
// Different scope levels: reject
|
|
202
|
+
if (docIsGlobal) {
|
|
203
|
+
throw new kuzzle_1.BadRequestError(`Asset model "${model}" already exists as a global (commons) model. A model cannot exist at multiple scopes.`);
|
|
204
|
+
}
|
|
205
|
+
if (isGlobal) {
|
|
206
|
+
throw new kuzzle_1.BadRequestError(`Asset model "${model}" already exists at a non-global scope. A model cannot exist at multiple scopes.`);
|
|
207
|
+
}
|
|
208
|
+
if (isTenantScoped && docIsGroupScoped) {
|
|
209
|
+
throw new kuzzle_1.BadRequestError(`Asset model "${model}" already exists at group scope. A model cannot be both group-scoped and tenant-scoped.`);
|
|
210
|
+
}
|
|
211
|
+
if (isGroupScoped && docIsTenantScoped) {
|
|
212
|
+
throw new kuzzle_1.BadRequestError(`Asset model "${model}" already exists at tenant scope. A model cannot be both group-scoped and tenant-scoped.`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
116
215
|
const modelContent = {
|
|
117
216
|
asset: {
|
|
118
217
|
defaultMetadata,
|
|
@@ -124,7 +223,8 @@ class ModelService extends shared_1.BaseService {
|
|
|
124
223
|
model,
|
|
125
224
|
tooltipModels,
|
|
126
225
|
},
|
|
127
|
-
|
|
226
|
+
engineGroups: normalizedEngineGroups,
|
|
227
|
+
...(engineIds?.length ? { engineIds } : {}),
|
|
128
228
|
type: "asset",
|
|
129
229
|
};
|
|
130
230
|
this.checkDefaultValues(metadataMappings, defaultMetadata);
|
|
@@ -132,40 +232,14 @@ class ModelService extends shared_1.BaseService {
|
|
|
132
232
|
if (conflicts.length > 0) {
|
|
133
233
|
throw new MappingsConflictsError_1.MappingsConflictsError(`New assets mappings are causing conflicts`, conflicts);
|
|
134
234
|
}
|
|
135
|
-
const assetModel = await this.sdk.document.createOrReplace(this.config.
|
|
136
|
-
await this.sdk.collection.refresh(this.config.
|
|
235
|
+
const assetModel = await this.sdk.document.createOrReplace(this.config.platformIndex, plugin_1.InternalCollection.MODELS, ModelSerializer_1.ModelSerializer.id("asset", modelContent), modelContent);
|
|
236
|
+
await this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.MODELS);
|
|
137
237
|
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:updateAll");
|
|
138
238
|
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:asset:refresh-model", {
|
|
139
239
|
assetModel: assetModel._source,
|
|
140
240
|
});
|
|
141
241
|
return assetModel;
|
|
142
242
|
}
|
|
143
|
-
checkDefaultValues(metadataMappings, defaultMetadata) {
|
|
144
|
-
const flattenedMetadataMappings = (0, shared_1.flattenObject)(metadataMappings);
|
|
145
|
-
const metadata = Object.keys(JSON.parse(JSON.stringify(flattenedMetadataMappings)
|
|
146
|
-
.replace(/properties\./g, "")
|
|
147
|
-
.replace(/\.type/g, "")));
|
|
148
|
-
const values = Object.keys((0, shared_1.flattenObject)(defaultMetadata));
|
|
149
|
-
for (let i = 0; i < values.length; i++) {
|
|
150
|
-
const key = values[i];
|
|
151
|
-
// ? Check if the exact key exists in the metadata
|
|
152
|
-
if (!metadata.includes(key)) {
|
|
153
|
-
// ? Extract base key for complex types like geo_point or geo_shape
|
|
154
|
-
const baseKey = key.includes(".") ? key.split(".")[0] : key;
|
|
155
|
-
// ? Check if the base key is in the metadata
|
|
156
|
-
if (!metadata.includes(baseKey)) {
|
|
157
|
-
throw new kuzzle_1.BadRequestError(`The default value "${key}" is not in the metadata mappings.`);
|
|
158
|
-
}
|
|
159
|
-
// ? Accept nested properties for geo_point or geo_shape
|
|
160
|
-
const baseKeyMetadata = flattenedMetadataMappings[`${baseKey}.type`];
|
|
161
|
-
if (baseKeyMetadata === "geo_point" ||
|
|
162
|
-
baseKeyMetadata === "geo_shape") {
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
throw new kuzzle_1.BadRequestError(`The default value "${values[i]}" is not in the metadata mappings.`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
243
|
async writeDevice(model, metadataMappings, defaultMetadata, metadataDetails, metadataGroups, measures) {
|
|
170
244
|
if (kuzzle_1.Inflector.pascalCase(model) !== model) {
|
|
171
245
|
throw new kuzzle_1.BadRequestError(`Device model "${model}" must be PascalCase.`);
|
|
@@ -189,18 +263,26 @@ class ModelService extends shared_1.BaseService {
|
|
|
189
263
|
if (conflicts.length > 0) {
|
|
190
264
|
throw new MappingsConflictsError_1.MappingsConflictsError(`New devices mappings are causing conflicts`, conflicts);
|
|
191
265
|
}
|
|
192
|
-
const deviceModel = await this.sdk.document.createOrReplace(this.config.
|
|
193
|
-
await this.sdk.collection.refresh(this.config.
|
|
266
|
+
const deviceModel = await this.sdk.document.createOrReplace(this.config.platformIndex, plugin_1.InternalCollection.MODELS, ModelSerializer_1.ModelSerializer.id("device", modelContent), modelContent);
|
|
267
|
+
await this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.MODELS);
|
|
194
268
|
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:updateAll");
|
|
269
|
+
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:device:refresh-model", {
|
|
270
|
+
deviceModel: modelContent,
|
|
271
|
+
});
|
|
195
272
|
return deviceModel;
|
|
196
273
|
}
|
|
197
|
-
async writeGroup(
|
|
274
|
+
async writeGroup(engineGroups, model, affinity, metadataMappings, defaultMetadata, metadataDetails, metadataGroups) {
|
|
198
275
|
if (kuzzle_1.Inflector.pascalCase(model) !== model) {
|
|
199
276
|
throw new kuzzle_1.BadRequestError(`Group model "${model}" must be PascalCase.`);
|
|
200
277
|
}
|
|
278
|
+
if (engineGroups.includes("commons")) {
|
|
279
|
+
engineGroups = ["commons"];
|
|
280
|
+
}
|
|
281
|
+
const groupAffinity = this.checkGroupAffinity(affinity);
|
|
201
282
|
const modelContent = {
|
|
202
|
-
|
|
283
|
+
engineGroups,
|
|
203
284
|
group: {
|
|
285
|
+
affinity: groupAffinity,
|
|
204
286
|
defaultMetadata,
|
|
205
287
|
metadataDetails,
|
|
206
288
|
metadataGroups,
|
|
@@ -213,12 +295,12 @@ class ModelService extends shared_1.BaseService {
|
|
|
213
295
|
if (conflicts.length > 0) {
|
|
214
296
|
throw new MappingsConflictsError_1.MappingsConflictsError(`New group mappings are causing conflicts`, conflicts);
|
|
215
297
|
}
|
|
216
|
-
const groupModel = await this.sdk.document.createOrReplace(this.config.
|
|
217
|
-
await this.sdk.collection.refresh(this.config.
|
|
298
|
+
const groupModel = await this.sdk.document.createOrReplace(this.config.platformIndex, plugin_1.InternalCollection.MODELS, ModelSerializer_1.ModelSerializer.id("group", modelContent), modelContent);
|
|
299
|
+
await this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.MODELS);
|
|
218
300
|
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:updateAll");
|
|
219
301
|
return groupModel;
|
|
220
302
|
}
|
|
221
|
-
async writeMeasure(type, valuesMappings, validationSchema, valuesDetails, locales) {
|
|
303
|
+
async writeMeasure(type, valuesMappings, validationSchema, valuesDetails, locales, engineIds) {
|
|
222
304
|
const modelContent = {
|
|
223
305
|
measure: {
|
|
224
306
|
locales,
|
|
@@ -228,6 +310,11 @@ class ModelService extends shared_1.BaseService {
|
|
|
228
310
|
},
|
|
229
311
|
type: "measure",
|
|
230
312
|
};
|
|
313
|
+
if (engineIds?.length) {
|
|
314
|
+
modelContent.engineIds = engineIds;
|
|
315
|
+
}
|
|
316
|
+
// Anti-shadowing: a measure type must be either global or tenant-scoped, not both
|
|
317
|
+
await this.checkMeasureShadowing(type, engineIds);
|
|
231
318
|
if (validationSchema) {
|
|
232
319
|
try {
|
|
233
320
|
(0, AJValidator_1.addSchemaToCache)(type, validationSchema);
|
|
@@ -241,25 +328,25 @@ class ModelService extends shared_1.BaseService {
|
|
|
241
328
|
if (conflicts.length > 0) {
|
|
242
329
|
throw new MappingsConflictsError_1.MappingsConflictsError(`New assets mappings are causing conflicts`, conflicts);
|
|
243
330
|
}
|
|
244
|
-
const measureModel = await this.sdk.document.createOrReplace(this.config.
|
|
245
|
-
await this.sdk.collection.refresh(this.config.
|
|
331
|
+
const measureModel = await this.sdk.document.createOrReplace(this.config.platformIndex, plugin_1.InternalCollection.MODELS, ModelSerializer_1.ModelSerializer.id("measure", modelContent), modelContent);
|
|
332
|
+
await this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.MODELS);
|
|
246
333
|
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:updateAll");
|
|
247
334
|
return measureModel;
|
|
248
335
|
}
|
|
249
336
|
async deleteAsset(_id) {
|
|
250
|
-
await this.sdk.document.delete(this.config.
|
|
337
|
+
await this.sdk.document.delete(this.config.platformIndex, plugin_1.InternalCollection.MODELS, _id);
|
|
251
338
|
}
|
|
252
339
|
async deleteDevice(_id) {
|
|
253
|
-
await this.sdk.document.delete(this.config.
|
|
340
|
+
await this.sdk.document.delete(this.config.platformIndex, plugin_1.InternalCollection.MODELS, _id);
|
|
254
341
|
}
|
|
255
342
|
async deleteGroup(_id) {
|
|
256
|
-
await this.sdk.document.delete(this.config.
|
|
343
|
+
await this.sdk.document.delete(this.config.platformIndex, plugin_1.InternalCollection.MODELS, _id);
|
|
257
344
|
}
|
|
258
345
|
async deleteMeasure(_id) {
|
|
259
|
-
await this.sdk.document.delete(this.config.
|
|
346
|
+
await this.sdk.document.delete(this.config.platformIndex, plugin_1.InternalCollection.MODELS, _id);
|
|
260
347
|
}
|
|
261
|
-
async listAsset(
|
|
262
|
-
const result = await this.searchAssets(
|
|
348
|
+
async listAsset(engineGroups, engineId) {
|
|
349
|
+
const result = await this.searchAssets(engineGroups, engineId, {
|
|
263
350
|
searchBody: {
|
|
264
351
|
sort: { "asset.model": "asc" },
|
|
265
352
|
},
|
|
@@ -276,8 +363,8 @@ class ModelService extends shared_1.BaseService {
|
|
|
276
363
|
});
|
|
277
364
|
return result.hits;
|
|
278
365
|
}
|
|
279
|
-
async listGroups(
|
|
280
|
-
const result = await this.searchGroups(
|
|
366
|
+
async listGroups(engineGroups) {
|
|
367
|
+
const result = await this.searchGroups(engineGroups, {
|
|
281
368
|
searchBody: {
|
|
282
369
|
sort: { "group.model": "asc" },
|
|
283
370
|
},
|
|
@@ -285,8 +372,8 @@ class ModelService extends shared_1.BaseService {
|
|
|
285
372
|
});
|
|
286
373
|
return result.hits;
|
|
287
374
|
}
|
|
288
|
-
async listMeasures() {
|
|
289
|
-
const result = await this.searchMeasures({
|
|
375
|
+
async listMeasures(engineId) {
|
|
376
|
+
const result = await this.searchMeasures(engineId, {
|
|
290
377
|
searchBody: {
|
|
291
378
|
sort: { "measure.type": "asc" },
|
|
292
379
|
},
|
|
@@ -294,24 +381,62 @@ class ModelService extends shared_1.BaseService {
|
|
|
294
381
|
});
|
|
295
382
|
return result.hits;
|
|
296
383
|
}
|
|
297
|
-
async searchAssets(
|
|
384
|
+
async searchAssets(engineGroups, engineId, searchParams) {
|
|
385
|
+
const scopeFilter = engineId
|
|
386
|
+
? {
|
|
387
|
+
bool: {
|
|
388
|
+
should: [
|
|
389
|
+
{
|
|
390
|
+
bool: {
|
|
391
|
+
must: [
|
|
392
|
+
{ term: { engineIds: engineId } },
|
|
393
|
+
{ terms: { engineGroups } },
|
|
394
|
+
],
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
bool: {
|
|
399
|
+
must: [{ terms: { engineGroups } }],
|
|
400
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
bool: {
|
|
405
|
+
must: [{ term: { engineGroups: "commons" } }],
|
|
406
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
}
|
|
412
|
+
: {
|
|
413
|
+
bool: {
|
|
414
|
+
should: [
|
|
415
|
+
{
|
|
416
|
+
bool: {
|
|
417
|
+
must: [{ terms: { engineGroups } }],
|
|
418
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
bool: {
|
|
423
|
+
must: [{ term: { engineGroups: "commons" } }],
|
|
424
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
},
|
|
429
|
+
};
|
|
298
430
|
const query = {
|
|
299
431
|
bool: {
|
|
300
432
|
must: [
|
|
301
433
|
searchParams.searchBody.query,
|
|
302
|
-
{
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
should: [
|
|
306
|
-
{ match: { engineGroup } },
|
|
307
|
-
{ match: { engineGroup: "commons" } },
|
|
308
|
-
],
|
|
309
|
-
},
|
|
310
|
-
},
|
|
311
|
-
],
|
|
434
|
+
{ term: { type: "asset" } },
|
|
435
|
+
scopeFilter,
|
|
436
|
+
].filter(Boolean),
|
|
312
437
|
},
|
|
313
438
|
};
|
|
314
|
-
return this.sdk.document.search(this.config.
|
|
439
|
+
return this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, {
|
|
315
440
|
...searchParams.searchBody,
|
|
316
441
|
query,
|
|
317
442
|
}, {
|
|
@@ -324,10 +449,13 @@ class ModelService extends shared_1.BaseService {
|
|
|
324
449
|
async searchDevices(searchParams) {
|
|
325
450
|
const query = {
|
|
326
451
|
bool: {
|
|
327
|
-
must: [
|
|
452
|
+
must: [
|
|
453
|
+
searchParams.searchBody.query,
|
|
454
|
+
{ term: { type: "device" } },
|
|
455
|
+
].filter(Boolean),
|
|
328
456
|
},
|
|
329
457
|
};
|
|
330
|
-
return this.sdk.document.search(this.config.
|
|
458
|
+
return this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, {
|
|
331
459
|
...searchParams.searchBody,
|
|
332
460
|
query,
|
|
333
461
|
}, {
|
|
@@ -337,24 +465,24 @@ class ModelService extends shared_1.BaseService {
|
|
|
337
465
|
size: searchParams.size,
|
|
338
466
|
});
|
|
339
467
|
}
|
|
340
|
-
async searchGroups(
|
|
468
|
+
async searchGroups(engineGroups, searchParams) {
|
|
341
469
|
const query = {
|
|
342
470
|
bool: {
|
|
343
471
|
must: [
|
|
344
472
|
searchParams.searchBody.query,
|
|
345
|
-
{
|
|
473
|
+
{ term: { type: "group" } },
|
|
346
474
|
{
|
|
347
475
|
bool: {
|
|
348
476
|
should: [
|
|
349
|
-
{
|
|
350
|
-
{
|
|
477
|
+
{ terms: { engineGroups } },
|
|
478
|
+
{ term: { engineGroups: "commons" } },
|
|
351
479
|
],
|
|
352
480
|
},
|
|
353
481
|
},
|
|
354
|
-
],
|
|
482
|
+
].filter(Boolean),
|
|
355
483
|
},
|
|
356
484
|
};
|
|
357
|
-
return this.sdk.document.search(this.config.
|
|
485
|
+
return this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, {
|
|
358
486
|
...searchParams.searchBody,
|
|
359
487
|
query,
|
|
360
488
|
}, {
|
|
@@ -364,13 +492,31 @@ class ModelService extends shared_1.BaseService {
|
|
|
364
492
|
size: searchParams.size,
|
|
365
493
|
});
|
|
366
494
|
}
|
|
367
|
-
async searchMeasures(searchParams) {
|
|
495
|
+
async searchMeasures(engineId, searchParams) {
|
|
496
|
+
const scopeFilter = engineId
|
|
497
|
+
? {
|
|
498
|
+
bool: {
|
|
499
|
+
should: [
|
|
500
|
+
{ term: { engineIds: engineId } },
|
|
501
|
+
{ bool: { must_not: [{ exists: { field: "engineIds" } }] } },
|
|
502
|
+
],
|
|
503
|
+
},
|
|
504
|
+
}
|
|
505
|
+
: {
|
|
506
|
+
bool: {
|
|
507
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
508
|
+
},
|
|
509
|
+
};
|
|
368
510
|
const query = {
|
|
369
511
|
bool: {
|
|
370
|
-
must: [
|
|
512
|
+
must: [
|
|
513
|
+
searchParams.searchBody.query,
|
|
514
|
+
{ term: { type: "measure" } },
|
|
515
|
+
scopeFilter,
|
|
516
|
+
].filter(Boolean),
|
|
371
517
|
},
|
|
372
518
|
};
|
|
373
|
-
return this.sdk.document.search(this.config.
|
|
519
|
+
return this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, {
|
|
374
520
|
...searchParams.searchBody,
|
|
375
521
|
query,
|
|
376
522
|
}, {
|
|
@@ -387,7 +533,7 @@ class ModelService extends shared_1.BaseService {
|
|
|
387
533
|
{ equals: { "asset.model": model } },
|
|
388
534
|
],
|
|
389
535
|
};
|
|
390
|
-
const result = await this.sdk.document.search(this.config.
|
|
536
|
+
const result = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query }, { lang: "koncorde", size: 1 });
|
|
391
537
|
return result.total > 0;
|
|
392
538
|
}
|
|
393
539
|
async deviceExists(model) {
|
|
@@ -397,27 +543,53 @@ class ModelService extends shared_1.BaseService {
|
|
|
397
543
|
{ equals: { "device.model": model } },
|
|
398
544
|
],
|
|
399
545
|
};
|
|
400
|
-
const result = await this.sdk.document.search(this.config.
|
|
546
|
+
const result = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query }, { lang: "koncorde", size: 1 });
|
|
401
547
|
return result.total > 0;
|
|
402
548
|
}
|
|
403
|
-
async getAsset(
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
549
|
+
async getAsset(engineGroups, engineId, model) {
|
|
550
|
+
const baseFilter = [
|
|
551
|
+
{ term: { type: "asset" } },
|
|
552
|
+
{ term: { "asset.model": model } },
|
|
553
|
+
];
|
|
554
|
+
// Priority 1: tenant-scoped model for this specific engine
|
|
555
|
+
if (engineId) {
|
|
556
|
+
const tenantQuery = {
|
|
557
|
+
bool: {
|
|
558
|
+
must: [
|
|
559
|
+
...baseFilter,
|
|
560
|
+
{ terms: { engineGroups } },
|
|
561
|
+
{ term: { engineIds: engineId } },
|
|
410
562
|
],
|
|
411
563
|
},
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
564
|
+
};
|
|
565
|
+
const tenantResult = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query: tenantQuery }, { lang: "elasticsearch", size: 1 });
|
|
566
|
+
if (tenantResult.total > 0) {
|
|
567
|
+
return tenantResult.hits[0];
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
// Priority 2: group-scoped model (no engineIds field)
|
|
571
|
+
const groupQuery = {
|
|
572
|
+
bool: {
|
|
573
|
+
must: [...baseFilter, { terms: { engineGroups } }],
|
|
574
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
575
|
+
},
|
|
415
576
|
};
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
|
|
577
|
+
const groupResult = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query: groupQuery }, { lang: "elasticsearch", size: 1 });
|
|
578
|
+
if (groupResult.total > 0) {
|
|
579
|
+
return groupResult.hits[0];
|
|
419
580
|
}
|
|
420
|
-
|
|
581
|
+
// Priority 3: commons model
|
|
582
|
+
const commonsQuery = {
|
|
583
|
+
bool: {
|
|
584
|
+
must: [...baseFilter, { term: { engineGroups: "commons" } }],
|
|
585
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
586
|
+
},
|
|
587
|
+
};
|
|
588
|
+
const commonsResult = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query: commonsQuery }, { lang: "elasticsearch", size: 1 });
|
|
589
|
+
if (commonsResult.total > 0) {
|
|
590
|
+
return commonsResult.hits[0];
|
|
591
|
+
}
|
|
592
|
+
throw new kuzzle_1.NotFoundError(`Unknown Asset model "${model}" for engineGroups ${engineGroups.join(", ")}.`);
|
|
421
593
|
}
|
|
422
594
|
async getDevice(model) {
|
|
423
595
|
const query = {
|
|
@@ -426,7 +598,7 @@ class ModelService extends shared_1.BaseService {
|
|
|
426
598
|
{ equals: { "device.model": model } },
|
|
427
599
|
],
|
|
428
600
|
};
|
|
429
|
-
const result = await this.sdk.document.search(this.config.
|
|
601
|
+
const result = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query }, { lang: "koncorde", size: 1 });
|
|
430
602
|
if (result.total === 0) {
|
|
431
603
|
throw new kuzzle_1.NotFoundError(`Unknown Device model "${model}".`);
|
|
432
604
|
}
|
|
@@ -439,7 +611,7 @@ class ModelService extends shared_1.BaseService {
|
|
|
439
611
|
{ equals: { "group.model": model } },
|
|
440
612
|
],
|
|
441
613
|
};
|
|
442
|
-
const result = await this.sdk.document.search(this.config.
|
|
614
|
+
const result = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query }, { lang: "koncorde", size: 1 });
|
|
443
615
|
if (result.total === 0) {
|
|
444
616
|
throw new kuzzle_1.NotFoundError(`Unknown Group model "${model}".`);
|
|
445
617
|
}
|
|
@@ -448,31 +620,92 @@ class ModelService extends shared_1.BaseService {
|
|
|
448
620
|
}
|
|
449
621
|
return result.hits[0];
|
|
450
622
|
}
|
|
451
|
-
async getMeasure(type) {
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
623
|
+
async getMeasure(type, engineId) {
|
|
624
|
+
const baseFilter = [
|
|
625
|
+
{ term: { type: "measure" } },
|
|
626
|
+
{ term: { "measure.type": type } },
|
|
627
|
+
];
|
|
628
|
+
const scopeFilter = engineId
|
|
629
|
+
? {
|
|
630
|
+
bool: {
|
|
631
|
+
should: [
|
|
632
|
+
{ term: { engineIds: engineId } },
|
|
633
|
+
{ bool: { must_not: [{ exists: { field: "engineIds" } }] } },
|
|
634
|
+
],
|
|
635
|
+
},
|
|
636
|
+
}
|
|
637
|
+
: {
|
|
638
|
+
bool: {
|
|
639
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
640
|
+
},
|
|
641
|
+
};
|
|
642
|
+
const result = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, {
|
|
643
|
+
query: {
|
|
644
|
+
bool: {
|
|
645
|
+
must: [...baseFilter, scopeFilter],
|
|
646
|
+
},
|
|
647
|
+
},
|
|
648
|
+
}, { lang: "elasticsearch", size: 1 });
|
|
649
|
+
if (result.total > 0) {
|
|
650
|
+
return result.hits[0];
|
|
651
|
+
}
|
|
652
|
+
throw new kuzzle_1.NotFoundError(`Unknown Measure type "${type}".`);
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Checks that creating/updating a measure model does not shadow an existing
|
|
656
|
+
* one at a different scope (global vs tenant-scoped).
|
|
657
|
+
*/
|
|
658
|
+
async checkMeasureShadowing(type, engineIds) {
|
|
659
|
+
const isNewTenantScoped = engineIds && engineIds.length > 0;
|
|
660
|
+
// Check for existing measures of the same type at the opposite scope
|
|
661
|
+
const conflictQuery = isNewTenantScoped
|
|
662
|
+
? {
|
|
663
|
+
// New is tenant-scoped → reject if a global measure exists
|
|
664
|
+
bool: {
|
|
665
|
+
must: [
|
|
666
|
+
{ term: { type: "measure" } },
|
|
667
|
+
{ term: { "measure.type": type } },
|
|
668
|
+
],
|
|
669
|
+
must_not: [{ exists: { field: "engineIds" } }],
|
|
670
|
+
},
|
|
671
|
+
}
|
|
672
|
+
: {
|
|
673
|
+
// New is global → reject if any tenant-scoped measure exists
|
|
674
|
+
bool: {
|
|
675
|
+
must: [
|
|
676
|
+
{ term: { type: "measure" } },
|
|
677
|
+
{ term: { "measure.type": type } },
|
|
678
|
+
{ exists: { field: "engineIds" } },
|
|
679
|
+
],
|
|
680
|
+
},
|
|
681
|
+
};
|
|
682
|
+
const result = await this.sdk.document.search(this.config.platformIndex, plugin_1.InternalCollection.MODELS, { query: conflictQuery }, { lang: "elasticsearch", size: 1 });
|
|
683
|
+
if (result.total > 0) {
|
|
684
|
+
const scope = isNewTenantScoped ? "global" : "tenant-scoped";
|
|
685
|
+
throw new kuzzle_1.BadRequestError(`Measure type "${type}" already exists as a ${scope} measure. A measure type cannot be both global and tenant-scoped.`);
|
|
461
686
|
}
|
|
462
|
-
return result.hits[0];
|
|
463
687
|
}
|
|
464
688
|
/**
|
|
465
689
|
* Update an asset model
|
|
466
690
|
*/
|
|
467
|
-
async updateAsset(
|
|
691
|
+
async updateAsset(engineGroups, engineId, model, metadataMappings, defaultMetadata, metadataDetails, metadataGroups, measures, tooltipModels, locales, request) {
|
|
468
692
|
if (kuzzle_1.Inflector.pascalCase(model) !== model) {
|
|
469
693
|
throw new kuzzle_1.BadRequestError(`Asset model "${model}" must be PascalCase.`);
|
|
470
694
|
}
|
|
471
695
|
this.checkDefaultValues(metadataMappings, defaultMetadata);
|
|
472
|
-
const existingAsset = await this.getAsset(
|
|
696
|
+
const existingAsset = await this.getAsset(engineGroups, engineId, model);
|
|
473
697
|
// The field must be deleted if an element of the table is to be deleted
|
|
474
|
-
await this.sdk.document.deleteFields(this.config.
|
|
698
|
+
await this.sdk.document.deleteFields(this.config.platformIndex, plugin_1.InternalCollection.MODELS, existingAsset._id, [
|
|
699
|
+
"asset.tooltipModels",
|
|
700
|
+
"asset.metadataMappings",
|
|
701
|
+
"asset.defaultMetadata",
|
|
702
|
+
"asset.metadataDetails",
|
|
703
|
+
"asset.metadataGroups",
|
|
704
|
+
], { source: true });
|
|
475
705
|
const measuresUpdated = measures.length === 0 ? existingAsset._source.asset.measures : measures;
|
|
706
|
+
const normalizedEngineGroups = engineGroups.includes("commons")
|
|
707
|
+
? ["commons"]
|
|
708
|
+
: engineGroups;
|
|
476
709
|
const assetModelContent = {
|
|
477
710
|
asset: {
|
|
478
711
|
defaultMetadata,
|
|
@@ -484,7 +717,8 @@ class ModelService extends shared_1.BaseService {
|
|
|
484
717
|
model,
|
|
485
718
|
tooltipModels,
|
|
486
719
|
},
|
|
487
|
-
|
|
720
|
+
engineGroups: normalizedEngineGroups,
|
|
721
|
+
engineIds: existingAsset._source.engineIds,
|
|
488
722
|
type: "asset",
|
|
489
723
|
};
|
|
490
724
|
const assetModel = {
|
|
@@ -497,13 +731,16 @@ class ModelService extends shared_1.BaseService {
|
|
|
497
731
|
}
|
|
498
732
|
const endDocument = await this.updateDocument(request, assetModel, {
|
|
499
733
|
collection: plugin_1.InternalCollection.MODELS,
|
|
500
|
-
engineId: this.config.
|
|
734
|
+
engineId: this.config.platformIndex,
|
|
501
735
|
}, { source: true });
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
736
|
+
// ? Only update engineIds and refresh asset models when necessary
|
|
737
|
+
if (Object.keys(metadataMappings).length > 0 || measures.length > 0) {
|
|
738
|
+
await this.sdk.collection.refresh(this.config.platformIndex, plugin_1.InternalCollection.MODELS);
|
|
739
|
+
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:engine:updateAll");
|
|
740
|
+
await (0, kuzzle_plugin_commons_1.ask)("ask:device-manager:asset:refresh-model", {
|
|
741
|
+
assetModel: endDocument._source,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
507
744
|
return endDocument;
|
|
508
745
|
}
|
|
509
746
|
}
|