From ed9c7a29726a2224b1d1836be7c4e0474ce5fc4c Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Fri, 8 Sep 2023 12:11:02 +0200 Subject: [PATCH 01/29] chore: enable eslint/strict-boolean-expressions and strictNullChecks --- .eslintrc.js | 1 + tsconfig.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index d8f683df7..ee76b16aa 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,6 +29,7 @@ module.exports = { "@typescript-eslint/no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off", "no-use-before-define": "off", "@typescript-eslint/no-use-before-define": ["error"], + "@typescript-eslint/strict-boolean-expressions": ["error"], "unused-imports/no-unused-imports": "error", "unused-imports/no-unused-vars": [ "warn", diff --git a/tsconfig.json b/tsconfig.json index 5b3cda168..5e9e08f4a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "module": "commonjs", "outDir": "dist", "strict": true, + "strictNullChecks": true, "composite": true, "incremental": true, "sourceMap": true, From af1839239d1f732aa17ed643cc0aa556ede567f7 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Fri, 8 Sep 2023 12:15:03 +0200 Subject: [PATCH 02/29] fix package examples --- packages/examples/src/scripts/countdown.ts | 6 +++--- .../examples/src/scripts/smart-coffee-machine-client.ts | 2 +- packages/examples/src/scripts/smart-coffee-machine.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/examples/src/scripts/countdown.ts b/packages/examples/src/scripts/countdown.ts index fa7c2e25c..f65306204 100644 --- a/packages/examples/src/scripts/countdown.ts +++ b/packages/examples/src/scripts/countdown.ts @@ -127,7 +127,7 @@ WoT.produce({ "startCountdown", async (params: WoT.InteractionOutput, options): Promise => { let initValue = 100; - if (params) { + if (params !== undefined) { const value = await params.value(); if (typeof value === "number") { initValue = value as number; @@ -147,7 +147,7 @@ WoT.produce({ thing.setActionHandler( "stopCountdown", async (params: WoT.InteractionOutput, options): Promise => { - if (params) { + if (params !== undefined) { const value = await params.value(); if (typeof value === "string" && countdowns.has(value)) { const as = countdowns.get(value); @@ -170,7 +170,7 @@ WoT.produce({ thing.setActionHandler( "monitorCountdown", async (params: WoT.InteractionOutput, options): Promise => { - if (params) { + if (params !== undefined) { const value = await params.value(); if (typeof value === "string" && countdowns.has(value)) { const as = countdowns.get(value); diff --git a/packages/examples/src/scripts/smart-coffee-machine-client.ts b/packages/examples/src/scripts/smart-coffee-machine-client.ts index 05e745c35..767cba1ef 100644 --- a/packages/examples/src/scripts/smart-coffee-machine-client.ts +++ b/packages/examples/src/scripts/smart-coffee-machine-client.ts @@ -61,7 +61,7 @@ WoTHelpers.fetch("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) = uriVariables: { drinkId: "latte", size: "l", quantity: 3 }, }); const makeCoffeep = (await makeCoffee?.value()) as Record; - if (makeCoffeep.result) { + if (makeCoffeep.result !== undefined) { log("Enjoy your drink!", makeCoffeep); } else { log("Failed making your drink:", makeCoffeep); diff --git a/packages/examples/src/scripts/smart-coffee-machine.ts b/packages/examples/src/scripts/smart-coffee-machine.ts index 896ebe947..17f11a225 100644 --- a/packages/examples/src/scripts/smart-coffee-machine.ts +++ b/packages/examples/src/scripts/smart-coffee-machine.ts @@ -396,7 +396,7 @@ Assumes one medium americano if not specified, but time and mode are mandatory f const paramsp = (await params.value()) as Record; // : any = await Helpers.parseInteractionOutput(params); // Check if uriVariables are provided - if (paramsp && typeof paramsp === "object" && "time" in paramsp && "mode" in paramsp) { + if (paramsp !== undefined && typeof paramsp === "object" && "time" in paramsp && "mode" in paramsp) { // Use default values if not provided paramsp.drinkId = "drinkId" in paramsp ? paramsp.drinkId : "americano"; paramsp.size = "size" in paramsp ? paramsp.size : "m"; From 9a667e36389adf6b895097a860fce93092685170 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Fri, 8 Sep 2023 13:56:38 +0200 Subject: [PATCH 03/29] fix package td-tools Note: leave out asset-interface-description.ts because of https://github.com/eclipse-thingweb/node-wot/pull/1052 --- packages/td-tools/src/td-parser.ts | 22 ++++++++--------- packages/td-tools/src/thing-description.ts | 2 +- packages/td-tools/src/thing-model-helpers.ts | 26 ++++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index 2edf6e5c2..af3fc89e7 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -158,7 +158,7 @@ export function parseTD(td: string, normalize?: boolean): Thing { throw new Error(`Form of Property '${propName}' has no href field`); } // check if base field required - if (!isAbsoluteUrl(form.href) && !thing.base) + if (!isAbsoluteUrl(form.href) && thing.base === undefined) throw new Error(`Form of Property '${propName}' has relative URI while TD has no base field`); // add allForms.push(form); @@ -176,7 +176,7 @@ export function parseTD(td: string, normalize?: boolean): Thing { throw new Error(`Form of Action '${actName}' has no href field`); } // check if base field required - if (!isAbsoluteUrl(form.href) && !thing.base) + if (!isAbsoluteUrl(form.href) && thing.base === undefined) throw new Error(`Form of Action '${actName}' has relative URI while TD has no base field`); // add allForms.push(form); @@ -194,7 +194,7 @@ export function parseTD(td: string, normalize?: boolean): Thing { throw new Error(`Form of Event '${evtName}' has no href field`); } // check if base field required - if (!isAbsoluteUrl(form.href) && !thing.base) + if (!isAbsoluteUrl(form.href) && thing.base === undefined) throw new Error(`Form of Event '${evtName}' has relative URI while TD has no base field`); // add allForms.push(form); @@ -222,20 +222,20 @@ export function serializeTD(thing: Thing): string { const copy = JSON.parse(JSON.stringify(thing)); // clean-ups - if (!copy.security || copy.security.length === 0) { + if (copy.security === undefined || copy.security.length === 0) { copy.securityDefinitions = { nosec_sc: { scheme: "nosec" }, }; copy.security = ["nosec_sc"]; } - if (copy.forms && copy.forms.length === 0) { + if (copy.forms !== undefined && copy.forms.length === 0) { delete copy.forms; } - if (copy.properties && Object.keys(copy.properties).length === 0) { + if (copy.properties !== undefined && Object.keys(copy.properties).length === 0) { delete copy.properties; - } else if (copy.properties) { + } else if (copy.properties !== undefined) { // add mandatory fields (if missing): observable, writeOnly, and readOnly for (const propName in copy.properties) { const prop = copy.properties[propName]; @@ -251,9 +251,9 @@ export function serializeTD(thing: Thing): string { } } - if (copy.actions && Object.keys(copy.actions).length === 0) { + if (copy.actions !== undefined && Object.keys(copy.actions).length === 0) { delete copy.actions; - } else if (copy.actions) { + } else if (copy.actions !== undefined) { // add mandatory fields (if missing): idempotent and safe for (const actName in copy.actions) { const act = copy.actions[actName]; @@ -265,11 +265,11 @@ export function serializeTD(thing: Thing): string { } } } - if (copy.events && Object.keys(copy.events).length === 0) { + if (copy.events !== undefined && Object.keys(copy.events).length === 0) { delete copy.events; } - if (copy.links && copy.links.length === 0) { + if (copy.links !== undefined && copy.links.length === 0) { delete copy.links; } diff --git a/packages/td-tools/src/thing-description.ts b/packages/td-tools/src/thing-description.ts index 34ce5bd51..7756d78a4 100644 --- a/packages/td-tools/src/thing-description.ts +++ b/packages/td-tools/src/thing-description.ts @@ -67,7 +67,7 @@ export class Form implements TDT.FormElementBase { constructor(href: string, contentType?: string) { this.href = href; - if (contentType) this.contentType = contentType; + if (contentType !== undefined) this.contentType = contentType; } } export interface ExpectedResponse { diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 1cb71213c..074b8944e 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -110,7 +110,7 @@ export class ThingModelHelpers { } if ("links" in data && Array.isArray(data.links)) { const foundTmExtendsRel = data.links.find((link) => link.rel === "tm:extends"); - if (foundTmExtendsRel) return true; + if (foundTmExtendsRel !== undefined) return true; } if (data.properties !== undefined) { @@ -138,7 +138,7 @@ export class ThingModelHelpers { public static getModelVersion(data: ThingModel): string | undefined { if ( "version" in data && - data.version && + data.version !== undefined && typeof data.version === "object" && "model" in data.version && typeof data.version.model === "string" @@ -241,7 +241,7 @@ export class ThingModelHelpers { case "http": { return new Promise((resolve, reject) => { http.get(uri, (res) => { - if (!res.statusCode || res.statusCode !== 200) { + if (res.statusCode === undefined || res.statusCode !== 200) { reject(new Error(`http status code not 200 but ${res.statusCode} for ${uri}`)); } @@ -268,7 +268,7 @@ export class ThingModelHelpers { return new Promise((resolve, reject) => { https .get(uri, (res) => { - if (!res.statusCode || res.statusCode !== 200) { + if (res.statusCode === undefined || res.statusCode !== 200) { reject(new Error(`https status code not 200 but ${res.statusCode} for ${uri}`)); } @@ -343,7 +343,7 @@ export class ThingModelHelpers { for (const aff in affRefs) { const affUri = affRefs[aff] as string; const refObj = this.parseTmRef(affUri); - if (!refObj.uri) { + if (refObj.uri === undefined) { throw new Error(`Missing remote path in ${affUri}`); } let source = await this.fetchModel(refObj.uri); @@ -376,7 +376,7 @@ export class ThingModelHelpers { if (!options) { options = {} as CompositionOptions; } - if (!options.baseUrl) { + if (options.baseUrl === undefined) { options.baseUrl = "."; } const newTMHref = this.returnNewTMHref(options.baseUrl, title); @@ -405,7 +405,7 @@ export class ThingModelHelpers { for (const key in submodelObj) { const sub = submodelObj[key]; - if (options.selfComposition) { + if (options.selfComposition !== undefined) { if (!data.links) { throw new Error( "You used self composition but links are missing; they are needed to extract the instance name" @@ -415,7 +415,7 @@ export class ThingModelHelpers { const index = data.links.findIndex((el) => el.href === key); const el = data.links[index]; const instanceName = el.instanceName; - if (!instanceName) { + if (instanceName === undefined) { throw new Error("Self composition is not possible without instance names"); } // self composition enabled, just one TD expected @@ -449,7 +449,7 @@ export class ThingModelHelpers { } } } - if (!data.links || options.selfComposition) { + if (!data.links || options.selfComposition !== undefined) { data.links = []; } // add reference to the thing model @@ -475,7 +475,7 @@ export class ThingModelHelpers { private static getThingModelRef(data: Record): Record { const refs = {} as Record; - if (!data) { + if (data === undefined) { return refs; } for (const key in data) { @@ -508,7 +508,7 @@ export class ThingModelHelpers { extendedModel.properties = {}; } for (const key in properties) { - if (dest.properties && dest.properties[key]) { + if (dest.properties && dest.properties[key] !== undefined) { extendedModel.properties[key] = { ...properties[key], ...dest.properties[key] }; } else { extendedModel.properties[key] = properties[key]; @@ -625,7 +625,7 @@ export class ThingModelHelpers { keys = keys.map((el) => el.replace("{{", "").replace("}}", "")); let isValid = true; let errors; - if (keys && keys.length > 0 && (map === undefined || map === null)) { + if (keys !== undefined && keys.length > 0 && (map === undefined || map === null)) { isValid = false; errors = `No map provided for model ${model.title}`; } else if (keys.length > 0) { @@ -660,7 +660,7 @@ export class ThingModelHelpers { } private removeDependency(dep?: string) { - if (dep) { + if (dep !== undefined) { this.deps = this.deps.filter((el) => el !== dep); } else { this.deps.pop(); From 59d04b9c51f9467dc55ea41248570f7f4b979b64 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:03:47 +0200 Subject: [PATCH 04/29] Update packages/td-tools/src/td-parser.ts Co-authored-by: Jan Romann --- packages/td-tools/src/td-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index af3fc89e7..fe2f73293 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -222,7 +222,7 @@ export function serializeTD(thing: Thing): string { const copy = JSON.parse(JSON.stringify(thing)); // clean-ups - if (copy.security === undefined || copy.security.length === 0) { + if (copy?.security.length === 0) { copy.securityDefinitions = { nosec_sc: { scheme: "nosec" }, }; From f7be620be318ff91c1d9242c4b50809860efe86c Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:03:57 +0200 Subject: [PATCH 05/29] Update packages/td-tools/src/td-parser.ts Co-authored-by: Jan Romann --- packages/td-tools/src/td-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index fe2f73293..bc2b835b4 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -229,7 +229,7 @@ export function serializeTD(thing: Thing): string { copy.security = ["nosec_sc"]; } - if (copy.forms !== undefined && copy.forms.length === 0) { + if (copy?.forms.length === 0) { delete copy.forms; } From c5749133c41d5a89f8ab3aaadddd0ce722794ae1 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:04:05 +0200 Subject: [PATCH 06/29] Update packages/td-tools/src/td-parser.ts Co-authored-by: Jan Romann --- packages/td-tools/src/td-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index bc2b835b4..6612767aa 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -269,7 +269,7 @@ export function serializeTD(thing: Thing): string { delete copy.events; } - if (copy.links !== undefined && copy.links.length === 0) { + if (copy?.links.length === 0) { delete copy.links; } From ea1dc82644e7030bd786997fe78b490c3241fcd7 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:04:16 +0200 Subject: [PATCH 07/29] Update packages/td-tools/src/thing-model-helpers.ts Co-authored-by: Jan Romann --- packages/td-tools/src/thing-model-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 074b8944e..ecb434f2d 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -241,7 +241,7 @@ export class ThingModelHelpers { case "http": { return new Promise((resolve, reject) => { http.get(uri, (res) => { - if (res.statusCode === undefined || res.statusCode !== 200) { + if (res?.statusCode !== 200) { reject(new Error(`http status code not 200 but ${res.statusCode} for ${uri}`)); } From 58198a2a81a33937978cee851c056d2d9bfd6172 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:04:24 +0200 Subject: [PATCH 08/29] Update packages/td-tools/src/thing-model-helpers.ts Co-authored-by: Jan Romann --- packages/td-tools/src/thing-model-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index ecb434f2d..abf28fde4 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -268,7 +268,7 @@ export class ThingModelHelpers { return new Promise((resolve, reject) => { https .get(uri, (res) => { - if (res.statusCode === undefined || res.statusCode !== 200) { + if (res?.statusCode !== 200) { reject(new Error(`https status code not 200 but ${res.statusCode} for ${uri}`)); } From d1f6ee65547f159cd14de3738e85df114b33edb8 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:04:43 +0200 Subject: [PATCH 09/29] Update packages/td-tools/src/thing-model-helpers.ts Co-authored-by: Jan Romann --- packages/td-tools/src/thing-model-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index abf28fde4..02cfd73e1 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -508,7 +508,7 @@ export class ThingModelHelpers { extendedModel.properties = {}; } for (const key in properties) { - if (dest.properties && dest.properties[key] !== undefined) { + if (dest?.properties[key] !== undefined) { extendedModel.properties[key] = { ...properties[key], ...dest.properties[key] }; } else { extendedModel.properties[key] = properties[key]; From 10fc13bdd829b422cd63eac0f24fcccf20d5118a Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 12 Sep 2023 10:05:45 +0200 Subject: [PATCH 10/29] Update packages/td-tools/src/thing-model-helpers.ts Co-authored-by: Jan Romann --- packages/td-tools/src/thing-model-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 02cfd73e1..008206b27 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -625,7 +625,7 @@ export class ThingModelHelpers { keys = keys.map((el) => el.replace("{{", "").replace("}}", "")); let isValid = true; let errors; - if (keys !== undefined && keys.length > 0 && (map === undefined || map === null)) { + if ((keys ?? []).length > 0 && (map == null)) { isValid = false; errors = `No map provided for model ${model.title}`; } else if (keys.length > 0) { From c641193f3b81bf81b5a378df5d66c0b983738d3a Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 14 Sep 2023 10:16:22 +0200 Subject: [PATCH 11/29] fix: issue issue introduced by commenting --- packages/td-tools/src/thing-model-helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 008206b27..61634bf85 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -508,7 +508,7 @@ export class ThingModelHelpers { extendedModel.properties = {}; } for (const key in properties) { - if (dest?.properties[key] !== undefined) { + if (dest.properties !== undefined && dest.properties[key] !== undefined) { extendedModel.properties[key] = { ...properties[key], ...dest.properties[key] }; } else { extendedModel.properties[key] = properties[key]; @@ -625,7 +625,7 @@ export class ThingModelHelpers { keys = keys.map((el) => el.replace("{{", "").replace("}}", "")); let isValid = true; let errors; - if ((keys ?? []).length > 0 && (map == null)) { + if ((keys ?? []).length > 0 && map == null) { isValid = false; errors = `No map provided for model ${model.title}`; } else if (keys.length > 0) { From 6b4b0103b263fc3b2f76e0a666061c57ba644880 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 14 Sep 2023 10:25:12 +0200 Subject: [PATCH 12/29] move eslint settings to td-tools package only --- .eslintrc.js | 1 - packages/td-tools/.eslintrc.json | 5 ++++- packages/td-tools/tsconfig.json | 3 ++- tsconfig.json | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index ee76b16aa..d8f683df7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,7 +29,6 @@ module.exports = { "@typescript-eslint/no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off", "no-use-before-define": "off", "@typescript-eslint/no-use-before-define": ["error"], - "@typescript-eslint/strict-boolean-expressions": ["error"], "unused-imports/no-unused-imports": "error", "unused-imports/no-unused-vars": [ "warn", diff --git a/packages/td-tools/.eslintrc.json b/packages/td-tools/.eslintrc.json index 7bb9b651d..8cc298a95 100644 --- a/packages/td-tools/.eslintrc.json +++ b/packages/td-tools/.eslintrc.json @@ -1,4 +1,7 @@ { "extends": "../../.eslintrc.js", - "ignorePatterns": "webpack.config.js" + "ignorePatterns": "webpack.config.js", + "rules": { + "@typescript-eslint/strict-boolean-expressions": ["error"] + } } diff --git a/packages/td-tools/tsconfig.json b/packages/td-tools/tsconfig.json index b2c3d8edc..cbbaa970a 100644 --- a/packages/td-tools/tsconfig.json +++ b/packages/td-tools/tsconfig.json @@ -4,7 +4,8 @@ "resolveJsonModule": true, "types": ["node", "readable-stream"], "outDir": "dist", - "rootDir": "src" + "rootDir": "src", + "strictNullChecks": true }, "include": ["src/**/*"] } diff --git a/tsconfig.json b/tsconfig.json index 5e9e08f4a..5b3cda168 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,6 @@ "module": "commonjs", "outDir": "dist", "strict": true, - "strictNullChecks": true, "composite": true, "incremental": true, "sourceMap": true, From 4204a907af972e52e9085989024ff156b1658774 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 14 Sep 2023 10:44:45 +0200 Subject: [PATCH 13/29] fix: lint errors for AID --- .../src/util/asset-interface-description.ts | 89 +++++++++++-------- .../test/AssetInterfaceDescriptionTest.ts | 2 +- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index ec8504e79..581923c01 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -132,7 +132,7 @@ export class AssetInterfaceDescriptionUtil { public transformTD2SM(tdAsString: string, protocols?: string[]): string { const td: ThingDescription = TDParser.parseTD(tdAsString); - const aidID = td.id ? td.id : "ID" + Math.random(); + const aidID = td.id != null ? td.id : "ID" + Math.random(); logInfo("TD " + td.title + " parsed..."); @@ -218,9 +218,9 @@ export class AssetInterfaceDescriptionUtil { } private updateProtocolPrefixes(forms: [FormElementBase, ...FormElementBase[]], protocols: string[]): void { - if (forms) { + if (forms !== undefined) { for (const interactionForm of forms) { - if (interactionForm.href) { + if (interactionForm.href != null) { const positionColon = interactionForm.href.indexOf(":"); if (positionColon > 0) { const prefix = interactionForm.href.substring(0, positionColon); @@ -234,7 +234,7 @@ export class AssetInterfaceDescriptionUtil { } private getBaseFromEndpointMetadata(endpointMetadata?: Record): string { - if (endpointMetadata?.value && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "base") { // e.g., "value": "modbus+tcp://192.168.1.187:502" @@ -246,7 +246,7 @@ export class AssetInterfaceDescriptionUtil { } private getContentTypeFromEndpointMetadata(endpointMetadata?: Record): string { - if (endpointMetadata?.value && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "contentType") { // e.g., "value": "application/octet-stream;byteSeq=BIG_ENDIAN" @@ -264,18 +264,18 @@ export class AssetInterfaceDescriptionUtil { [k: string]: SecurityScheme; } = {}; - if (endpointMetadata?.value && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "securityDefinitions") { // const securitySchemes: Array = []; - if (v.value && v.value instanceof Array) { + if (v.value !== undefined && v.value instanceof Array) { for (const securityDefinitionsValues of v.value) { - if (securityDefinitionsValues.idShort) { + if (securityDefinitionsValues.idShort !== undefined) { // key if (securityDefinitionsValues.value instanceof Array) { for (const securityDefinitionsValue of securityDefinitionsValues.value) { if (securityDefinitionsValue.idShort === "scheme") { - if (securityDefinitionsValue.value) { + if (securityDefinitionsValue.value !== undefined) { const ss: SecurityScheme = { scheme: securityDefinitionsValue.value }; securityDefinitions[securityDefinitionsValues.idShort] = ss; } @@ -295,12 +295,12 @@ export class AssetInterfaceDescriptionUtil { endpointMetadata?: Record ): string | [string, ...string[]] { const security: string[] = []; - if (endpointMetadata?.value && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "security") { - if (v.value && v.value instanceof Array) { + if (v.value !== undefined && v.value instanceof Array) { for (const securityValue of v.value) { - if (securityValue.value) { + if (securityValue.value !== undefined) { security.push(securityValue.value); } } @@ -346,17 +346,16 @@ export class AssetInterfaceDescriptionUtil { } } else if (typeof v.idShort === "string" && v.idShort.length > 0) { // TODO is this still relevant? - // pick *any* value (and possibly override, e.g, contentType) + // pick *any* value (and possibly override, e. g, contentType) // TODO Should we add all value's (e.g., dataMapping might be empty array) ? // if (typeof v.value === "string" ||typeof v.value === "number" || typeof v.value === "boolean") { - if (v.value) { + if (v.value !== undefined) { form[v.idShort] = v.value; // use valueType to convert the string value if ( - v.valueType && - v.valueType && - v.valueType.dataObjectType && - v.valueType.dataObjectType.name && + v.valueType !== undefined && + v.valueType.dataObjectType !== undefined && + v.valueType.dataObjectType.name !== undefined && typeof v.valueType.dataObjectType.name === "string" ) { // XSD schemaTypes, https://www.w3.org/TR/xmlschema-2/#built-in-datatypes @@ -400,12 +399,20 @@ export class AssetInterfaceDescriptionUtil { submodel: Record, submodelRegex?: string ): void { - if (submodel instanceof Object && submodel.idShort && submodel.idShort === "AssetInterfacesDescription") { - if (submodel.submodelElements && submodel.submodelElements instanceof Array) { + if ( + submodel instanceof Object && + submodel.idShort !== undefined && + submodel.idShort === "AssetInterfacesDescription" + ) { + if (submodel.submodelElements !== undefined && submodel.submodelElements instanceof Array) { for (const submodelElement of submodel.submodelElements) { if (submodelElement instanceof Object) { logDebug("SubmodelElement.idShort: " + submodelElement.idShort); - if (submodelRegex && typeof submodelRegex === "string" && submodelRegex.length > 0) { + if ( + submodelRegex !== undefined && + typeof submodelRegex === "string" && + submodelRegex.length > 0 + ) { const regex = new RegExp(submodelRegex); if (!regex.test(submodelElement.idShort)) { logInfo("submodel not of interest"); @@ -422,7 +429,7 @@ export class AssetInterfaceDescriptionUtil { private processSubmodelElement(smInformation: SubmodelInformation, submodelElement: Record): void { // EndpointMetadata vs. InterfaceMetadata - if (submodelElement.value && submodelElement.value instanceof Array) { + if (submodelElement.value !== undefined && submodelElement.value instanceof Array) { // Note: iterate twice over to collect first EndpointMetadata let endpointMetadata: Record = {}; for (const smValue of submodelElement.value) { @@ -446,7 +453,7 @@ export class AssetInterfaceDescriptionUtil { if (smValue instanceof Object) { if (smValue.idShort === "InterfaceMetadata") { logInfo("InterfaceMetadata"); - if (smValue.value && smValue.value instanceof Array) { + if (smValue.value !== undefined && smValue.value instanceof Array) { for (const interactionValue of smValue.value) { if (interactionValue.idShort === "Properties") { if (interactionValue.value instanceof Array) { @@ -510,7 +517,7 @@ export class AssetInterfaceDescriptionUtil { thing: new Map>(), }; - if (aidModel instanceof Object && aidModel.submodels) { + if (aidModel instanceof Object && aidModel.submodels !== undefined) { if (aidModel.submodels instanceof Array) { for (const submodel of aidModel.submodels) { this.processSubmodel(smInformation, submodel, submodelRegex); @@ -522,7 +529,7 @@ export class AssetInterfaceDescriptionUtil { } private _transform(smInformation: SubmodelInformation, template?: string): string { - const thing: Thing = template ? JSON.parse(template) : {}; + const thing: Thing = template !== undefined ? JSON.parse(template) : {}; // walk over thing information and set them for (const [key, value] of smInformation.thing) { @@ -534,7 +541,7 @@ export class AssetInterfaceDescriptionUtil { } // required TD fields - if (!thing["@context"]) { + if (thing["@context"] === undefined) { thing["@context"] = "https://www.w3.org/2022/wot/td/v1.1"; } if (!thing.title) { @@ -544,7 +551,7 @@ export class AssetInterfaceDescriptionUtil { // Security in AID is defined for each submodel // add "securityDefinitions" globally and add them on form level if necessary // TODO: possible collisions for "security" names *could* be handled by cnt - if (!thing.securityDefinitions) { + if (thing.securityDefinitions === undefined) { thing.securityDefinitions = {}; } // let cnt = 1; @@ -595,7 +602,10 @@ export class AssetInterfaceDescriptionUtil { const tdDescription: Record = {}; if (aasDescription instanceof Array) { for (const aasDescriptionEntry of aasDescription) { - if (aasDescriptionEntry.language && aasDescriptionEntry.text) { + if ( + aasDescriptionEntry.language !== undefined && + aasDescriptionEntry.text !== undefined + ) { const language: string = aasDescriptionEntry.language; const text: string = aasDescriptionEntry.text; tdDescription[language] = text; @@ -613,10 +623,10 @@ export class AssetInterfaceDescriptionUtil { thing.properties[key].type = interactionValue.value; } } else if (interactionValue.idShort === "range") { - if (interactionValue.min) { + if (interactionValue.min !== undefined) { thing.properties[key].min = interactionValue.min; } - if (interactionValue.max) { + if (interactionValue.max !== undefined) { thing.properties[key].max = interactionValue.max; } } else if (interactionValue.idShort === "observable") { @@ -694,7 +704,7 @@ export class AssetInterfaceDescriptionUtil { const values: Array = []; // base ? - if (td.base) { + if (td.base !== undefined) { values.push({ idShort: "base", valueType: "xs:anyURI", @@ -715,7 +725,7 @@ export class AssetInterfaceDescriptionUtil { // security const securityValues: Array = []; - if (td.security) { + if (td.security !== undefined) { for (const secKey of td.security) { securityValues.push({ valueType: "xs:string", @@ -779,7 +789,10 @@ export class AssetInterfaceDescriptionUtil { let formElementPicked: FormElementBase | undefined; if (propertyValue.forms) { for (const formElementProperty of propertyValue.forms) { - if (formElementProperty.href?.startsWith(protocol)) { + if ( + formElementProperty.href !== undefined && + formElementProperty.href.startsWith(protocol) + ) { formElementPicked = formElementProperty; // found matching form --> abort loop break; @@ -793,7 +806,7 @@ export class AssetInterfaceDescriptionUtil { const propertyValues: Array = []; // type - if (propertyValue.type) { + if (propertyValue.type !== undefined) { propertyValues.push({ idShort: "type", valueType: "xs:string", @@ -802,7 +815,7 @@ export class AssetInterfaceDescriptionUtil { }); } // title - if (propertyValue.title) { + if (propertyValue.title !== undefined) { propertyValues.push({ idShort: "title", valueType: "xs:string", @@ -811,7 +824,7 @@ export class AssetInterfaceDescriptionUtil { }); } // observable - if (propertyValue.observable) { + if (propertyValue.observable !== undefined) { propertyValues.push({ idShort: "observable", valueType: "xs:boolean", @@ -823,7 +836,7 @@ export class AssetInterfaceDescriptionUtil { // range and others? Simply add them as is? // forms - if (formElementPicked) { + if (formElementPicked !== undefined) { const propertyForm: Array = []; // TODO AID for now supports just *one* href/form @@ -861,7 +874,7 @@ export class AssetInterfaceDescriptionUtil { text: langValue, }); } - } else if (propertyValue.description) { + } else if (propertyValue.description !== undefined) { // fallback description = []; description.push({ diff --git a/packages/td-tools/test/AssetInterfaceDescriptionTest.ts b/packages/td-tools/test/AssetInterfaceDescriptionTest.ts index bbe390ebc..2ff6e8dd6 100644 --- a/packages/td-tools/test/AssetInterfaceDescriptionTest.ts +++ b/packages/td-tools/test/AssetInterfaceDescriptionTest.ts @@ -343,7 +343,7 @@ class AssetInterfaceDescriptionUtilTest { expect(hasObservable).to.equal(true); expect(hasForms).to.equal(true); } - if (propertyValue.description) { + if (propertyValue.description !== undefined) { hasPropertyStatusDescription = true; expect(propertyValue) .to.have.property("description") From 100bdde97c78765c2f7508de89b71818017511b5 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 20 Sep 2023 09:47:31 +0200 Subject: [PATCH 14/29] refactor: revert changes in package "examples" --- packages/examples/src/scripts/countdown.ts | 6 +++--- .../examples/src/scripts/smart-coffee-machine-client.ts | 2 +- packages/examples/src/scripts/smart-coffee-machine.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/examples/src/scripts/countdown.ts b/packages/examples/src/scripts/countdown.ts index f65306204..fa7c2e25c 100644 --- a/packages/examples/src/scripts/countdown.ts +++ b/packages/examples/src/scripts/countdown.ts @@ -127,7 +127,7 @@ WoT.produce({ "startCountdown", async (params: WoT.InteractionOutput, options): Promise => { let initValue = 100; - if (params !== undefined) { + if (params) { const value = await params.value(); if (typeof value === "number") { initValue = value as number; @@ -147,7 +147,7 @@ WoT.produce({ thing.setActionHandler( "stopCountdown", async (params: WoT.InteractionOutput, options): Promise => { - if (params !== undefined) { + if (params) { const value = await params.value(); if (typeof value === "string" && countdowns.has(value)) { const as = countdowns.get(value); @@ -170,7 +170,7 @@ WoT.produce({ thing.setActionHandler( "monitorCountdown", async (params: WoT.InteractionOutput, options): Promise => { - if (params !== undefined) { + if (params) { const value = await params.value(); if (typeof value === "string" && countdowns.has(value)) { const as = countdowns.get(value); diff --git a/packages/examples/src/scripts/smart-coffee-machine-client.ts b/packages/examples/src/scripts/smart-coffee-machine-client.ts index 767cba1ef..05e745c35 100644 --- a/packages/examples/src/scripts/smart-coffee-machine-client.ts +++ b/packages/examples/src/scripts/smart-coffee-machine-client.ts @@ -61,7 +61,7 @@ WoTHelpers.fetch("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) = uriVariables: { drinkId: "latte", size: "l", quantity: 3 }, }); const makeCoffeep = (await makeCoffee?.value()) as Record; - if (makeCoffeep.result !== undefined) { + if (makeCoffeep.result) { log("Enjoy your drink!", makeCoffeep); } else { log("Failed making your drink:", makeCoffeep); diff --git a/packages/examples/src/scripts/smart-coffee-machine.ts b/packages/examples/src/scripts/smart-coffee-machine.ts index 17f11a225..896ebe947 100644 --- a/packages/examples/src/scripts/smart-coffee-machine.ts +++ b/packages/examples/src/scripts/smart-coffee-machine.ts @@ -396,7 +396,7 @@ Assumes one medium americano if not specified, but time and mode are mandatory f const paramsp = (await params.value()) as Record; // : any = await Helpers.parseInteractionOutput(params); // Check if uriVariables are provided - if (paramsp !== undefined && typeof paramsp === "object" && "time" in paramsp && "mode" in paramsp) { + if (paramsp && typeof paramsp === "object" && "time" in paramsp && "mode" in paramsp) { // Use default values if not provided paramsp.drinkId = "drinkId" in paramsp ? paramsp.drinkId : "americano"; paramsp.size = "size" in paramsp ? paramsp.size : "m"; From 88330e2edaa8d578def38947d727ada3ed192cd9 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 20 Sep 2023 10:16:30 +0200 Subject: [PATCH 15/29] refactor: revert "!== undefined" to "!= null" OR "=== undefined" to "== null" --- packages/td-tools/src/td-parser.ts | 16 ++-- packages/td-tools/src/thing-description.ts | 2 +- packages/td-tools/src/thing-model-helpers.ts | 20 ++--- .../src/util/asset-interface-description.ts | 78 ++++++++----------- .../test/AssetInterfaceDescriptionTest.ts | 2 +- 5 files changed, 54 insertions(+), 64 deletions(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index 6612767aa..1311c776f 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -158,7 +158,7 @@ export function parseTD(td: string, normalize?: boolean): Thing { throw new Error(`Form of Property '${propName}' has no href field`); } // check if base field required - if (!isAbsoluteUrl(form.href) && thing.base === undefined) + if (!isAbsoluteUrl(form.href) && thing.base == null) throw new Error(`Form of Property '${propName}' has relative URI while TD has no base field`); // add allForms.push(form); @@ -176,7 +176,7 @@ export function parseTD(td: string, normalize?: boolean): Thing { throw new Error(`Form of Action '${actName}' has no href field`); } // check if base field required - if (!isAbsoluteUrl(form.href) && thing.base === undefined) + if (!isAbsoluteUrl(form.href) && thing.base == null) throw new Error(`Form of Action '${actName}' has relative URI while TD has no base field`); // add allForms.push(form); @@ -194,7 +194,7 @@ export function parseTD(td: string, normalize?: boolean): Thing { throw new Error(`Form of Event '${evtName}' has no href field`); } // check if base field required - if (!isAbsoluteUrl(form.href) && thing.base === undefined) + if (!isAbsoluteUrl(form.href) && thing.base == null) throw new Error(`Form of Event '${evtName}' has relative URI while TD has no base field`); // add allForms.push(form); @@ -233,9 +233,9 @@ export function serializeTD(thing: Thing): string { delete copy.forms; } - if (copy.properties !== undefined && Object.keys(copy.properties).length === 0) { + if (copy.properties != null && Object.keys(copy.properties).length === 0) { delete copy.properties; - } else if (copy.properties !== undefined) { + } else if (copy.properties != null) { // add mandatory fields (if missing): observable, writeOnly, and readOnly for (const propName in copy.properties) { const prop = copy.properties[propName]; @@ -251,9 +251,9 @@ export function serializeTD(thing: Thing): string { } } - if (copy.actions !== undefined && Object.keys(copy.actions).length === 0) { + if (copy.actions != null && Object.keys(copy.actions).length === 0) { delete copy.actions; - } else if (copy.actions !== undefined) { + } else if (copy.actions != null) { // add mandatory fields (if missing): idempotent and safe for (const actName in copy.actions) { const act = copy.actions[actName]; @@ -265,7 +265,7 @@ export function serializeTD(thing: Thing): string { } } } - if (copy.events !== undefined && Object.keys(copy.events).length === 0) { + if (copy.events != null && Object.keys(copy.events).length === 0) { delete copy.events; } diff --git a/packages/td-tools/src/thing-description.ts b/packages/td-tools/src/thing-description.ts index 7756d78a4..b308fbddb 100644 --- a/packages/td-tools/src/thing-description.ts +++ b/packages/td-tools/src/thing-description.ts @@ -67,7 +67,7 @@ export class Form implements TDT.FormElementBase { constructor(href: string, contentType?: string) { this.href = href; - if (contentType !== undefined) this.contentType = contentType; + if (contentType != null) this.contentType = contentType; } } export interface ExpectedResponse { diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 61634bf85..e16ff50bb 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -110,7 +110,7 @@ export class ThingModelHelpers { } if ("links" in data && Array.isArray(data.links)) { const foundTmExtendsRel = data.links.find((link) => link.rel === "tm:extends"); - if (foundTmExtendsRel !== undefined) return true; + if (foundTmExtendsRel != null) return true; } if (data.properties !== undefined) { @@ -138,7 +138,7 @@ export class ThingModelHelpers { public static getModelVersion(data: ThingModel): string | undefined { if ( "version" in data && - data.version !== undefined && + data.version != null && typeof data.version === "object" && "model" in data.version && typeof data.version.model === "string" @@ -343,7 +343,7 @@ export class ThingModelHelpers { for (const aff in affRefs) { const affUri = affRefs[aff] as string; const refObj = this.parseTmRef(affUri); - if (refObj.uri === undefined) { + if (refObj.uri == null) { throw new Error(`Missing remote path in ${affUri}`); } let source = await this.fetchModel(refObj.uri); @@ -376,7 +376,7 @@ export class ThingModelHelpers { if (!options) { options = {} as CompositionOptions; } - if (options.baseUrl === undefined) { + if (options.baseUrl == null) { options.baseUrl = "."; } const newTMHref = this.returnNewTMHref(options.baseUrl, title); @@ -405,7 +405,7 @@ export class ThingModelHelpers { for (const key in submodelObj) { const sub = submodelObj[key]; - if (options.selfComposition !== undefined) { + if (options.selfComposition != null) { if (!data.links) { throw new Error( "You used self composition but links are missing; they are needed to extract the instance name" @@ -415,7 +415,7 @@ export class ThingModelHelpers { const index = data.links.findIndex((el) => el.href === key); const el = data.links[index]; const instanceName = el.instanceName; - if (instanceName === undefined) { + if (instanceName == null) { throw new Error("Self composition is not possible without instance names"); } // self composition enabled, just one TD expected @@ -449,7 +449,7 @@ export class ThingModelHelpers { } } } - if (!data.links || options.selfComposition !== undefined) { + if (!data.links || options.selfComposition != null) { data.links = []; } // add reference to the thing model @@ -475,7 +475,7 @@ export class ThingModelHelpers { private static getThingModelRef(data: Record): Record { const refs = {} as Record; - if (data === undefined) { + if (data == null) { return refs; } for (const key in data) { @@ -508,7 +508,7 @@ export class ThingModelHelpers { extendedModel.properties = {}; } for (const key in properties) { - if (dest.properties !== undefined && dest.properties[key] !== undefined) { + if (dest.properties != null && dest.properties[key] != null) { extendedModel.properties[key] = { ...properties[key], ...dest.properties[key] }; } else { extendedModel.properties[key] = properties[key]; @@ -660,7 +660,7 @@ export class ThingModelHelpers { } private removeDependency(dep?: string) { - if (dep !== undefined) { + if (dep != null) { this.deps = this.deps.filter((el) => el !== dep); } else { this.deps.pop(); diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index 581923c01..e7d1c677f 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -218,7 +218,7 @@ export class AssetInterfaceDescriptionUtil { } private updateProtocolPrefixes(forms: [FormElementBase, ...FormElementBase[]], protocols: string[]): void { - if (forms !== undefined) { + if (forms != null) { for (const interactionForm of forms) { if (interactionForm.href != null) { const positionColon = interactionForm.href.indexOf(":"); @@ -234,7 +234,7 @@ export class AssetInterfaceDescriptionUtil { } private getBaseFromEndpointMetadata(endpointMetadata?: Record): string { - if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "base") { // e.g., "value": "modbus+tcp://192.168.1.187:502" @@ -264,18 +264,18 @@ export class AssetInterfaceDescriptionUtil { [k: string]: SecurityScheme; } = {}; - if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "securityDefinitions") { // const securitySchemes: Array = []; - if (v.value !== undefined && v.value instanceof Array) { + if (v.value != null && v.value instanceof Array) { for (const securityDefinitionsValues of v.value) { - if (securityDefinitionsValues.idShort !== undefined) { + if (securityDefinitionsValues.idShort != null) { // key if (securityDefinitionsValues.value instanceof Array) { for (const securityDefinitionsValue of securityDefinitionsValues.value) { if (securityDefinitionsValue.idShort === "scheme") { - if (securityDefinitionsValue.value !== undefined) { + if (securityDefinitionsValue.value != null) { const ss: SecurityScheme = { scheme: securityDefinitionsValue.value }; securityDefinitions[securityDefinitionsValues.idShort] = ss; } @@ -295,12 +295,12 @@ export class AssetInterfaceDescriptionUtil { endpointMetadata?: Record ): string | [string, ...string[]] { const security: string[] = []; - if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "security") { - if (v.value !== undefined && v.value instanceof Array) { + if (v.value != null && v.value instanceof Array) { for (const securityValue of v.value) { - if (securityValue.value !== undefined) { + if (securityValue.value != null) { security.push(securityValue.value); } } @@ -346,16 +346,16 @@ export class AssetInterfaceDescriptionUtil { } } else if (typeof v.idShort === "string" && v.idShort.length > 0) { // TODO is this still relevant? - // pick *any* value (and possibly override, e. g, contentType) + // pick *any* value (and possibly override, e.g. contentType) // TODO Should we add all value's (e.g., dataMapping might be empty array) ? // if (typeof v.value === "string" ||typeof v.value === "number" || typeof v.value === "boolean") { - if (v.value !== undefined) { + if (v.value != null) { form[v.idShort] = v.value; // use valueType to convert the string value if ( - v.valueType !== undefined && - v.valueType.dataObjectType !== undefined && - v.valueType.dataObjectType.name !== undefined && + v.valueType != null && + v.valueType.dataObjectType != null && + v.valueType.dataObjectType.name != null && typeof v.valueType.dataObjectType.name === "string" ) { // XSD schemaTypes, https://www.w3.org/TR/xmlschema-2/#built-in-datatypes @@ -401,18 +401,14 @@ export class AssetInterfaceDescriptionUtil { ): void { if ( submodel instanceof Object && - submodel.idShort !== undefined && + submodel.idShort != null && submodel.idShort === "AssetInterfacesDescription" ) { - if (submodel.submodelElements !== undefined && submodel.submodelElements instanceof Array) { + if (submodel.submodelElements != null && submodel.submodelElements instanceof Array) { for (const submodelElement of submodel.submodelElements) { if (submodelElement instanceof Object) { logDebug("SubmodelElement.idShort: " + submodelElement.idShort); - if ( - submodelRegex !== undefined && - typeof submodelRegex === "string" && - submodelRegex.length > 0 - ) { + if (submodelRegex != null && typeof submodelRegex === "string" && submodelRegex.length > 0) { const regex = new RegExp(submodelRegex); if (!regex.test(submodelElement.idShort)) { logInfo("submodel not of interest"); @@ -429,7 +425,7 @@ export class AssetInterfaceDescriptionUtil { private processSubmodelElement(smInformation: SubmodelInformation, submodelElement: Record): void { // EndpointMetadata vs. InterfaceMetadata - if (submodelElement.value !== undefined && submodelElement.value instanceof Array) { + if (submodelElement.value != null && submodelElement.value instanceof Array) { // Note: iterate twice over to collect first EndpointMetadata let endpointMetadata: Record = {}; for (const smValue of submodelElement.value) { @@ -453,7 +449,7 @@ export class AssetInterfaceDescriptionUtil { if (smValue instanceof Object) { if (smValue.idShort === "InterfaceMetadata") { logInfo("InterfaceMetadata"); - if (smValue.value !== undefined && smValue.value instanceof Array) { + if (smValue.value != null && smValue.value instanceof Array) { for (const interactionValue of smValue.value) { if (interactionValue.idShort === "Properties") { if (interactionValue.value instanceof Array) { @@ -517,7 +513,7 @@ export class AssetInterfaceDescriptionUtil { thing: new Map>(), }; - if (aidModel instanceof Object && aidModel.submodels !== undefined) { + if (aidModel instanceof Object && aidModel.submodels != null) { if (aidModel.submodels instanceof Array) { for (const submodel of aidModel.submodels) { this.processSubmodel(smInformation, submodel, submodelRegex); @@ -529,7 +525,7 @@ export class AssetInterfaceDescriptionUtil { } private _transform(smInformation: SubmodelInformation, template?: string): string { - const thing: Thing = template !== undefined ? JSON.parse(template) : {}; + const thing: Thing = template != null ? JSON.parse(template) : {}; // walk over thing information and set them for (const [key, value] of smInformation.thing) { @@ -541,7 +537,7 @@ export class AssetInterfaceDescriptionUtil { } // required TD fields - if (thing["@context"] === undefined) { + if (thing["@context"] == null) { thing["@context"] = "https://www.w3.org/2022/wot/td/v1.1"; } if (!thing.title) { @@ -551,7 +547,7 @@ export class AssetInterfaceDescriptionUtil { // Security in AID is defined for each submodel // add "securityDefinitions" globally and add them on form level if necessary // TODO: possible collisions for "security" names *could* be handled by cnt - if (thing.securityDefinitions === undefined) { + if (thing.securityDefinitions == null) { thing.securityDefinitions = {}; } // let cnt = 1; @@ -602,10 +598,7 @@ export class AssetInterfaceDescriptionUtil { const tdDescription: Record = {}; if (aasDescription instanceof Array) { for (const aasDescriptionEntry of aasDescription) { - if ( - aasDescriptionEntry.language !== undefined && - aasDescriptionEntry.text !== undefined - ) { + if (aasDescriptionEntry.language != null && aasDescriptionEntry.text != null) { const language: string = aasDescriptionEntry.language; const text: string = aasDescriptionEntry.text; tdDescription[language] = text; @@ -623,10 +616,10 @@ export class AssetInterfaceDescriptionUtil { thing.properties[key].type = interactionValue.value; } } else if (interactionValue.idShort === "range") { - if (interactionValue.min !== undefined) { + if (interactionValue.min != null) { thing.properties[key].min = interactionValue.min; } - if (interactionValue.max !== undefined) { + if (interactionValue.max != null) { thing.properties[key].max = interactionValue.max; } } else if (interactionValue.idShort === "observable") { @@ -704,7 +697,7 @@ export class AssetInterfaceDescriptionUtil { const values: Array = []; // base ? - if (td.base !== undefined) { + if (td.base != null) { values.push({ idShort: "base", valueType: "xs:anyURI", @@ -725,7 +718,7 @@ export class AssetInterfaceDescriptionUtil { // security const securityValues: Array = []; - if (td.security !== undefined) { + if (td.security != null) { for (const secKey of td.security) { securityValues.push({ valueType: "xs:string", @@ -789,10 +782,7 @@ export class AssetInterfaceDescriptionUtil { let formElementPicked: FormElementBase | undefined; if (propertyValue.forms) { for (const formElementProperty of propertyValue.forms) { - if ( - formElementProperty.href !== undefined && - formElementProperty.href.startsWith(protocol) - ) { + if (formElementProperty.href != null && formElementProperty.href.startsWith(protocol)) { formElementPicked = formElementProperty; // found matching form --> abort loop break; @@ -806,7 +796,7 @@ export class AssetInterfaceDescriptionUtil { const propertyValues: Array = []; // type - if (propertyValue.type !== undefined) { + if (propertyValue.type != null) { propertyValues.push({ idShort: "type", valueType: "xs:string", @@ -815,7 +805,7 @@ export class AssetInterfaceDescriptionUtil { }); } // title - if (propertyValue.title !== undefined) { + if (propertyValue.title != null) { propertyValues.push({ idShort: "title", valueType: "xs:string", @@ -824,7 +814,7 @@ export class AssetInterfaceDescriptionUtil { }); } // observable - if (propertyValue.observable !== undefined) { + if (propertyValue.observable != null) { propertyValues.push({ idShort: "observable", valueType: "xs:boolean", @@ -836,7 +826,7 @@ export class AssetInterfaceDescriptionUtil { // range and others? Simply add them as is? // forms - if (formElementPicked !== undefined) { + if (formElementPicked != null) { const propertyForm: Array = []; // TODO AID for now supports just *one* href/form @@ -874,7 +864,7 @@ export class AssetInterfaceDescriptionUtil { text: langValue, }); } - } else if (propertyValue.description !== undefined) { + } else if (propertyValue.description != null) { // fallback description = []; description.push({ diff --git a/packages/td-tools/test/AssetInterfaceDescriptionTest.ts b/packages/td-tools/test/AssetInterfaceDescriptionTest.ts index 2ff6e8dd6..3c582d087 100644 --- a/packages/td-tools/test/AssetInterfaceDescriptionTest.ts +++ b/packages/td-tools/test/AssetInterfaceDescriptionTest.ts @@ -343,7 +343,7 @@ class AssetInterfaceDescriptionUtilTest { expect(hasObservable).to.equal(true); expect(hasForms).to.equal(true); } - if (propertyValue.description !== undefined) { + if (propertyValue.description != null) { hasPropertyStatusDescription = true; expect(propertyValue) .to.have.property("description") From a04d8c778fef668828d67a19eb8b4f784ec75798 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 20 Sep 2023 10:30:37 +0200 Subject: [PATCH 16/29] refactor: revert some changes proposed by @JKRhb leads to different results --- packages/td-tools/src/thing-model-helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index e16ff50bb..970da554b 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -241,7 +241,7 @@ export class ThingModelHelpers { case "http": { return new Promise((resolve, reject) => { http.get(uri, (res) => { - if (res?.statusCode !== 200) { + if (res.statusCode == null || res.statusCode !== 200) { reject(new Error(`http status code not 200 but ${res.statusCode} for ${uri}`)); } @@ -268,7 +268,7 @@ export class ThingModelHelpers { return new Promise((resolve, reject) => { https .get(uri, (res) => { - if (res?.statusCode !== 200) { + if (res.statusCode == null || res.statusCode !== 200) { reject(new Error(`https status code not 200 but ${res.statusCode} for ${uri}`)); } @@ -625,7 +625,7 @@ export class ThingModelHelpers { keys = keys.map((el) => el.replace("{{", "").replace("}}", "")); let isValid = true; let errors; - if ((keys ?? []).length > 0 && map == null) { + if (keys != null && keys.length > 0 && (map === undefined || map === null)) { isValid = false; errors = `No map provided for model ${model.title}`; } else if (keys.length > 0) { From 25d5390b5c9213128cd51404367da2bc98f0f6d9 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 20 Sep 2023 11:05:40 +0200 Subject: [PATCH 17/29] fix: wrong conversion --- packages/td-tools/src/td-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index 1311c776f..71c5fbfc9 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -222,7 +222,7 @@ export function serializeTD(thing: Thing): string { const copy = JSON.parse(JSON.stringify(thing)); // clean-ups - if (copy?.security.length === 0) { + if (copy.security == null || copy.security.length === 0) { copy.securityDefinitions = { nosec_sc: { scheme: "nosec" }, }; From e4c6590dfb565e56859f26b5122686d40a82703b Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 20 Sep 2023 11:11:36 +0200 Subject: [PATCH 18/29] refactor: missing one undefined change --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index e7d1c677f..d325b1279 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -246,7 +246,7 @@ export class AssetInterfaceDescriptionUtil { } private getContentTypeFromEndpointMetadata(endpointMetadata?: Record): string { - if (endpointMetadata?.value !== undefined && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "contentType") { // e.g., "value": "application/octet-stream;byteSeq=BIG_ENDIAN" From 9954040609aad23489b086ed833f85da7ae2b052 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 20 Sep 2023 11:31:49 +0200 Subject: [PATCH 19/29] fix: add proper boolean check --- packages/td-tools/src/thing-model-helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 970da554b..7e99cf6a6 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -405,7 +405,7 @@ export class ThingModelHelpers { for (const key in submodelObj) { const sub = submodelObj[key]; - if (options.selfComposition != null) { + if (options.selfComposition === true) { if (!data.links) { throw new Error( "You used self composition but links are missing; they are needed to extract the instance name" @@ -449,7 +449,7 @@ export class ThingModelHelpers { } } } - if (!data.links || options.selfComposition != null) { + if (!data.links || options.selfComposition === true) { data.links = []; } // add reference to the thing model @@ -508,7 +508,7 @@ export class ThingModelHelpers { extendedModel.properties = {}; } for (const key in properties) { - if (dest.properties != null && dest.properties[key] != null) { + if (dest.properties && dest.properties[key] != null) { extendedModel.properties[key] = { ...properties[key], ...dest.properties[key] }; } else { extendedModel.properties[key] = properties[key]; From f5b386b7b7673c8b4a87106ad1b3e2da25a8796e Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:37:04 +0200 Subject: [PATCH 20/29] Update packages/td-tools/src/thing-model-helpers.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/thing-model-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 7e99cf6a6..7a20ae13e 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -625,7 +625,7 @@ export class ThingModelHelpers { keys = keys.map((el) => el.replace("{{", "").replace("}}", "")); let isValid = true; let errors; - if (keys != null && keys.length > 0 && (map === undefined || map === null)) { + if (keys?.length > 0 && (map === undefined || map === null)) { isValid = false; errors = `No map provided for model ${model.title}`; } else if (keys.length > 0) { From 49c7bc7aee5d6b3d1565edf99d1c66b52188bf00 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:37:45 +0200 Subject: [PATCH 21/29] Update packages/td-tools/src/util/asset-interface-description.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index d325b1279..c67e3b718 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -132,7 +132,7 @@ export class AssetInterfaceDescriptionUtil { public transformTD2SM(tdAsString: string, protocols?: string[]): string { const td: ThingDescription = TDParser.parseTD(tdAsString); - const aidID = td.id != null ? td.id : "ID" + Math.random(); + const aidID = td.id ?? "ID" + Math.random(); logInfo("TD " + td.title + " parsed..."); From 0a8539936c0cf6b63d91064be55b1c98bfbe19ad Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:38:16 +0200 Subject: [PATCH 22/29] Update packages/td-tools/src/util/asset-interface-description.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index c67e3b718..acfa07187 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -295,7 +295,7 @@ export class AssetInterfaceDescriptionUtil { endpointMetadata?: Record ): string | [string, ...string[]] { const security: string[] = []; - if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "security") { if (v.value != null && v.value instanceof Array) { From 3e65aa07c7e690ce1bd3a1539af3370f2cf39a42 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:42:57 +0200 Subject: [PATCH 23/29] Update packages/td-tools/src/util/asset-interface-description.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index acfa07187..b76a09097 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -298,7 +298,7 @@ export class AssetInterfaceDescriptionUtil { if (endpointMetadata?.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "security") { - if (v.value != null && v.value instanceof Array) { + if (v.value instanceof Array) { for (const securityValue of v.value) { if (securityValue.value != null) { security.push(securityValue.value); From f10a4a08af1c75fabeb9d43097a9a184a3f59829 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:43:18 +0200 Subject: [PATCH 24/29] Update packages/td-tools/src/util/asset-interface-description.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index b76a09097..aa8de371f 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -449,7 +449,7 @@ export class AssetInterfaceDescriptionUtil { if (smValue instanceof Object) { if (smValue.idShort === "InterfaceMetadata") { logInfo("InterfaceMetadata"); - if (smValue.value != null && smValue.value instanceof Array) { + if (smValue.value instanceof Array) { for (const interactionValue of smValue.value) { if (interactionValue.idShort === "Properties") { if (interactionValue.value instanceof Array) { From dcb16c33d1d6fcc066c766621891d382a7df73e4 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:43:41 +0200 Subject: [PATCH 25/29] Update packages/td-tools/src/util/asset-interface-description.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index aa8de371f..ea931cd74 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -425,7 +425,7 @@ export class AssetInterfaceDescriptionUtil { private processSubmodelElement(smInformation: SubmodelInformation, submodelElement: Record): void { // EndpointMetadata vs. InterfaceMetadata - if (submodelElement.value != null && submodelElement.value instanceof Array) { + if (submodelElement.value instanceof Array) { // Note: iterate twice over to collect first EndpointMetadata let endpointMetadata: Record = {}; for (const smValue of submodelElement.value) { From 6a496d4bb4d3fd330bf81e9e3c2825706a28d3e6 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:44:20 +0200 Subject: [PATCH 26/29] Update packages/td-tools/src/util/asset-interface-description.ts Co-authored-by: Cristiano Aguzzi --- packages/td-tools/src/util/asset-interface-description.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index ea931cd74..f2c7e28a0 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -408,7 +408,7 @@ export class AssetInterfaceDescriptionUtil { for (const submodelElement of submodel.submodelElements) { if (submodelElement instanceof Object) { logDebug("SubmodelElement.idShort: " + submodelElement.idShort); - if (submodelRegex != null && typeof submodelRegex === "string" && submodelRegex.length > 0) { + if (typeof submodelRegex === "string" && submodelRegex.length > 0) { const regex = new RegExp(submodelRegex); if (!regex.test(submodelElement.idShort)) { logInfo("submodel not of interest"); From 3d78e8e1df2cc541e823243b364e4a194f7e8789 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 10:51:37 +0200 Subject: [PATCH 27/29] refactor: further simplifications --- .../td-tools/src/util/asset-interface-description.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/td-tools/src/util/asset-interface-description.ts b/packages/td-tools/src/util/asset-interface-description.ts index f2c7e28a0..b851af209 100644 --- a/packages/td-tools/src/util/asset-interface-description.ts +++ b/packages/td-tools/src/util/asset-interface-description.ts @@ -234,7 +234,7 @@ export class AssetInterfaceDescriptionUtil { } private getBaseFromEndpointMetadata(endpointMetadata?: Record): string { - if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "base") { // e.g., "value": "modbus+tcp://192.168.1.187:502" @@ -246,7 +246,7 @@ export class AssetInterfaceDescriptionUtil { } private getContentTypeFromEndpointMetadata(endpointMetadata?: Record): string { - if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "contentType") { // e.g., "value": "application/octet-stream;byteSeq=BIG_ENDIAN" @@ -264,11 +264,11 @@ export class AssetInterfaceDescriptionUtil { [k: string]: SecurityScheme; } = {}; - if (endpointMetadata?.value != null && endpointMetadata.value instanceof Array) { + if (endpointMetadata?.value instanceof Array) { for (const v of endpointMetadata.value) { if (v.idShort === "securityDefinitions") { // const securitySchemes: Array = []; - if (v.value != null && v.value instanceof Array) { + if (v.value instanceof Array) { for (const securityDefinitionsValues of v.value) { if (securityDefinitionsValues.idShort != null) { // key @@ -404,7 +404,7 @@ export class AssetInterfaceDescriptionUtil { submodel.idShort != null && submodel.idShort === "AssetInterfacesDescription" ) { - if (submodel.submodelElements != null && submodel.submodelElements instanceof Array) { + if (submodel.submodelElements instanceof Array) { for (const submodelElement of submodel.submodelElements) { if (submodelElement instanceof Object) { logDebug("SubmodelElement.idShort: " + submodelElement.idShort); From fecd6e4143f0171b4e634d06d343a70b6994c9e5 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 13:49:01 +0200 Subject: [PATCH 28/29] Update packages/td-tools/src/td-parser.ts Co-authored-by: Jan Romann --- packages/td-tools/src/td-parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/td-tools/src/td-parser.ts b/packages/td-tools/src/td-parser.ts index 71c5fbfc9..4ba73c973 100644 --- a/packages/td-tools/src/td-parser.ts +++ b/packages/td-tools/src/td-parser.ts @@ -229,7 +229,7 @@ export function serializeTD(thing: Thing): string { copy.security = ["nosec_sc"]; } - if (copy?.forms.length === 0) { + if (copy.forms?.length === 0) { delete copy.forms; } From 7762ea4163987323362138d5c15e7900537c3db2 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 21 Sep 2023 16:32:18 +0200 Subject: [PATCH 29/29] refactor: simplify data.version.model check --- packages/td-tools/src/thing-model-helpers.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/td-tools/src/thing-model-helpers.ts b/packages/td-tools/src/thing-model-helpers.ts index 7a20ae13e..c5ea34b6d 100644 --- a/packages/td-tools/src/thing-model-helpers.ts +++ b/packages/td-tools/src/thing-model-helpers.ts @@ -136,17 +136,9 @@ export class ThingModelHelpers { * @experimental */ public static getModelVersion(data: ThingModel): string | undefined { - if ( - "version" in data && - data.version != null && - typeof data.version === "object" && - "model" in data.version && - typeof data.version.model === "string" - ) { - return data.version.model; - } else { - return undefined; - } + return typeof data?.version === "object" && typeof data?.version?.model === "string" + ? data.version.model + : undefined; } /**