@twin.org/telemetry-service 0.9.2-next.7 → 0.9.2-next.8

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.
@@ -1,5 +1,5 @@
1
1
  import { ContextIdKeys, ContextIdStore } from "@twin.org/context";
2
- import { ComponentFactory, Guards, Is } from "@twin.org/core";
2
+ import { ComponentFactory, Guards, Is, NotImplementedError } from "@twin.org/core";
3
3
  import { TelemetryConnectorFactory } from "@twin.org/telemetry-models";
4
4
  /**
5
5
  * Service for performing telemetry operations to a connector.
@@ -60,7 +60,11 @@ export class TelemetryService {
60
60
  */
61
61
  async getMetric(id) {
62
62
  Guards.stringValue(TelemetryService.CLASS_NAME, "id", id);
63
- return this._telemetryConnector.getMetric(id);
63
+ const boundGetMetric = this._telemetryConnector.getMetric?.bind(this._telemetryConnector);
64
+ if (Is.undefined(boundGetMetric)) {
65
+ throw new NotImplementedError(TelemetryService.CLASS_NAME, "getMetric");
66
+ }
67
+ return boundGetMetric(id);
64
68
  }
65
69
  /**
66
70
  * Get a specific metric value by its id.
@@ -71,7 +75,11 @@ export class TelemetryService {
71
75
  async getMetricValue(id, valueId) {
72
76
  Guards.stringValue(TelemetryService.CLASS_NAME, "id", id);
73
77
  Guards.stringValue(TelemetryService.CLASS_NAME, "valueId", valueId);
74
- return this._telemetryConnector.getMetricValue(id, valueId);
78
+ const boundGetMetricValue = this._telemetryConnector.getMetricValue?.bind(this._telemetryConnector);
79
+ if (Is.undefined(boundGetMetricValue)) {
80
+ throw new NotImplementedError(TelemetryService.CLASS_NAME, "getMetricValue");
81
+ }
82
+ return boundGetMetricValue(id, valueId);
75
83
  }
76
84
  /**
77
85
  * Update metric.
@@ -114,7 +122,11 @@ export class TelemetryService {
114
122
  * @throws NotImplementedError if the implementation does not support retrieval.
115
123
  */
116
124
  async query(type, cursor, limit) {
117
- return this._telemetryConnector.query(type, cursor, limit);
125
+ const boundQuery = this._telemetryConnector.query?.bind(this._telemetryConnector);
126
+ if (Is.undefined(boundQuery)) {
127
+ throw new NotImplementedError(TelemetryService.CLASS_NAME, "query");
128
+ }
129
+ return boundQuery(type, cursor, limit);
118
130
  }
119
131
  /**
120
132
  * Query the metric values.
@@ -129,7 +141,11 @@ export class TelemetryService {
129
141
  */
130
142
  async queryValues(id, timeStart, timeEnd, cursor, limit) {
131
143
  Guards.stringValue(TelemetryService.CLASS_NAME, "id", id);
132
- return this._telemetryConnector.queryValues(id, timeStart, timeEnd, cursor, limit);
144
+ const boundQueryValues = this._telemetryConnector.queryValues?.bind(this._telemetryConnector);
145
+ if (Is.undefined(boundQueryValues)) {
146
+ throw new NotImplementedError(TelemetryService.CLASS_NAME, "queryValues");
147
+ }
148
+ return boundQueryValues(id, timeStart, timeEnd, cursor, limit);
133
149
  }
134
150
  }
