From 0a6a4204dbd6409b1a7f760a0c4b4122265f0fba Mon Sep 17 00:00:00 2001 From: Pierre Jochem Date: Thu, 4 Jun 2026 13:44:13 +0200 Subject: [PATCH 01/28] build(ts): bootstrap strict TypeScript toolchain (stage 0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set up the foundation for migrating MagicMirror to strict TypeScript while keeping the existing dual-runtime architecture intact (browser global scripts + Node CommonJS), with zero changes to hardcoded .js runtime paths. Approach: author .ts under src/, compile in place back into js/, defaultmodules/, serveronly/, clientonly/, translations/ (outputs gitignored). No bundler — browser files stay TS "script" files (no top-level import/export) so tsc emits global- defining JS 1:1. Two project configs split the DOM (browser) vs node (server) libs. - tsconfig.base.json + src/tsconfig.{browser,server}.json + editor tsconfig.json - src/types/globals.d.ts (ambient window globals; promoted from module-types.ts) and browser-shims.d.ts for the dual CommonJS export guard - build/build:watch/clean scripts; pre-build hooks on test*/server/start/config:check so the suite and runtime always execute fresh compiled output - eslint: typescript-eslint block for src/**/*.ts mirroring the JS @stylistic style; ignore compiled output; vitest esbuild target es2022 - *.ts formatted via eslint (tabs), added to .prettierignore; .ts in editorconfig tab group - migrate js/deprecated.js -> src/js/deprecated.ts to validate the src->output mapping Gate: full unit suite green (357 passing; the 1 failure is the pre-existing macOS-only systeminformation test that asserts a Linux platform). Co-Authored-By: Claude Opus 4.8 (1M context) --- .editorconfig | 2 +- .gitignore | 11 ++ .prettierignore | 2 + eslint.config.mjs | 113 +++++++++++++---- js/deprecated.js | 4 - jsconfig.json | 10 -- module-types.ts | 34 ------ package-lock.json | 228 +++++++++++++++++++++++++++++------ package.json | 19 ++- src/js/deprecated.ts | 11 ++ src/tsconfig.browser.json | 13 ++ src/tsconfig.server.json | 13 ++ src/types/browser-shims.d.ts | 15 +++ src/types/globals.d.ts | 87 +++++++++++++ tsconfig.base.json | 24 ++++ tsconfig.json | 10 ++ vitest.config.mjs | 8 ++ 17 files changed, 495 insertions(+), 109 deletions(-) delete mode 100644 js/deprecated.js delete mode 100644 jsconfig.json delete mode 100644 module-types.ts create mode 100644 src/js/deprecated.ts create mode 100644 src/tsconfig.browser.json create mode 100644 src/tsconfig.server.json create mode 100644 src/types/browser-shims.d.ts create mode 100644 src/types/globals.d.ts create mode 100644 tsconfig.base.json create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig index db01ad9e90..92ed8cbdf8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,6 @@ insert_final_newline = true max_line_length = 250 trim_trailing_whitespace = true -[*.{js,json}] +[*.{js,ts,json}] indent_size = 4 indent_style = tab diff --git a/.gitignore b/.gitignore index e1365c2fe6..b76674be1a 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,17 @@ config # Ignore positions file (#3518) js/positions.js +# TypeScript build output (compiled from src/*.ts by `npm run build`). +# Source of truth lives in src/; never edit or commit these compiled artifacts. +*.tsbuildinfo +/js/**/*.js.map +/defaultmodules/**/*.js.map +/serveronly/**/*.js.map +/clientonly/**/*.js.map +/translations/**/*.js.map +# Compiled outputs, listed per migrated file as each source moves to src/: +/js/deprecated.js + # Ignore lock files other than package-lock.json pnpm-lock.yaml yarn.lock diff --git a/.prettierignore b/.prettierignore index 0315d69371..fcaca59ea4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,7 +1,9 @@ *.js *.mjs +*.ts .husky/pre-commit .prettierignore +.claude /config /coverage package-lock.json diff --git a/eslint.config.mjs b/eslint.config.mjs index 05232e45df..4ff2193759 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -6,10 +6,53 @@ import jsdocPlugin from "eslint-plugin-jsdoc"; import {configs as packageJsonConfigs} from "eslint-plugin-package-json"; import playwright from "eslint-plugin-playwright"; import stylistic from "@stylistic/eslint-plugin"; +import tseslint from "typescript-eslint"; import vitest from "@vitest/eslint-plugin"; +/* + * Shared @stylistic overrides applied to both the JavaScript block and the + * TypeScript source block so TS matches the existing JS code style (tabs, double + * quotes, semicolons, ...). Keep in sync between the two blocks. + */ +const stylisticOverrides = { + "@stylistic/array-element-newline": ["error", "consistent"], + "@stylistic/arrow-parens": ["error", "always"], + "@stylistic/brace-style": "off", + "@stylistic/dot-location": ["error", "property"], + "@stylistic/function-call-argument-newline": ["error", "consistent"], + "@stylistic/function-paren-newline": ["error", "consistent"], + "@stylistic/implicit-arrow-linebreak": ["error", "beside"], + "@stylistic/indent": ["error", "tab"], + "@stylistic/max-statements-per-line": ["error", {max: 2}], + "@stylistic/multiline-comment-style": "off", + "@stylistic/multiline-ternary": ["error", "always-multiline"], + "@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 4}], + "@stylistic/no-extra-parens": "off", + "@stylistic/no-tabs": "off", + "@stylistic/object-curly-spacing": ["error", "always"], + "@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}], + "@stylistic/operator-linebreak": ["error", "before"], + "@stylistic/padded-blocks": "off", + "@stylistic/quote-props": ["error", "as-needed"], + "@stylistic/quotes": ["error", "double"], + "@stylistic/semi": ["error", "always"], + "@stylistic/space-before-function-paren": ["error", "always"], + "@stylistic/spaced-comment": "off" +}; + export default defineConfig([ - globalIgnores(["config/**", "modules/**/*", "js/positions.js", "tests/configs/config_variables.js"]), + globalIgnores([ + "config/**", + "modules/**/*", + "js/positions.js", + "tests/configs/config_variables.js", + + /* + * Compiled TypeScript output (generated from src/*.ts; never linted as source). + * Listed per migrated file as each source moves to src/: + */ + "js/deprecated.js" + ]), { files: ["**/*.js"], languageOptions: { @@ -26,29 +69,7 @@ export default defineConfig([ }, extends: [importX.recommended, js.configs.recommended, jsdocPlugin.configs["flat/recommended"], stylistic.configs.all], rules: { - "@stylistic/array-element-newline": ["error", "consistent"], - "@stylistic/arrow-parens": ["error", "always"], - "@stylistic/brace-style": "off", - "@stylistic/dot-location": ["error", "property"], - "@stylistic/function-call-argument-newline": ["error", "consistent"], - "@stylistic/function-paren-newline": ["error", "consistent"], - "@stylistic/implicit-arrow-linebreak": ["error", "beside"], - "@stylistic/indent": ["error", "tab"], - "@stylistic/max-statements-per-line": ["error", {max: 2}], - "@stylistic/multiline-comment-style": "off", - "@stylistic/multiline-ternary": ["error", "always-multiline"], - "@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 4}], - "@stylistic/no-extra-parens": "off", - "@stylistic/no-tabs": "off", - "@stylistic/object-curly-spacing": ["error", "always"], - "@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}], - "@stylistic/operator-linebreak": ["error", "before"], - "@stylistic/padded-blocks": "off", - "@stylistic/quote-props": ["error", "as-needed"], - "@stylistic/quotes": ["error", "double"], - "@stylistic/semi": ["error", "always"], - "@stylistic/space-before-function-paren": ["error", "always"], - "@stylistic/spaced-comment": "off", + ...stylisticOverrides, "dot-notation": "error", eqeqeq: ["error", "always", {null: "ignore"}], "id-length": "off", @@ -86,6 +107,50 @@ export default defineConfig([ ], rules: {"no-console": "error"} }, + { + files: ["src/**/*.ts"], + languageOptions: { + parser: tseslint.parser, + ecmaVersion: "latest", + sourceType: "module", + globals: { + ...globals.browser, + ...globals.node + } + }, + extends: [importX.recommended, ...tseslint.configs.recommended, stylistic.configs.all], + settings: { + "import-x/resolver": { + typescript: true, + node: true + } + }, + rules: { + ...stylisticOverrides, + "dot-notation": "error", + eqeqeq: ["error", "always", {null: "ignore"}], + "id-length": "off", + "import-x/extensions": "off", + "import-x/newline-after-import": "error", + "import-x/order": "error", + "no-param-reassign": "error", + "no-throw-literal": "error", + "no-unneeded-ternary": "error", + "no-useless-return": "error", + "object-shorthand": ["error", "methods"], + "prefer-template": "error", + "require-await": "error", + + /* + * TypeScript relaxations during migration. The compiler enforces the + * hard guarantees; these keep the existing CommonJS/global patterns lintable. + */ + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-require-imports": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-unused-vars": ["error", {argsIgnorePattern: "^_", varsIgnorePattern: "^_"}] + } + }, { files: ["**/package.json"], extends: [packageJsonConfigs.recommended] diff --git a/js/deprecated.js b/js/deprecated.js deleted file mode 100644 index 8c8ef3fc54..0000000000 --- a/js/deprecated.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - configs: [], - clock: ["secondsColor"] -}; diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 6ae848fc38..0000000000 --- a/jsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=759670 - // for the documentation about the jsconfig.json format - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "allowSyntheticDefaultImports": true - }, - "exclude": ["modules", "node_modules"] -} diff --git a/module-types.ts b/module-types.ts deleted file mode 100644 index 440b2c4959..0000000000 --- a/module-types.ts +++ /dev/null @@ -1,34 +0,0 @@ -type ModuleProperties = { - defaults?: object; - [key: string]: any; - start?(): void; - getScripts?(): string[]; - getStyles?(): string[]; - getTranslations?(): object; - getDom?(): HTMLElement; - getHeader?(): string; - getTemplate?(): string; - getTemplateData?(): object; - notificationReceived?(notification: string, payload: any, sender: object): void; - nunjucksEnvironment?(): void; - socketNotificationReceived?(notification: string, payload: any): void; - suspend?(): void; - resume?(): void; -}; - -export declare const Module: { - register(moduleName: string, moduleProperties: ModuleProperties): void; -}; - -export declare const Log: { - info(message?: any, ...optionalParams: any[]): void; - log(message?: any, ...optionalParams: any[]): void; - error(message?: any, ...optionalParams: any[]): void; - warn(message?: any, ...optionalParams: any[]): void; - group(groupTitle?: string, ...optionalParams: any[]): void; - groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void; - groupEnd(): void; - time(timerName?: string): void; - timeEnd(timerName?: string): void; - timeStamp(timerName?: string): void; -}; diff --git a/package-lock.json b/package-lock.json index 5e384ba317..09cff1ba1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "@vitest/eslint-plugin": "^1.6.16", "@vitest/ui": "^4.1.5", "cspell": "^10.0.0", + "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-import-x": "^4.16.2", "eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-package-json": "^0.91.2", @@ -58,6 +59,8 @@ "stylelint": "^17.9.1", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", + "typescript": "^6.0.3", + "typescript-eslint": "^8.60.1", "vitest": "^4.1.5" }, "engines": { @@ -2569,15 +2572,79 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz", + "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.60.1", + "@typescript-eslint/type-utils": "8.60.1", + "@typescript-eslint/utils": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.60.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz", + "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.60.1", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/project-service": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", - "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz", + "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.1", - "@typescript-eslint/types": "^8.59.1", + "@typescript-eslint/tsconfig-utils": "^8.60.1", + "@typescript-eslint/types": "^8.60.1", "debug": "^4.4.3" }, "engines": { @@ -2592,14 +2659,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", - "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz", + "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1" + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2610,9 +2677,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", - "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz", + "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==", "dev": true, "license": "MIT", "engines": { @@ -2626,10 +2693,35 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz", + "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1", + "@typescript-eslint/utils": "8.60.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/@typescript-eslint/types": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", - "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz", + "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==", "dev": true, "license": "MIT", "engines": { @@ -2641,16 +2733,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", - "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz", + "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.1", - "@typescript-eslint/tsconfig-utils": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/visitor-keys": "8.59.1", + "@typescript-eslint/project-service": "8.60.1", + "@typescript-eslint/tsconfig-utils": "8.60.1", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/visitor-keys": "8.60.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2669,16 +2761,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", - "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz", + "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.1", - "@typescript-eslint/types": "8.59.1", - "@typescript-eslint/typescript-estree": "8.59.1" + "@typescript-eslint/scope-manager": "8.60.1", + "@typescript-eslint/types": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2693,13 +2785,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", - "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz", + "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/types": "8.60.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -5204,6 +5296,41 @@ } } }, + "node_modules/eslint-import-resolver-typescript": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.5.tgz", + "integrity": "sha512-nbE5XLph6TLtGYcu/U6e6ZVXyKBhbDWK5cLGk76eJ7NdZpwf1P9EFkpt1Z01mNZNrrilsAYWKH6zUkL4reoXbw==", + "dev": true, + "license": "ISC", + "dependencies": { + "debug": "^4.4.1", + "eslint-import-context": "^0.1.8", + "get-tsconfig": "^4.10.1", + "is-bun-module": "^2.0.0", + "stable-hash-x": "^0.2.0", + "tinyglobby": "^0.2.14", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^16.17.0 || >=18.6.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, "node_modules/eslint-plugin-import-x": { "version": "4.16.2", "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.16.2.tgz", @@ -6723,6 +6850,16 @@ "node": ">=8" } }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -11350,7 +11487,6 @@ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11359,6 +11495,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.60.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz", + "integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.60.1", + "@typescript-eslint/parser": "8.60.1", + "@typescript-eslint/typescript-estree": "8.60.1", + "@typescript-eslint/utils": "8.60.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", diff --git a/package.json b/package.json index b2c0eca59b..78d5c2cd4c 100644 --- a/package.json +++ b/package.json @@ -48,17 +48,23 @@ ], "sideEffects": true, "scripts": { + "build": "tsc -p src/tsconfig.browser.json && tsc -p src/tsconfig.server.json", + "build:watch": "tsc -w -p src/tsconfig.browser.json & tsc -w -p src/tsconfig.server.json", + "clean:build": "tsc -b --clean src/tsconfig.browser.json src/tsconfig.server.json || rm -rf node_modules/.cache/tsc", + "preconfig:check": "node --run build", "config:check": "node js/check_config.js", "postinstall": "git clean -df fonts vendor modules/default", "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", - "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier && npx playwright install chromium", + "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier && npx playwright install chromium && node --run build", "lint:css": "stylelint 'css/**/*.css' 'defaultmodules/**/*.css' --fix", "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", + "preserver": "node --run build", "server": "node ./serveronly", "server:watch": "node ./serveronly/watcher.js", + "prestart": "node --run build", "start": "node --run start:wayland", "start:dev": "node --run start:wayland -- dev", "start:wayland": "WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY:=wayland-1}\" ./node_modules/.bin/electron js/electron.js --ozone-platform=wayland", @@ -67,19 +73,25 @@ "start:windows:dev": "node --run start:windows -- dev", "start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", "start:x11:dev": "node --run start:x11 -- dev", + "pretest": "node --run build", "test": "vitest run", "test:calendar": "node ./defaultmodules/calendar/debug.js", + "pretest:coverage": "node --run build", "test:coverage": "vitest run --coverage", "test:css": "stylelint 'css/**/*.css' 'defaultmodules/**/*.css'", + "pretest:e2e": "node --run build", "test:e2e": "vitest run tests/e2e", + "pretest:electron": "node --run build", "test:electron": "vitest run tests/electron", "test:js": "eslint", "test:markdown": "markdownlint-cli2 .", "test:prettier": "prettier . --check", "test:spelling": "cspell . --gitignore", "test:ui": "vitest --ui", + "pretest:unit": "node --run build", "test:unit": "vitest run tests/unit", - "test:watch": "vitest" + "test:watch": "vitest", + "typecheck": "tsc -p tsconfig.json" }, "lint-staged": { "*": "prettier --ignore-unknown --write", @@ -119,6 +131,7 @@ "@vitest/eslint-plugin": "^1.6.16", "@vitest/ui": "^4.1.5", "cspell": "^10.0.0", + "eslint-import-resolver-typescript": "^4.4.5", "eslint-plugin-import-x": "^4.16.2", "eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-package-json": "^0.91.2", @@ -135,6 +148,8 @@ "stylelint": "^17.9.1", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", + "typescript": "^6.0.3", + "typescript-eslint": "^8.60.1", "vitest": "^4.1.5" }, "optionalDependencies": { diff --git a/src/js/deprecated.ts b/src/js/deprecated.ts new file mode 100644 index 0000000000..fb82f77c93 --- /dev/null +++ b/src/js/deprecated.ts @@ -0,0 +1,11 @@ +type DeprecatedConfig = { + configs: string[]; + [moduleName: string]: string[]; +}; + +const deprecated: DeprecatedConfig = { + configs: [], + clock: ["secondsColor"] +}; + +export = deprecated; diff --git a/src/tsconfig.browser.json b/src/tsconfig.browser.json new file mode 100644 index 0000000000..e61bb8910a --- /dev/null +++ b/src/tsconfig.browser.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "..", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": [], + "incremental": true, + "tsBuildInfoFile": "../node_modules/.cache/tsc/browser.tsbuildinfo" + }, + "//": "Browser files loaded via