diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 6ced36a92..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2018, // Allows for the parsing of modern ECMAScript features - "sourceType": "module", // Allows for the use of imports - "project": [ "./tsconfig.eslint.json" ] - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "plugins": ["@typescript-eslint", "import"], - "reportUnusedDisableDirectives": true, - "env": { - "node": true - }, - "ignorePatterns": ["*/node_modules/**/*", "*/dist/**/*", "*/build/**/*", "packages/*/dist/**/*", "packages/*/build/**/*", "models/*/**/*", "**/forwards/**/*", "docs/**/*"], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/ban-types": [ - "error", - { - "types": { - "{}": false - }, - "extendDefaults": true - } - ], - - "@typescript-eslint/require-await": "off", - - // We can turn these on from time to time but in general they rules - // make our lives harder instead of easier - "@typescript-eslint/no-unsafe-argument": "off", - "@typescript-eslint/no-unsafe-assignment": "off", - "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/no-unsafe-return": "off", - "@typescript-eslint/no-unsafe-call": "off", - "@typescript-eslint/restrict-template-expressions": "off", - "@typescript-eslint/no-base-to-string": "off", - - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - - "no-restricted-imports": [ - "error", - { - "patterns": [ - { - "group": ["**/export"], - "message": "Please import the directory rather than the export file" - }, - - { - "group": ["**/export.js"], - "message": "Please import directly from the defining file" - } - ] - } - ], - - // Namespaces are the only way to nest types and merge with some declarations. IOW they have uses beyond simple - // package structure which error verbiage indicates is the purpose of the test - "@typescript-eslint/no-namespace": "off", - - // Cannot nest functions within namespaces with this on - "no-inner-declarations": "off", - - // Blocks are the only way to have case-specific variables defined. Alternative is a bunch of lets for all - // possible variables for all cases above the switch. Which sucks - "no-case-declarations": "off", - - // Metaprogramming is impossible with this on - "@typescript-eslint/no-implied-eval": "off", - - // I mean, I understand why this rule exists, but sometimes you need to assign "this" to a variable (see e.g. cd - // method in github.ts) - "@typescript-eslint/no-this-alias": "off", - - // This prevents us from transpiling to ESM that works in both node and the browser for some CommonJS - // dependencies (elliptic and ansi-colors are two examples) - "import/default": "off", - - // TS I believe takes care of this for us, and the plugin does not understand TS object/namespace merges - "import/export": "off", - - // Related to import/default, this generates warnings when we use properties of the default export when eslint - // thinks we should be using the named export. In some cases it isn't even possible to do it the way eslint - // wants us to (e.g. you can't do "import { static } from express because "static" is a reserved word.). In - // other cases the code is valid but the transpiled ESM isn't compatible with Node because it's not smart enough - // to find the "named exports" in CommonJS files - "import/no-named-as-default-member": "off", - - // This makes it impossible to compare non-enums to enums, like one might do with a value off the wire - "@typescript-eslint/no-unsafe-enum-comparison": "off", - - // tsc catches these for us and eslint doesn't recognize references to type imports in comment @links - "@typescript-eslint/no-unused-vars": "off", - - // This is highly inconvenient and breaks basic language features. I don't think we've ever actually unbound - // a method unintentionally and we do it quite often intentionally. Perhaps its useful if you aren't authoring - // a library - "@typescript-eslint/unbound-method": "off", - - // Umm, this mattered for IE <= 8?? - "no-ex-assign": "off", - - // Always of dubious value, this rule is buggy as of typescript-eslint 7.2.0 and TS 5.4.2 (works w/ TS 5.3.3 - // though) - "@typescript-eslint/no-redundant-type-constituents": "off", - - // This rule is fine... Except it's redundant with tsc and seems to be buggy with wildcard package.json - // import aliases - "import/no-unresolved": "off" - }, - "settings": { - "import/extensions": [".ts"], - "import/parsers": { - "@typescript-eslint/parser": [".ts"] - }, - "import/resolver": { - "typescript": { - // Multiple tsconfigs (Useful for monorepos) - "project": "packages/*/tsconfig.json" - } - } - } -} diff --git a/codegen/src/clusters/TlvGenerator.ts b/codegen/src/clusters/TlvGenerator.ts index 0bcbc5712..615e5b213 100644 --- a/codegen/src/clusters/TlvGenerator.ts +++ b/codegen/src/clusters/TlvGenerator.ts @@ -193,7 +193,7 @@ export class TlvGenerator { * Get the filename for global datatypes. */ static filenameFor(model: Model) { - const name = model.name.replace(/(Enum|Bitmap|Struct)$/, ""); + const name = model.name.replace(/Enum|Bitmap|Struct$/, ""); return camelize(name, true); } diff --git a/codegen/src/mom/spec/add-documentation.ts b/codegen/src/mom/spec/add-documentation.ts index 4c16b0c14..7c459a8ca 100644 --- a/codegen/src/mom/spec/add-documentation.ts +++ b/codegen/src/mom/spec/add-documentation.ts @@ -52,11 +52,11 @@ function extractUsefulDocumentation(p: HTMLElement) { .replace(/ such that:$/, "") .replace(/, derived from \w+,/, "") .replace(/\([^)]*$/, "") - .replace(/\s\s+/, " ") + .replace(/\s{2,}/, " ") .replace(/This attribute shall (?:indicate|represent)/, "Indicates") .replace(/This attribute shall be null/, "Null") .replace(/The following tags are defined in this namespace\./, "") - .replace(/This section contains the (.*) as part of the semantic tag feature\./i, "") + .replace(/This section contains the .* as part of the semantic tag feature\./i, "") .replace( /The table below lists the changes relative to the Mode Base Cluster for the fields of the ModeOptionStruct type\./, "", @@ -70,7 +70,7 @@ function extractUsefulDocumentation(p: HTMLElement) { function mergeSplitParagraphs(paragraphs: string[]) { for (let i = 0; i < paragraphs.length - 1; i++) { const trailing = paragraphs[i].replace(/^.*\s(\w+)$/, "$1").toLowerCase(); - const leading = paragraphs[i + 1].replace(/^(\w+).*$/, "$1").toLowerCase(); + const leading = paragraphs[i + 1].replace(/^(\w+)\W.*$/, "$1").toLowerCase(); if (Words.has(leading) && !NotWords.has(leading) && Words.has(trailing) && !NotWords.has(trailing)) { continue; } diff --git a/codegen/src/mom/spec/doc-utils.ts b/codegen/src/mom/spec/doc-utils.ts index c12935c05..d36d64be3 100644 --- a/codegen/src/mom/spec/doc-utils.ts +++ b/codegen/src/mom/spec/doc-utils.ts @@ -82,7 +82,7 @@ export function identifyDocument(path: string): IndexDetail { let version; const titleAndVersion = title.split(/ version /i); - if (titleAndVersion.length === 2 && titleAndVersion[1].match(/(?:\d\.)+/i)) { + if (titleAndVersion.length === 2 && titleAndVersion[1].match(/(?:\d\.)+/)) { title = titleAndVersion[0]; version = titleAndVersion[1]; } else { @@ -90,7 +90,7 @@ export function identifyDocument(path: string): IndexDetail { if (!versionEl || !versionEl.textContent || !versionEl.textContent.match(/version (?:\d\.)+/i)) { throw new Error(`No version found for ${title} in ${path}`); } - version = versionEl.textContent.replace(/.*version ([\d.]+).*/i, "$1"); + version = versionEl.textContent.replace(/.*version ([\d.]).*/i, "$1"); } // Drop dotted elements except the first two. To date these have represented trivial changes diff --git a/codegen/src/mom/spec/html-translators.ts b/codegen/src/mom/spec/html-translators.ts index 3699a3504..09fa397f9 100644 --- a/codegen/src/mom/spec/html-translators.ts +++ b/codegen/src/mom/spec/html-translators.ts @@ -24,7 +24,7 @@ export const Str = (el: HTMLElement) => { // P starts with text child.firstChild?.nodeType === 3 /** TEXT_CONTENT */ && // Containing a single digit - child.firstChild.textContent?.match(/^[0-9]$/) && + child.firstChild.textContent?.match(/^\d$/) && // Followed by a span (child.firstChild.nextSibling as Element)?.tagName === "SPAN" && // That doesn't indicate numeric arity @@ -146,7 +146,7 @@ export const Code = (el: HTMLElement) => { const beginning = parts[i].replace(/^.*([A-Z])/, "$1"); // Get ending of word from next part - const ending = parts[i + 1].replace(/^([a-z]+).*/, "$1"); + const ending = parts[i + 1].replace(/^([a-z]).*/, "$1"); // If the concatenation is a word, assume it should be joined if (Words.has(`${beginning}${ending}`.toLowerCase())) { @@ -180,7 +180,7 @@ export const Identifier = (el: HTMLElement) => { let str = Code(el); // Strip everything following a subset of characters known to be inside what is properly a "key" - str = str.replace(/^([a-z0-9 _:.,/\-$]+).*/i, "$1"); + str = str.replace(/^([\w :.,/\-$]+)/, "$1"); return camelize(str, true); }; diff --git a/codegen/src/mom/spec/load-clusters.ts b/codegen/src/mom/spec/load-clusters.ts index 23265a373..bad36926b 100644 --- a/codegen/src/mom/spec/load-clusters.ts +++ b/codegen/src/mom/spec/load-clusters.ts @@ -288,7 +288,7 @@ export function* loadClusters(clusters: HtmlReference): Generator { let key = cell.textContent || ""; - key = key.replace(/[\W]/g, "").toLowerCase(); + key = key.replace(/\W/g, "").toLowerCase(); table?.fields.push(key); }); continue; diff --git a/codegen/src/mom/spec/translate-cluster.ts b/codegen/src/mom/spec/translate-cluster.ts index f9bf458e1..bcffd2ee3 100644 --- a/codegen/src/mom/spec/translate-cluster.ts +++ b/codegen/src/mom/spec/translate-cluster.ts @@ -304,7 +304,7 @@ function translateInvokable(definition: ClusterReference, children: Array { let direction: CommandElement.Direction | undefined; - if (r.direction?.match(/client.*⇐.*server/i)) { + if (r.direction?.match(/client[^⇐]*⇐[^⇐]*server/i)) { direction = CommandElement.Direction.Response; } else if (r.direction?.match(/client.*server/i)) { direction = CommandElement.Direction.Request; diff --git a/codegen/src/mom/spec/translate-datatype.ts b/codegen/src/mom/spec/translate-datatype.ts index 8f77a635c..c7d016d34 100644 --- a/codegen/src/mom/spec/translate-datatype.ts +++ b/codegen/src/mom/spec/translate-datatype.ts @@ -45,24 +45,22 @@ export function translateDatatype(definition: HtmlReference): DatatypeElement | } // Up through 1.1 prose was informal but remarkably consistent; "derived from" always matches - let match = text?.match(/derived from ([a-z0-9\-_]+)/i); + let match = text?.match(/derived from ([\w-]+)/i); // This now applies to cluster 1.2 § 1.14.15.1, because consistency is overrated if (!match) { - match = text?.match(/data type shall be a ([a-z0-9\-_]+)/i); + match = text?.match(/data type shall be a ([\w-]+)/i); } // Applies to a handful of overrides of ModeOptionStruct in cluster 1.2 if (!match) { - match = text?.match( - /lists the changes relative to the [a-z0-9\-_ ]+ cluster for the fields of the ([a-z0-9\-_]+) type/i, - ); + match = text?.match(/lists the changes relative to the [\w\- ]+ cluster for the fields of the ([\w-]+) type/i); } // And 1.3 throws in this beaut let constraint: string | undefined; if (!match) { - match = text?.match(/This data type is an? ([a-z0-9\-_]+) of fixed length (\d+)/i); + match = text?.match(/This data type is an? ([\w-]+) of fixed length (\d+)/i); constraint = match?.[2]; } diff --git a/codegen/src/util/TsFile.ts b/codegen/src/util/TsFile.ts index d3f5857b4..bf60a9c2d 100644 --- a/codegen/src/util/TsFile.ts +++ b/codegen/src/util/TsFile.ts @@ -292,7 +292,7 @@ export class Block extends Entry { let m = s.match(/^(\w+):/); if (!m) { m = s.match( - /\s*(?:(?:export|public|private|const)\s+)*(?:(?:function|enum|class|interface|const|var|let)\s+)(\w+)/, + /\s*(?:(?:export|public|private|const)\s+)*(?:function|enum|class|interface|const|var|let)\s+(\w+)/, ); } if (m) { @@ -408,9 +408,7 @@ export class Block extends Entry { protected delimiterAfter(entry: Entry, serialized: string): string { if ( - serialized.match( - /^(?:\s*(?:\/\*.*\*\/|export|const))*\s*(?:export)?\s*(?:enum|function|namespace|interface|class)/m, - ) + serialized.match(/^\s*(?:\/\*(?!\*\/)\*\/\s*)?(?:export\s*)?(?:enum|function|namespace|interface|class)\s/m) ) { // Do not delimit functions structures that eslint will complain about return ""; @@ -497,7 +495,7 @@ function chooseExpressionLayout(lineLength: number, prefix: string, serializedEn const multiline = entry.indexOf("\n") !== -1; // Any comment or assignment automatically forces verbose layout mode - if (entry.match(/(?:\/\*|\/\/| = )/)) { + if (entry.match(/\/\*|\/\/| = /)) { return ExpressionLayout.Verbose; } @@ -740,7 +738,7 @@ export class TsFile extends Block { } else if (filename.startsWith("@matter/")) { // For @matter/package we assume an alias of "#package"; for "@matter/package/submodule" we assume an // alias of "#submodule" - return filename.replace(/^@matter\/(?:[^/]+\/)/, "#"); + return filename.replace(/^@matter\/[^/]+\//, "#"); } else { throw new InternalError(`Absolute import of ${filename} must start with "@matter"`); } diff --git a/codegen/src/util/string.ts b/codegen/src/util/string.ts index 3bbcd4c86..8054443fc 100644 --- a/codegen/src/util/string.ts +++ b/codegen/src/util/string.ts @@ -12,7 +12,7 @@ export { camelize, describeList, serialize } from "#general"; */ export function asObjectKey(label: any) { let str = `${label}`; - if (!str.match(/^[$_a-z][$_a-z0-9]*$/i)) { + if (!str.match(/^[$_a-z][$\w]*$/i)) { str = JSON.stringify(label); } return str; diff --git a/eslint.config.mjs b/eslint.config.mjs index f5d39af3c..351a764ff 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,3 +1,9 @@ +/** + * @license + * Copyright 2022-2025 Project CHIP Authors + * SPDX-License-Identifier: Apache-2.0 + */ + import { fixupConfigRules, fixupPluginRules } from "@eslint/compat"; import { FlatCompat } from "@eslint/eslintrc"; import js from "@eslint/js"; @@ -37,6 +43,7 @@ export default [ "plugin:import/errors", "plugin:import/warnings", "plugin:import/typescript", + "plugin:regexp/recommended", ), ), { diff --git a/package-lock.json b/package-lock.json index 58b3f3016..b2db2aa92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,7 @@ "embedme": "^1.22.1", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-regexp": "^2.7.0", "globals": "^15.14.0", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", @@ -6824,6 +6825,16 @@ "node": ">=18" } }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -7972,6 +7983,28 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-regexp": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.7.0.tgz", + "integrity": "sha512-U8oZI77SBtH8U3ulZ05iu0qEzIizyEDXd+BWHvyVxTOjGwcDcvy/kEpgFG4DYca2ByRLiVPFZ2GeH7j1pdvZTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "comment-parser": "^1.4.0", + "jsdoc-type-pratt-parser": "^4.0.0", + "refa": "^0.12.1", + "regexp-ast-analysis": "^0.7.1", + "scslre": "^0.3.0" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "eslint": ">=8.44.0" + } + }, "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", @@ -10311,6 +10344,16 @@ "signal-exit": "^3.0.2" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsdom": { "version": "26.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz", @@ -13457,6 +13500,19 @@ "node": ">= 4" } }, + "node_modules/refa": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz", + "integrity": "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -13517,6 +13573,20 @@ "@babel/runtime": "^7.8.4" } }, + "node_modules/regexp-ast-analysis": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz", + "integrity": "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.1" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -13812,6 +13882,21 @@ "loose-envify": "^1.1.0" } }, + "node_modules/scslre": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz", + "integrity": "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.8.0", + "refa": "^0.12.0", + "regexp-ast-analysis": "^0.7.0" + }, + "engines": { + "node": "^14.0.0 || >=16.0.0" + } + }, "node_modules/selfsigned": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", diff --git a/package.json b/package.json index a13e327a5..040f21801 100644 --- a/package.json +++ b/package.json @@ -46,15 +46,16 @@ "relock": "node -e \"fs.rmSync('package-lock.json', { force: true }); fs.rmSync('node_modules', { recursive: true, force: true });\" && npm install" }, "devDependencies": { + "@eslint/compat": "^1.2.5", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "^9.17.0", "@typescript-eslint/eslint-plugin": "^8.19.0", "@typescript-eslint/parser": "^8.20.0", "c8": "^10.1.3", "embedme": "^1.22.1", - "@eslint/compat": "^1.2.5", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.17.0", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-import": "^2.31.0", + "eslint-plugin-regexp": "^2.7.0", "globals": "^15.14.0", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.1.0", diff --git a/packages/cli-tool/src/parser.ts b/packages/cli-tool/src/parser.ts index 0d253219f..d2c64b9c7 100644 --- a/packages/cli-tool/src/parser.ts +++ b/packages/cli-tool/src/parser.ts @@ -237,7 +237,7 @@ export namespace isCommand { const statementStarts = [...STATEMENT_KEYWORDS.map(kw => `${kw}${EOW}`), `${IDENTIFIER}\\s*=`]; - const commandStarts = ["\\.", "\\.\\.", `\\s*(?:\\.?\\.?/)?${PATH_SEGMENT}(?:\\/(?:\\.?\\.|${PATH_SEGMENT}))*`]; + const commandStarts = ["\\.", "\\.\\.", `\\s*(?:\\.{0,2}/)?${PATH_SEGMENT}(?:\\/(?:\\.?\\.|${PATH_SEGMENT}))*`]; // If this regexp matches, input is NOT a command export const STATEMENT_DETECTOR = new RegExp(`^\\s*(?:${statementStarts.join("|")})`, "u"); diff --git a/packages/cli-tool/src/repl.ts b/packages/cli-tool/src/repl.ts index 6ed9f8b55..cb2a0e39e 100644 --- a/packages/cli-tool/src/repl.ts +++ b/packages/cli-tool/src/repl.ts @@ -252,7 +252,7 @@ function evaluate( } else { // Look for the "matter-cli-" marker which we prefix on the "filename" specialLine = lines.findIndex(line => { - const match = line.match(/at matter-cli-(?:[a-z]+):([0-9]+:[0-9]+)?/); + const match = line.match(/at matter-cli-[a-z]+:(\d+:\d+)?/); if (match) { specialLoc = match[1]; return true; diff --git a/packages/create/src/build.config.ts b/packages/create/src/build.config.ts index 3b25cd5c0..e27985aae 100644 --- a/packages/create/src/build.config.ts +++ b/packages/create/src/build.config.ts @@ -45,7 +45,7 @@ export async function before({ project }: Project.Context) { // Quick hack to pull out imports, assumes modules formatted by prettier. More than sufficient for current // needs - for (const [, pkgName] of source.matchAll(/import .* from "(@[^/"]+\/[^/"]+|[^/"]+)[^"]*";/g)) { + for (const [, pkgName] of source.matchAll(/import .* from "(@[^/"]+\/[^/"]+|[^/"]+)";/g)) { if (dependencies[pkgName]) { continue; } diff --git a/packages/general/src/codec/DerCodec.ts b/packages/general/src/codec/DerCodec.ts index d4a0b5973..eb14f976e 100644 --- a/packages/general/src/codec/DerCodec.ts +++ b/packages/general/src/codec/DerCodec.ts @@ -203,7 +203,7 @@ export class DerCodec { } private static encodePrintableString(value: string) { - if (!/^[A-Za-z0-9 '()+,-./:=?]*$/g.test(value)) { + if (!/^[a-z0-9 '()+,\-./:=?]*$/i.test(value)) { throw new UnexpectedDataError(`String ${value} is not a printable string.`); } return this.encodeAsn1(DerType.PrintableString, Bytes.fromString(value)); diff --git a/packages/general/src/environment/Environment.ts b/packages/general/src/environment/Environment.ts index 5d391cfb1..fb9cce85f 100644 --- a/packages/general/src/environment/Environment.ts +++ b/packages/general/src/environment/Environment.ts @@ -176,8 +176,8 @@ export class Environment { let events = this.#serviceEvents.get(type); if (events === undefined) { events = { - added: new Observable(), - deleted: new Observable(), + added: Observable(), + deleted: Observable(), }; this.#serviceEvents.set(type, events); } diff --git a/packages/general/src/log/Diagnostic.ts b/packages/general/src/log/Diagnostic.ts index 19ad555fa..33ac31c42 100644 --- a/packages/general/src/log/Diagnostic.ts +++ b/packages/general/src/log/Diagnostic.ts @@ -550,7 +550,7 @@ function messageAndStackFor(error: any, parentStack?: string[]) { // Spiff up stack lines a bit const stack = Array(); for (const line of stackLines) { - const match1 = line.match(/^at\s+(?:(.+)\s+\(([^)]+)\)|())$/); + const match1 = line.match(/^at\s+(?:(\S|\S.*\S)\s+\(([^)]+)\)|())$/); if (match1) { const value = [Diagnostic.weak("at "), match1[1] ?? match1[3]]; if (match1[2] !== undefined) { @@ -560,7 +560,7 @@ function messageAndStackFor(error: any, parentStack?: string[]) { continue; } - const match2 = line.match(/^at\s+(.+)(:\d+:\d+)$/); + const match2 = line.match(/^at\s+(\S.*)(:\d+:\d+)$/); if (match2) { stack.push(Diagnostic.squash(Diagnostic.weak("at "), match2[1], Diagnostic.weak(match2[2]))); continue; diff --git a/packages/general/src/log/LogFormat.ts b/packages/general/src/log/LogFormat.ts index 52e53388b..a76c3e6e2 100644 --- a/packages/general/src/log/LogFormat.ts +++ b/packages/general/src/log/LogFormat.ts @@ -384,7 +384,7 @@ function formatAnsi(diagnostic: unknown, indents = 0) { if (text === "") { return text; } - const segments = text.match(/([^✓✔✗✘]+|[✓✔✗✘])/g); + const segments = text.match(/[^✓✔✗✘]+|[✓✔✗✘]/g); if (segments === null) { throw new InternalError("ANSI text processing regex failure"); } @@ -682,8 +682,8 @@ function formatTime(time: Date) { * Multiline messages should always have whitespace as the first character after newlines. Ensure this is so. */ function ensureIndented(text: string) { - if (text.match(/\n\S/s)) { - return text.replace(/\n/gs, "\n "); + if (text.match(/\n\S/)) { + return text.replace(/\n/g, "\n "); } return text; } diff --git a/packages/general/src/log/Logger.ts b/packages/general/src/log/Logger.ts index c7f06008e..d565599af 100644 --- a/packages/general/src/log/Logger.ts +++ b/packages/general/src/log/Logger.ts @@ -151,7 +151,7 @@ export class Logger { let levelNum; if (typeof level === "string") { - if (level.match(/^[0-9]+$/)) { + if (level.match(/^\d+$/)) { levelNum = Number.parseInt(level); } else { levelNum = (LogLevel as unknown as Record)[level.toUpperCase()]; diff --git a/packages/general/src/util/FormattedText.ts b/packages/general/src/util/FormattedText.ts index 4bb1e2431..ee82415db 100644 --- a/packages/general/src/util/FormattedText.ts +++ b/packages/general/src/util/FormattedText.ts @@ -65,7 +65,7 @@ function detectList(text: string, listState: ListType[]) { return false; } - if (detectEnumeration(/^[0-9]+\./, ListType.Number, "1")) return; + if (detectEnumeration(/^\d+\./, ListType.Number, "1")) return; if (detectEnumeration(/^[ivx]+\./, ListType.LowerRoman, "i")) return; if (detectEnumeration(/^[IVX]+\./, ListType.UpperRoman, "I")) return; if (detectEnumeration(/^[a-z]+\./, ListType.LowerAlpha, "a")) return; @@ -144,13 +144,25 @@ function detectStructure(text: string): TextStructure { } function wrapParagraph(input: string, into: string[], wrapWidth: number, padding: number, prefixWidth: number) { - // Note - do not wrap text surrounded by "{@" and "}" as this is likely a ESDoc directive and ESDoc doesn't like - // directives wrapped - const segments = input.match(/(?:{@[^}]+}|\S+)(?:\s+|$)/g); - if (!segments?.length) { + const segments = input.match(/\s+/g); + if (!segments) { return; } + // Reassemble text surrounded by "{@" and "}" as this is likely an ESDoc directive and ESDoc doesn't like directives + // wrapped + for (let i = 0; i < segments?.length; i++) { + if (!segments[i].includes("{@")) { + continue; + } + for (let j = i; j < segments.length; j++) { + if (segments[j].includes("}")) { + segments.splice(i, j - i + 1, segments.slice(i, j + 1).join(" ")); + break; + } + } + } + // Configure for list prefix formatting let wrapPrefix: string; if (prefixWidth) { diff --git a/packages/general/src/util/GeneratedClass.ts b/packages/general/src/util/GeneratedClass.ts index 55ae656bf..588241ecf 100644 --- a/packages/general/src/util/GeneratedClass.ts +++ b/packages/general/src/util/GeneratedClass.ts @@ -116,16 +116,15 @@ interface ConstructorOptions { function createConstructor({ name, base, args, mixins }: ConstructorOptions) { // CJS Transpilation renames this symbol so bring it local to access + // @ts-expect-error this is used by generated code that TS knows nothing of const _InternalError = InternalError; - // eslint-disable-next-line @typescript-eslint/no-unused-expressions - _InternalError; // Have to use eval if we don't want every class to be called "GeneratedClass" in the debugger but we can ensure // this won't be abused. // // "name" is the only input to this function that appears textually in the eval. We limit it to letters, numbers, // "$" and "_". - if (!name.match(/^(?:\p{L}|[0-9$_])+$/u)) { + if (!name.match(/^[\p{L}0-9$_]+$/u)) { throw new InternalError("Refusing to generate class with untrustworthy name"); } diff --git a/packages/general/src/util/String.ts b/packages/general/src/util/String.ts index e8768e1ed..a98c6946b 100644 --- a/packages/general/src/util/String.ts +++ b/packages/general/src/util/String.ts @@ -104,7 +104,7 @@ export function serialize(value: any) { const visited = new Set(); function asValidKey(key: string) { - if (key.match(/[a-z_$][a-z_$0-9]*/i)) { + if (key.match(/[a-z_$][\w$]*/i)) { return key; } return JSON.stringify(key); diff --git a/packages/general/test/util/ObservableTest.ts b/packages/general/test/util/ObservableTest.ts index 1f3142d02..3b89d6995 100644 --- a/packages/general/test/util/ObservableTest.ts +++ b/packages/general/test/util/ObservableTest.ts @@ -12,7 +12,7 @@ import { Observable, ObserverGroup } from "#util/Observable.js"; describe("ObservableGroup", () => { // Test for TS bug workaround it("supports variable argument lengths", () => { - const observable = new Observable<[foo: string, bar: boolean]>(); + const observable = Observable<[foo: string, bar: boolean]>(); const observers = new ObserverGroup(); observers.on(observable, foo => { if (foo === "four") return; @@ -24,7 +24,7 @@ describe("ObservableGroup", () => { }); it("installs observers", () => { - const observable = new Observable<[foo: string]>(); + const observable = Observable<[foo: string]>(); const observers = new ObserverGroup(); let observedValue: string | undefined; @@ -40,7 +40,7 @@ describe("ObservableGroup", () => { }); it("removes observers on close", () => { - const observable = new Observable<[foo: string]>(); + const observable = Observable<[foo: string]>(); const observers = new ObserverGroup(); observers.on(observable, () => {}); diff --git a/packages/matter.js/src/cluster/server/CommissioningServerFailsafeContext.ts b/packages/matter.js/src/cluster/server/CommissioningServerFailsafeContext.ts index 5a38bb642..bc9cd24bf 100644 --- a/packages/matter.js/src/cluster/server/CommissioningServerFailsafeContext.ts +++ b/packages/matter.js/src/cluster/server/CommissioningServerFailsafeContext.ts @@ -6,7 +6,7 @@ import { BasicInformation, GeneralCommissioning, NetworkCommissioning, OperationalCredentials } from "#clusters"; import { asyncNew } from "#general"; -import { EndpointInterface, Fabric, FailsafeContext } from "#protocol"; +import { type EndpointInterface, Fabric, FailsafeContext } from "#protocol"; import { EndpointNumber, TypeFromSchema } from "#types"; import { Endpoint } from "../../device/Endpoint.js"; diff --git a/packages/matter.js/src/cluster/server/GeneralDiagnosticsServer.ts b/packages/matter.js/src/cluster/server/GeneralDiagnosticsServer.ts index f58767433..181a6b191 100644 --- a/packages/matter.js/src/cluster/server/GeneralDiagnosticsServer.ts +++ b/packages/matter.js/src/cluster/server/GeneralDiagnosticsServer.ts @@ -64,7 +64,7 @@ export const GeneralDiagnosticsClusterHandler: () => Promise< isOperational: true, offPremiseServicesReachableIPv4: null, // null means unknown or not supported offPremiseServicesReachableIPv6: null, // null means unknown or not supported - hardwareAddress: Bytes.fromHex(mac.replace(/[^\da-fA-F]/g, "")), + hardwareAddress: Bytes.fromHex(mac.replace(/[^\da-f]/gi, "")), iPv4Addresses: ipV4.slice(0, 4).map(ip => ipv4ToBytes(ip)), iPv6Addresses: ipV6.slice(0, 8).map(ip => ipv6ToBytes(ip)), type: type ?? GeneralDiagnostics.InterfaceType.Ethernet, diff --git a/packages/model/src/aspects/Constraint.ts b/packages/model/src/aspects/Constraint.ts index 44f382bd6..d87329673 100644 --- a/packages/model/src/aspects/Constraint.ts +++ b/packages/model/src/aspects/Constraint.ts @@ -36,9 +36,14 @@ export class Constraint extends Aspect implements Constra switch (typeof definition) { case "string": // The spec designates a "0b000xxxxx" syntax for specifying constraints as bitmasks. Through 1.3 we - // only see this on bitmaps which constraint fine using the bit definitions. So just ignore it. We also + // only see this on bitmaps which constrain fine using the bit definitions. So just ignore it. We also // handle one invalid case where there is no "0b" or "0x" prefix on a mask - if (definition.match(/(?:0b[0x ]*x[0x ]*)|(?:0x[0x_]*x[0x_]*)|(?:00[0x]*x)/i)) { + if ( + // Mask + definition.match(/^0b[0x ]+$/) || + // Hack to identify mask without 0b prefix + (definition.startsWith("00") && definition.includes("x") && definition.match(/^[0x ]+$/)) + ) { break; } ast = Parser.parse(this, definition); diff --git a/packages/model/src/common/Metatype.ts b/packages/model/src/common/Metatype.ts index c7f81627d..9a3680730 100644 --- a/packages/model/src/common/Metatype.ts +++ b/packages/model/src/common/Metatype.ts @@ -176,7 +176,7 @@ export namespace Metatype { cast.enum = (value: any): number | string | null | undefined => { if (typeof value === "string") { - if (value.trim().match(/^(?:[0-9]+|0x[0-9a-f]+|0b[01]+)$/)) { + if (value.trim().match(/^(?:\d+|0x[0-9a-f]+|0b[01]+)$/)) { value = Number.parseInt(value); } else { return value; diff --git a/packages/model/src/logic/DefaultValue.ts b/packages/model/src/logic/DefaultValue.ts index e5f8d1e76..83f0538e9 100644 --- a/packages/model/src/logic/DefaultValue.ts +++ b/packages/model/src/logic/DefaultValue.ts @@ -202,7 +202,7 @@ function buildBitmap(scope: Scope, model: ValueModel) { maxBit = Math.trunc(Math.log2(defaultValue)) + 1; } - for (let i = 0, mask = 1 << minBit; i < maxBit - minBit; i++, mask << 1) { + for (let i = 0, mask = 1 << minBit; i < maxBit - minBit; i++, mask <<= 1) { if (fieldsDefined & mask) { continue; } diff --git a/packages/model/src/logic/cluster-variance/IllegalFeatureCombinations.ts b/packages/model/src/logic/cluster-variance/IllegalFeatureCombinations.ts index c12db7540..483e20116 100644 --- a/packages/model/src/logic/cluster-variance/IllegalFeatureCombinations.ts +++ b/packages/model/src/logic/cluster-variance/IllegalFeatureCombinations.ts @@ -190,11 +190,11 @@ function addFeatureNode( if (node.param.num > 1) { unsupported(); } - let choice = choices[node.param.name]; + const choice = choices[node.param.name]; if (choice) { choice.features.push(feature.name); } else { - choice = choices[node.param.name] = { + choices[node.param.name] = choices[node.param.name] = { exclusive: !node.param.orMore, features: [feature.name], }; diff --git a/packages/model/src/models/Children.ts b/packages/model/src/models/Children.ts index 7d0608a95..6de12f291 100644 --- a/packages/model/src/models/Children.ts +++ b/packages/model/src/models/Children.ts @@ -537,7 +537,7 @@ export function Children( const self = new Proxy(children, { get: (_target, name, receiver) => { - if (typeof name === "string" && name.match(/^[0-9]+$/)) { + if (typeof name === "string" && name.match(/^\d+$/)) { let child = children[name as unknown as number]; if (child && !(child instanceof Model)) { child = Model.create(child) as T; @@ -584,7 +584,7 @@ export function Children( }, set: (_target, name, value, receiver) => { - if (typeof name !== "string" || !name.match(/^[0-9]+$/)) { + if (typeof name !== "string" || !name.match(/^\d+$/)) { if (name === "length") { if (value > children.length) { // Do not allow preallocation that would create gaps @@ -636,7 +636,7 @@ export function Children( deleteProperty: (_target, p) => { let child: undefined | Model.Definition; - if (typeof p === "string" && p.match(/^[0-9]+$/)) { + if (typeof p === "string" && p.match(/^\d+$/)) { child = children[p as unknown as number]; } diff --git a/packages/model/src/models/Model.ts b/packages/model/src/models/Model.ts index f8868c0de..610e2d1ed 100644 --- a/packages/model/src/models/Model.ts +++ b/packages/model/src/models/Model.ts @@ -574,7 +574,7 @@ export abstract class Model { if (this.#children !== undefined && this.#children.length) { props.children = this.#children.length; } - return `${inspect(props, options)}`.replace(/^{/, `${decamelize(this.tag)} {`); + return `${inspect(props, options)}`.replace(/^\{/, `${decamelize(this.tag)} {`); } } diff --git a/packages/model/src/standard/elements/models.ts b/packages/model/src/standard/elements/models.ts index d18b45c95..a52ee898b 100644 --- a/packages/model/src/standard/elements/models.ts +++ b/packages/model/src/standard/elements/models.ts @@ -172,8 +172,8 @@ export const powerMW = new DatatypeModel(definitions.powerMW); export const amperageMA = new DatatypeModel(definitions.amperageMA); export const voltageMV = new DatatypeModel(definitions.voltageMV); export const energyMWh = new DatatypeModel(definitions.energyMWh); -export const enum8 = new DatatypeModel(definitions.enum8) -export const enum16 = new DatatypeModel(definitions.enum16) +export const enum8 = new DatatypeModel(definitions.enum8); +export const enum16 = new DatatypeModel(definitions.enum16); export const priority = new DatatypeModel(definitions.priority); export const status = new DatatypeModel(definitions.status); export const groupId = new DatatypeModel(definitions.groupId); diff --git a/packages/node/src/behavior/errors.ts b/packages/node/src/behavior/errors.ts index e565793e5..1bbc4f7dd 100644 --- a/packages/node/src/behavior/errors.ts +++ b/packages/node/src/behavior/errors.ts @@ -64,9 +64,9 @@ export class ValidateError extends SchemaViolationError { */ export class DatatypeError extends ValidateError { constructor(path: SchemaErrorPath, type: string, value: unknown, code?: StatusCode) { - const str = `${value}`; + let str = `${value}`; if (str.length > 60) { - value = `${str.substring(60)}…`; + str = `${str.substring(60)}…`; } super(path, `Value "${str}" is not ${type}`, code); } diff --git a/packages/node/src/behavior/internal/Reactors.ts b/packages/node/src/behavior/internal/Reactors.ts index 1cf808761..4a5baebf9 100644 --- a/packages/node/src/behavior/internal/Reactors.ts +++ b/packages/node/src/behavior/internal/Reactors.ts @@ -284,11 +284,6 @@ class ReactorBacking { // Otherwise run in independent context and errors do not interfere with emitter try { - let purpose = "react"; - if (this.#reactor.name) { - purpose = `${purpose}<${this.#reactor.name}>`; - } - const reactor = (context: ActionContext) => { return this.#reactWithContext(context, this.#owner.backing, args); }; diff --git a/packages/node/src/behavior/state/managed/values/ListManager.ts b/packages/node/src/behavior/state/managed/values/ListManager.ts index e5b55a643..a74ac82b1 100644 --- a/packages/node/src/behavior/state/managed/values/ListManager.ts +++ b/packages/node/src/behavior/state/managed/values/ListManager.ts @@ -336,7 +336,7 @@ function createProxy(config: ListConfig, reference: Val.Reference, ses if (typeof k !== "string") { return true; } - if (!k.match(/^[0-9]+$/)) { + if (!k.match(/^\d+$/)) { return true; } if (Number.parseInt(k) < length) { @@ -349,7 +349,7 @@ function createProxy(config: ListConfig, reference: Val.Reference, ses }; getOwnPropertyDescriptor = (_target, key) => { - if (typeof key === "string" && key.match(/^[0-9]+$/)) { + if (typeof key === "string" && key.match(/^\d+$/)) { key = Number.parseInt(key); } if (typeof key !== "number") { @@ -364,7 +364,7 @@ function createProxy(config: ListConfig, reference: Val.Reference, ses const target = [] as Val.List; const handlers: ProxyHandler = { get(_target, property, receiver) { - if (typeof property === "string" && property.match(/^[0-9]+/)) { + if (typeof property === "string" && property.match(/^\d+/)) { sublocation.path.id = property; return readEntry(Number.parseInt(property), sublocation); } @@ -393,7 +393,7 @@ function createProxy(config: ListConfig, reference: Val.Reference, ses // On write we enter a transaction set(_target, property, newValue, receiver) { - if (typeof property === "string" && property.match(/^[0-9]+/)) { + if (typeof property === "string" && property.match(/^\d+/)) { sublocation.path.id = property; validateEntry?.(newValue, session, sublocation); writeEntry(Number.parseInt(property), newValue, sublocation); @@ -407,7 +407,7 @@ function createProxy(config: ListConfig, reference: Val.Reference, ses }, has(_target, property) { - if (typeof property === "string" && property.match(/^[0-9]+/)) { + if (typeof property === "string" && property.match(/^\d+/)) { return hasEntry(Number.parseInt(property)); } @@ -415,7 +415,7 @@ function createProxy(config: ListConfig, reference: Val.Reference, ses }, deleteProperty: (_target, property) => { - if (typeof property === "string" && property.match(/^[0-9]+/)) { + if (typeof property === "string" && property.match(/^\d+/)) { sublocation.path.id = property; writeEntry(Number.parseInt(property), undefined, sublocation); return true; diff --git a/packages/node/src/behaviors/general-diagnostics/GeneralDiagnosticsServer.ts b/packages/node/src/behaviors/general-diagnostics/GeneralDiagnosticsServer.ts index b99097357..44d0355fc 100644 --- a/packages/node/src/behaviors/general-diagnostics/GeneralDiagnosticsServer.ts +++ b/packages/node/src/behaviors/general-diagnostics/GeneralDiagnosticsServer.ts @@ -368,7 +368,7 @@ export class GeneralDiagnosticsServer extends Base { isOperational: isOperationalReachable(name), offPremiseServicesReachableIPv4: null, // null means unknown or not supported offPremiseServicesReachableIPv6: null, // null means unknown or not supported - hardwareAddress: Bytes.fromHex(mac.replace(/[^\da-fA-F]/g, "")), + hardwareAddress: Bytes.fromHex(mac.replace(/[^\da-f]/gi, "")), iPv4Addresses: ipV4.slice(0, 4).map(ip => ipv4ToBytes(ip)), iPv6Addresses: ipV6.slice(0, 8).map(ip => ipv4ToBytes(ip)), type: type ?? networkType, diff --git a/packages/node/src/endpoint/properties/Behaviors.ts b/packages/node/src/endpoint/properties/Behaviors.ts index 2b32a6990..0214a47c4 100644 --- a/packages/node/src/endpoint/properties/Behaviors.ts +++ b/packages/node/src/endpoint/properties/Behaviors.ts @@ -331,10 +331,8 @@ export class Behaviors { * Behaviors that fail initialization will be marked with crashed {@link status}. */ activate(type: Behavior.Type, agent: Agent) { - let backing = this.#backings[type.id]; - - if (!backing) { - backing = this.#createBacking(type, agent); + if (!this.#backings[type.id]) { + this.#createBacking(type, agent); } } diff --git a/packages/node/src/endpoint/storage/DatasourceStore.ts b/packages/node/src/endpoint/storage/DatasourceStore.ts index 943611c1d..851ee11d8 100644 --- a/packages/node/src/endpoint/storage/DatasourceStore.ts +++ b/packages/node/src/endpoint/storage/DatasourceStore.ts @@ -35,7 +35,12 @@ export function DatasourceStore( } const behaviorMutations = participant.mutations[behaviorId]; if (behaviorMutations) { - Object.assign(behaviorMutations, values); + for (const key in values) { + if (key === "__proto__") { + continue; + } + behaviorMutations[key] = values[key]; + } } else { participant.mutations[behaviorId] = { ...values }; } diff --git a/packages/nodejs/src/environment/ProcessManager.ts b/packages/nodejs/src/environment/ProcessManager.ts index da49ca9db..f70a4871b 100644 --- a/packages/nodejs/src/environment/ProcessManager.ts +++ b/packages/nodejs/src/environment/ProcessManager.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Destructable, Environment, Logger, RuntimeService, VariableService } from "#general"; +import { Destructable, Environment, Logger, RuntimeService, type VariableService } from "#general"; import type { NodeJsEnvironment } from "./NodeJsEnvironment.js"; const logger = Logger.get("ProcessManager"); diff --git a/packages/protocol/src/interaction/AttributeDataDecoder.ts b/packages/protocol/src/interaction/AttributeDataDecoder.ts index a4e695399..5266cc9c7 100644 --- a/packages/protocol/src/interaction/AttributeDataDecoder.ts +++ b/packages/protocol/src/interaction/AttributeDataDecoder.ts @@ -269,8 +269,14 @@ export function structureReadAttributeDataToClusterObject(data: DecodedAttribute structure[endpointId] = {}; } if (structure[endpointId][clusterId] === undefined) { + if ((clusterId as any) === "__proto__") { + continue; + } structure[endpointId][clusterId] = {}; } + if (attributeName === "__proto__") { + continue; + } structure[endpointId][clusterId][attributeName] = value; } return structure; diff --git a/packages/protocol/src/session/SessionManager.ts b/packages/protocol/src/session/SessionManager.ts index 348ab5469..f55034f01 100644 --- a/packages/protocol/src/session/SessionManager.ts +++ b/packages/protocol/src/session/SessionManager.ts @@ -116,7 +116,7 @@ export class SessionManager { readonly #globalUnencryptedMessageCounter = new MessageCounter(); readonly #subscriptionsChanged = Observable<[session: SecureSession, subscription: Subscription]>(); #sessionParameters; - readonly #resubmissionStarted = new Observable<[session: Session]>(); + readonly #resubmissionStarted = Observable<[session: Session]>(); readonly #construction: Construction; readonly #observers = new ObserverGroup(); readonly #subscriptionUpdateMutex = new Mutex(this); diff --git a/packages/testing/src/chip/chip-test-common.ts b/packages/testing/src/chip/chip-test-common.ts index 7f8c36ba0..7463e813c 100644 --- a/packages/testing/src/chip/chip-test-common.ts +++ b/packages/testing/src/chip/chip-test-common.ts @@ -12,7 +12,7 @@ import colors from "ansi-colors"; * Adds coloring to improve visibility and updates the runner's state. */ export function parseStep(line: string, step: (name: string) => void) { - const stepMatch = line.match(/^(.*\s\*{5})\s+(Test Step \d+)\s+:\s+(.*)$/); + const stepMatch = line.match(/^(.*\s\*{5})\s+(Test Step \d+)\s+:(?:\s+(\S.*)|\S.*)$/); if (stepMatch) { const [, prefix, stepNum, stepName] = stepMatch; step(stepName); diff --git a/packages/testing/src/device/test.ts b/packages/testing/src/device/test.ts index bb18c57ee..0adbecd42 100644 --- a/packages/testing/src/device/test.ts +++ b/packages/testing/src/device/test.ts @@ -84,7 +84,7 @@ export namespace Test { return name .toLowerCase() .split("_") - .map(segment => (segment.match(/^[0-9]+$/) ? segment.padStart(8, "0") : segment)) + .map(segment => (segment.match(/^\d+$/) ? segment.padStart(8, "0") : segment)) .join("_"); } } diff --git a/packages/testing/src/failure-detail.ts b/packages/testing/src/failure-detail.ts index 47669311c..4e43b9cbc 100644 --- a/packages/testing/src/failure-detail.ts +++ b/packages/testing/src/failure-detail.ts @@ -25,7 +25,7 @@ export function FailureDetail(error: any, logs?: string[]) { diff = "(no diff implementation installed)"; } else { diff = FailureDetail.diff(error.actual.toString(), error.expected.toString()); - diff = diff.trim().replace(/^ {6}/gms, ""); + diff = diff.trim().replace(/^ {6}/gm, ""); } } @@ -54,11 +54,11 @@ export namespace FailureDetail { process.stdout.write(colors.redBright(`${prefix}${failure.message}\n\n`)); if (failure.diff) { - process.stdout.write(`${prefix} ${failure.diff.replace(/\n/gm, "\n ")}\n\n`); + process.stdout.write(`${prefix} ${failure.diff.replace(/\n/g, "\n ")}\n\n`); } if (failure.stack) { - process.stdout.write(`${prefix}${colors.dim(failure.stack.replace(/\n/gm, `\n${prefix}`))}\n\n`); + process.stdout.write(`${prefix}${colors.dim(failure.stack.replace(/\n/g, `\n${prefix}`))}\n\n`); } if (failure.cause) { @@ -75,7 +75,7 @@ export namespace FailureDetail { } if (failure.logs) { - process.stdout.write(` ${failure.logs.replace(/\n/gm, "\n ")}\n\n`); + process.stdout.write(` ${failure.logs.replace(/\n/g, "\n ")}\n\n`); } } diff --git a/packages/testing/src/options.ts b/packages/testing/src/options.ts index afa447d63..49b782124 100644 --- a/packages/testing/src/options.ts +++ b/packages/testing/src/options.ts @@ -28,7 +28,7 @@ function option(options: TestOptions, name: T) { return process.env?.[ "MATTER_" + name - .match(/(.[^A-Z]+)/g) + .match(/.[^A-Z]+/g) ?.map(s => s.toUpperCase()) .join("_") ]; diff --git a/packages/testing/src/util/text.ts b/packages/testing/src/util/text.ts index 82c787095..6aa7031ac 100644 --- a/packages/testing/src/util/text.ts +++ b/packages/testing/src/util/text.ts @@ -35,7 +35,7 @@ export async function* asyncLinesOf>(input: T, fil } const text = textOf(chunk); - const lines = text.split(/\r?\n/g); + const lines = text.split(/\r?\n/); for (let i = 0; i < lines.length; i++) { let line = lines[i]; if (partial) { @@ -61,5 +61,5 @@ export async function* asyncLinesOf>(input: T, fil export function deansify(text: string) { // Credit to https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings // eslint-disable-next-line no-control-regex - return text.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ""); + return text.replace(/[\u001b\u009b][[()#;?]*(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ""); } diff --git a/packages/tools/src/building/tsconfig.ts b/packages/tools/src/building/tsconfig.ts index f190ed7c6..11169e545 100644 --- a/packages/tools/src/building/tsconfig.ts +++ b/packages/tools/src/building/tsconfig.ts @@ -50,12 +50,6 @@ async function syncSubproject(node: Graph.Node, path: string, ...extraRefs: stri const tsconfig = await node.pkg.readJson(tsconfigPath); - let refs = tsconfig.refs as undefined | { path: string }[]; - - if (refs === undefined) { - refs = []; - } - const deps = node.dependencies .filter(dep => dep.pkg.isLibrary) .map(dep => dep.pkg.resolve("src")) diff --git a/packages/tools/src/building/typescript.ts b/packages/tools/src/building/typescript.ts index 2a756c61b..f70052d9a 100644 --- a/packages/tools/src/building/typescript.ts +++ b/packages/tools/src/building/typescript.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { TypescriptContext } from "./typescript/context.js"; +import { type TypescriptContext } from "./typescript/context.js"; import { createSolutionBuilderContext } from "./typescript/solution-builder.js"; /** diff --git a/packages/tools/src/building/typescript/context.ts b/packages/tools/src/building/typescript/context.ts index c8453bde8..0c2391f60 100644 --- a/packages/tools/src/building/typescript/context.ts +++ b/packages/tools/src/building/typescript/context.ts @@ -41,7 +41,7 @@ export namespace TypescriptContext { // command line. Use the "light blue" ANSI escape code as an injection point for an additional newline // // eslint-disable-next-line no-control-regex - formatted = formatted.replace(/\u001b\[96m/gms, "\n\u001b[96m"); + formatted = formatted.replace(/\u001b\[96m/g, "\n\u001b[96m"); throw new BuildError(formatted); } diff --git a/packages/types/src/clusters/network-commissioning.ts b/packages/types/src/clusters/network-commissioning.ts index 0711c82b5..804e31b74 100644 --- a/packages/types/src/clusters/network-commissioning.ts +++ b/packages/types/src/clusters/network-commissioning.ts @@ -1325,7 +1325,7 @@ export namespace NetworkCommissioning { component: false } ) - }) + }); /** * @see {@link Cluster} diff --git a/packages/types/src/schema/PairingCodeSchema.ts b/packages/types/src/schema/PairingCodeSchema.ts index bd350644e..35e7eafbb 100644 --- a/packages/types/src/schema/PairingCodeSchema.ts +++ b/packages/types/src/schema/PairingCodeSchema.ts @@ -206,7 +206,7 @@ class ManualPairingCodeSchema extends Schema { } protected decodeInternal(encoded: string): ManualPairingData { - encoded = encoded.replace(/[^0-9]/g, ""); // we SHALL be robust against other characters + encoded = encoded.replace(/\D/g, ""); // we SHALL be robust against other characters if (encoded.length !== 11 && encoded.length != 21) { throw new UnexpectedDataError("Invalid pairing code"); } diff --git a/packages/types/test/schema/PairingCodeSchemaTest.ts b/packages/types/test/schema/PairingCodeSchemaTest.ts index f7f3ab50b..30cffe62e 100644 --- a/packages/types/test/schema/PairingCodeSchemaTest.ts +++ b/packages/types/test/schema/PairingCodeSchemaTest.ts @@ -171,7 +171,7 @@ describe("ManualPairingCodeCodec", () => { for (const pairingCode of MANUAL_PAIRING_DATA_CODES) { const result = ManualPairingCodeCodec.encode(pairingCode.data); - expect(result).equal(pairingCode.code.replace(/[^0-9]/g, "")); + expect(result).equal(pairingCode.code.replace(/\D/g, "")); } });