135
151
  //# sourceMappingURL=telemetryService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetryService.js","sourceRoot":"","sources":["../../src/telemetryService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IPlatformComponent } from \"@twin.org/api-models\";\nimport { ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { ComponentFactory, Guards, Is } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\tTelemetryConnectorFactory,\n\ttype ITelemetryComponent,\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\ttype ITelemetryMetricValue,\n\ttype MetricCounterOperation,\n\ttype MetricType\n} from \"@twin.org/telemetry-models\";\nimport type { ITelemetryServiceConstructorOptions } from \"./models/ITelemetryServiceConstructorOptions.js\";\n\n/**\n * Service for performing telemetry operations to a connector.\n */\nexport class TelemetryService implements ITelemetryComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TelemetryService>();\n\n\t/**\n\t * Telemetry connector used by the service.\n\t * @internal\n\t */\n\tprivate readonly _telemetryConnector: ITelemetryConnector;\n\n\t/**\n\t * Platform component.\n\t * @internal\n\t */\n\tprivate readonly _platformComponent: IPlatformComponent;\n\n\t/**\n\t * Create a new instance of TelemetryService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: ITelemetryServiceConstructorOptions) {\n\t\tthis._telemetryConnector = TelemetryConnectorFactory.get(\n\t\t\toptions?.telemetryConnectorType ?? \"telemetry\"\n\t\t);\n\t\tthis._platformComponent = ComponentFactory.get<IPlatformComponent>(\n\t\t\toptions?.platformComponentType ?? \"platform\"\n\t\t);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn TelemetryService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Create a new metric.\n\t * @param metric The metric details.\n\t * @returns A promise that resolves when the metric has been created.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(TelemetryService.CLASS_NAME, nameof(metric), metric);\n\n\t\t// If we don't have a tenant context ID and the tenant component is multi-tenant,\n\t\t// we consider the entry as per-tenant and run it in all the tenant context to ensure\n\t\t// the metric is created for each tenant.\n\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\tconst perTenant =\n\t\t\t!Is.stringValue(contextIds[ContextIdKeys.Tenant]) && this._platformComponent.isMultiTenant();\n\n\t\tif (perTenant) {\n\t\t\tawait this._platformComponent.execute(async () =>\n\t\t\t\tthis._telemetryConnector.createMetric(metric)\n\t\t\t);\n\t\t} else {\n\t\t\tawait this._telemetryConnector.createMetric(metric);\n\t\t}\n\t}\n\n\t/**\n\t * Get the metric details and it's most recent value.\n\t * @param id The metric id.\n\t * @returns The metric details and it's most recent value.\n\t */\n\tpublic async getMetric(id: string): Promise<{\n\t\tmetric: ITelemetryMetric;\n\t\tvalue: ITelemetryMetricValue;\n\t}> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.getMetric(id);\n\t}\n\n\t/**\n\t * Get a specific metric value by its id.\n\t * @param id The id of the metric.\n\t * @param valueId The id of the metric value.\n\t * @returns The metric value.\n\t */\n\tpublic async getMetricValue(id: string, valueId: string): Promise<ITelemetryMetricValue> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(valueId), valueId);\n\t\treturn this._telemetryConnector.getMetricValue(id, valueId);\n\t}\n\n\t/**\n\t * Update metric.\n\t * @param metric The metric details.\n\t * @returns A promise that resolves when the metric has been updated.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(TelemetryService.CLASS_NAME, nameof(metric), metric);\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(metric.id), metric.id);\n\t\treturn this._telemetryConnector.updateMetric(metric);\n\t}\n\n\t/**\n\t * Add a metric value.\n\t * @param id The id of the metric.\n\t * @param value The value for the add operation.\n\t * @param customData The custom data for the add operation.\n\t * @returns The created metric value id.\n\t */\n\tpublic async addMetricValue(\n\t\tid: string,\n\t\tvalue: MetricCounterOperation | number,\n\t\tcustomData?: { [key: string]: unknown }\n\t): Promise<string> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\tGuards.defined(TelemetryService.CLASS_NAME, nameof(value), value);\n\t\treturn this._telemetryConnector.addMetricValue(id, value, customData);\n\t}\n\n\t/**\n\t * Remove metric.\n\t * @param id The id of the metric.\n\t * @returns A promise that resolves when the metric and all its values have been removed.\n\t */\n\tpublic async removeMetric(id: string): Promise<void> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.removeMetric(id);\n\t}\n\n\t/**\n\t * Query the metrics.\n\t * @param type The type of the metric.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit Limit the number of entities to return.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t * @throws NotImplementedError if the implementation does not support retrieval.\n\t */\n\tpublic async query(\n\t\ttype?: MetricType,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The metrics.\n\t\t */\n\t\tentities: ITelemetryMetric[];\n\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more values.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\treturn this._telemetryConnector.query(type, cursor, limit);\n\t}\n\n\t/**\n\t * Query the metric values.\n\t * @param id The id of the metric.\n\t * @param timeStart The inclusive time as the start of the metric entries.\n\t * @param timeEnd The inclusive time as the end of the metric entries.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit Limit the number of entities to return.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t * @throws NotImplementedError if the implementation does not support retrieval.\n\t */\n\tpublic async queryValues(\n\t\tid: string,\n\t\ttimeStart?: number,\n\t\ttimeEnd?: number,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The metric details.\n\t\t */\n\t\tmetric: ITelemetryMetric;\n\t\t/**\n\t\t * The values for the metric.\n\t\t */\n\t\tentities: ITelemetryMetricValue[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more values.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.queryValues(id, timeStart, timeEnd, cursor, limit);\n\t}\n}\n"]}
1
+ {"version":3,"file":"telemetryService.js","sourceRoot":"","sources":["../../src/telemetryService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IPlatformComponent } from \"@twin.org/api-models\";\nimport { ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { ComponentFactory, Guards, Is, NotImplementedError } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\tTelemetryConnectorFactory,\n\ttype ITelemetryComponent,\n\ttype ITelemetryConnector,\n\ttype ITelemetryMetric,\n\ttype ITelemetryMetricValue,\n\ttype MetricCounterOperation,\n\ttype MetricType\n} from \"@twin.org/telemetry-models\";\nimport type { ITelemetryServiceConstructorOptions } from \"./models/ITelemetryServiceConstructorOptions.js\";\n\n/**\n * Service for performing telemetry operations to a connector.\n */\nexport class TelemetryService implements ITelemetryComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TelemetryService>();\n\n\t/**\n\t * Telemetry connector used by the service.\n\t * @internal\n\t */\n\tprivate readonly _telemetryConnector: ITelemetryConnector;\n\n\t/**\n\t * Platform component.\n\t * @internal\n\t */\n\tprivate readonly _platformComponent: IPlatformComponent;\n\n\t/**\n\t * Create a new instance of TelemetryService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: ITelemetryServiceConstructorOptions) {\n\t\tthis._telemetryConnector = TelemetryConnectorFactory.get(\n\t\t\toptions?.telemetryConnectorType ?? \"telemetry\"\n\t\t);\n\t\tthis._platformComponent = ComponentFactory.get<IPlatformComponent>(\n\t\t\toptions?.platformComponentType ?? \"platform\"\n\t\t);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn TelemetryService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Create a new metric.\n\t * @param metric The metric details.\n\t * @returns A promise that resolves when the metric has been created.\n\t */\n\tpublic async createMetric(metric: ITelemetryMetric): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(TelemetryService.CLASS_NAME, nameof(metric), metric);\n\n\t\t// If we don't have a tenant context ID and the tenant component is multi-tenant,\n\t\t// we consider the entry as per-tenant and run it in all the tenant context to ensure\n\t\t// the metric is created for each tenant.\n\t\tconst contextIds = (await ContextIdStore.getContextIds()) ?? {};\n\t\tconst perTenant =\n\t\t\t!Is.stringValue(contextIds[ContextIdKeys.Tenant]) && this._platformComponent.isMultiTenant();\n\n\t\tif (perTenant) {\n\t\t\tawait this._platformComponent.execute(async () =>\n\t\t\t\tthis._telemetryConnector.createMetric(metric)\n\t\t\t);\n\t\t} else {\n\t\t\tawait this._telemetryConnector.createMetric(metric);\n\t\t}\n\t}\n\n\t/**\n\t * Get the metric details and it's most recent value.\n\t * @param id The metric id.\n\t * @returns The metric details and it's most recent value.\n\t */\n\tpublic async getMetric(id: string): Promise<{\n\t\tmetric: ITelemetryMetric;\n\t\tvalue?: ITelemetryMetricValue;\n\t}> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\n\t\tconst boundGetMetric = this._telemetryConnector.getMetric?.bind(this._telemetryConnector);\n\t\tif (Is.undefined(boundGetMetric)) {\n\t\t\tthrow new NotImplementedError(TelemetryService.CLASS_NAME, \"getMetric\");\n\t\t}\n\t\treturn boundGetMetric(id);\n\t}\n\n\t/**\n\t * Get a specific metric value by its id.\n\t * @param id The id of the metric.\n\t * @param valueId The id of the metric value.\n\t * @returns The metric value.\n\t */\n\tpublic async getMetricValue(id: string, valueId: string): Promise<ITelemetryMetricValue> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(valueId), valueId);\n\n\t\tconst boundGetMetricValue = this._telemetryConnector.getMetricValue?.bind(\n\t\t\tthis._telemetryConnector\n\t\t);\n\t\tif (Is.undefined(boundGetMetricValue)) {\n\t\t\tthrow new NotImplementedError(TelemetryService.CLASS_NAME, \"getMetricValue\");\n\t\t}\n\t\treturn boundGetMetricValue(id, valueId);\n\t}\n\n\t/**\n\t * Update metric.\n\t * @param metric The metric details.\n\t * @returns A promise that resolves when the metric has been updated.\n\t */\n\tpublic async updateMetric(metric: Omit<ITelemetryMetric, \"type\">): Promise<void> {\n\t\tGuards.object<ITelemetryMetric>(TelemetryService.CLASS_NAME, nameof(metric), metric);\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(metric.id), metric.id);\n\t\treturn this._telemetryConnector.updateMetric(metric);\n\t}\n\n\t/**\n\t * Add a metric value.\n\t * @param id The id of the metric.\n\t * @param value The value for the add operation.\n\t * @param customData The custom data for the add operation.\n\t * @returns The created metric value id.\n\t */\n\tpublic async addMetricValue(\n\t\tid: string,\n\t\tvalue: MetricCounterOperation | number,\n\t\tcustomData?: { [key: string]: unknown }\n\t): Promise<string> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\tGuards.defined(TelemetryService.CLASS_NAME, nameof(value), value);\n\t\treturn this._telemetryConnector.addMetricValue(id, value, customData);\n\t}\n\n\t/**\n\t * Remove metric.\n\t * @param id The id of the metric.\n\t * @returns A promise that resolves when the metric and all its values have been removed.\n\t */\n\tpublic async removeMetric(id: string): Promise<void> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\t\treturn this._telemetryConnector.removeMetric(id);\n\t}\n\n\t/**\n\t * Query the metrics.\n\t * @param type The type of the metric.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit Limit the number of entities to return.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t * @throws NotImplementedError if the implementation does not support retrieval.\n\t */\n\tpublic async query(\n\t\ttype?: MetricType,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The metrics.\n\t\t */\n\t\tentities: ITelemetryMetric[];\n\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more values.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst boundQuery = this._telemetryConnector.query?.bind(this._telemetryConnector);\n\t\tif (Is.undefined(boundQuery)) {\n\t\t\tthrow new NotImplementedError(TelemetryService.CLASS_NAME, \"query\");\n\t\t}\n\t\treturn boundQuery(type, cursor, limit);\n\t}\n\n\t/**\n\t * Query the metric values.\n\t * @param id The id of the metric.\n\t * @param timeStart The inclusive time as the start of the metric entries.\n\t * @param timeEnd The inclusive time as the end of the metric entries.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit Limit the number of entities to return.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t * @throws NotImplementedError if the implementation does not support retrieval.\n\t */\n\tpublic async queryValues(\n\t\tid: string,\n\t\ttimeStart?: number,\n\t\ttimeEnd?: number,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The metric details.\n\t\t */\n\t\tmetric: ITelemetryMetric;\n\t\t/**\n\t\t * The values for the metric.\n\t\t */\n\t\tentities: ITelemetryMetricValue[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more values.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tGuards.stringValue(TelemetryService.CLASS_NAME, nameof(id), id);\n\n\t\tconst boundQueryValues = this._telemetryConnector.queryValues?.bind(this._telemetryConnector);\n\t\tif (Is.undefined(boundQueryValues)) {\n\t\t\tthrow new NotImplementedError(TelemetryService.CLASS_NAME, \"queryValues\");\n\t\t}\n\t\treturn boundQueryValues(id, timeStart, timeEnd, cursor, limit);\n\t}\n}\n"]}
@@ -31,7 +31,7 @@ export declare class TelemetryService implements ITelemetryComponent {
31
31
  */
32
32
  getMetric(id: string): Promise<{
33
33
  metric: ITelemetryMetric;
34
- value: ITelemetryMetricValue;
34
+ value?: ITelemetryMetricValue;
35
35
  }>;
36
36
  /**
37
37
  * Get a specific metric value by its id.
package/docs/changelog.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.2-next.8](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.9.2-next.7...telemetry-service-v0.9.2-next.8) (2026-08-21)
4
+
5
+
6
+ ### Features
7
+
8
+ * reduce mutex locks ([#94](https://github.com/iotaledger/twin-telemetry/issues/94)) ([8deb4eb](https://github.com/iotaledger/twin-telemetry/commit/8deb4eb51649ed7d9c0828a632115fede8c6a436))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/telemetry-models bumped from 0.9.2-next.7 to 0.9.2-next.8
16
+
3
17
  ## [0.9.2-next.7](https://github.com/iotaledger/twin-telemetry/compare/telemetry-service-v0.9.2-next.6...telemetry-service-v0.9.2-next.7) (2026-08-19)
4
18
 
5
19
 
@@ -1059,8 +1059,7 @@
1059
1059
  }
1060
1060
  },
1061
1061
  "required": [
1062
- "metric",
1063
- "value"
1062
+ "metric"
1064
1063
  ],
1065
1064
  "description": "The body parameters."
1066
1065
  },
@@ -82,7 +82,7 @@ A promise that resolves when the metric has been created.
82
82
 
83
83
  ### getMetric() {#getmetric}
84
84
 
85
- > **getMetric**(`id`): `Promise`\<\{ `metric`: `ITelemetryMetric`; `value`: `ITelemetryMetricValue`; \}\>
85
+ > **getMetric**(`id`): `Promise`\<\{ `metric`: `ITelemetryMetric`; `value?`: `ITelemetryMetricValue`; \}\>
86
86
 
87
87
  Get the metric details and it's most recent value.
88
88
 
@@ -96,7 +96,7 @@ The metric id.
96
96
 
97
97
  #### Returns
98
98
 
99
- `Promise`\<\{ `metric`: `ITelemetryMetric`; `value`: `ITelemetryMetricValue`; \}\>
99
+ `Promise`\<\{ `metric`: `ITelemetryMetric`; `value?`: `ITelemetryMetricValue`; \}\>
100
100
 
101
101
  The metric details and it's most recent value.
102
102
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/telemetry-service",
3
- "version": "0.9.2-next.7",
3
+ "version": "0.9.2-next.8",
4
4
  "description": "Telemetry service implementation with REST entry points.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "@twin.org/entity": "next",
21
21
  "@twin.org/logging-models": "next",
22
22
  "@twin.org/nameof": "next",
23
- "@twin.org/telemetry-models": "0.9.2-next.7",
23
+ "@twin.org/telemetry-models": "0.9.2-next.8",
24
24
  "@twin.org/web": "next"
25
25
  },
26
26
  "main": "./dist/es/index.js",