From 18353bd33046504b6758876e2bda7e8bbec81f36 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 22 Dec 2025 15:53:15 +0200 Subject: [PATCH 01/30] chore(devextreme): create the localization gulp task alternative based on nx --- packages/nx-infra-plugin/package.json | 6 +- pnpm-lock.yaml | 663 +++++++++++++------------- 2 files changed, 344 insertions(+), 325 deletions(-) diff --git a/packages/nx-infra-plugin/package.json b/packages/nx-infra-plugin/package.json index 7f658ce0f993..ec5c04c11b06 100644 --- a/packages/nx-infra-plugin/package.json +++ b/packages/nx-infra-plugin/package.json @@ -12,10 +12,10 @@ "./package.json": "./package.json" }, "dependencies": { - "fs-extra": "^11.2.0", + "fs-extra": "11.2.0", "glob": "11.1.0", "normalize-path": "3.0.0", - "lodash": "^4.17.21", + "lodash": "4.17.21", "rimraf": "3.0.2" }, "peerDependencies": { @@ -35,7 +35,7 @@ "@types/jest": "29.5.14", "@types/normalize-path": "3.0.2", "@types/node": "18.19.130", - "@types/lodash": "^4.17.0", + "@types/lodash": "4.17.0", "prettier": "catalog:tools", "ts-jest": "29.1.3", "typescript": "4.9.5" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc67b58044c3..733a77249ca7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2238,7 +2238,7 @@ importers: packages/nx-infra-plugin: dependencies: fs-extra: - specifier: ^11.2.0 + specifier: 11.2.0 version: 11.2.0 glob: specifier: 11.1.0 @@ -2247,8 +2247,8 @@ importers: specifier: '>=6.0.0' version: 6.4.4 lodash: - specifier: ^4.17.21 - version: 4.17.23 + specifier: 4.17.21 + version: 4.17.21 ng-packagr: specifier: '>=19.0.0' version: 19.2.2(@angular/compiler-cli@21.0.8(@angular/compiler@21.0.8)(typescript@4.9.5))(tslib@2.8.1)(typescript@4.9.5) @@ -2266,8 +2266,8 @@ importers: specifier: 29.5.14 version: 29.5.14 '@types/lodash': - specifier: ^4.17.0 - version: 4.17.13 + specifier: 4.17.0 + version: 4.17.0 '@types/node': specifier: 18.19.130 version: 18.19.130 @@ -2839,10 +2839,6 @@ packages: resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.28.5': - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.28.6': resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} engines: {node: '>=6.9.0'} @@ -6945,8 +6941,8 @@ packages: '@types/jsonfile@6.1.4': resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - '@types/lodash@4.17.13': - resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==} + '@types/lodash@4.17.0': + resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==} '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -13581,6 +13577,9 @@ packages: lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.17.23: resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} @@ -19917,15 +19916,15 @@ snapshots: '@babel/core@7.26.10': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.26.10) - '@babel/helpers': 7.28.4 + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.26.10) + '@babel/helpers': 7.28.6 '@babel/parser': 7.28.6 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 @@ -19937,15 +19936,15 @@ snapshots: '@babel/core@7.26.9': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.26.9) - '@babel/helpers': 7.28.4 + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.26.9) + '@babel/helpers': 7.28.6 '@babel/parser': 7.28.6 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 @@ -19957,7 +19956,7 @@ snapshots: '@babel/core@7.28.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/generator': 7.28.6 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helpers': 7.28.4 @@ -20005,7 +20004,7 @@ snapshots: '@babel/generator@7.26.10': dependencies: '@babel/parser': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -20018,14 +20017,6 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/generator@7.28.5': - dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.5 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - '@babel/generator@7.28.6': dependencies: '@babel/parser': 7.28.6 @@ -20036,7 +20027,7 @@ snapshots: '@babel/helper-annotate-as-pure@7.25.9': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/helper-annotate-as-pure@7.27.3': dependencies: @@ -20044,9 +20035,9 @@ snapshots: '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.28.5 + '@babel/compat-data': 7.28.6 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.0 + browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 @@ -20071,41 +20062,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.26.10)': + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.10) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/traverse': 7.28.5 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.4)': + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.6 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/traverse': 7.28.5 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.6)': + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-member-expression-to-functions': 7.28.5 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6) + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.26.10) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -20144,6 +20135,13 @@ snapshots: regexpu-core: 6.2.0 semver: 6.3.1 + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20154,8 +20152,8 @@ snapshots: '@babel/helper-define-polyfill-provider@0.4.4(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.11 @@ -20165,8 +20163,8 @@ snapshots: '@babel/helper-define-polyfill-provider@0.5.0(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.11 @@ -20210,15 +20208,15 @@ snapshots: '@babel/helper-member-expression-to-functions@7.25.9': dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color '@babel/helper-member-expression-to-functions@7.28.5': dependencies: '@babel/traverse': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color @@ -20252,15 +20250,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.26.9)': - dependencies: - '@babel/core': 7.26.9 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 @@ -20288,6 +20277,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 @@ -20308,11 +20306,11 @@ snapshots: '@babel/helper-optimise-call-expression@7.25.9': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/helper-plugin-utils@7.27.1': {} @@ -20372,6 +20370,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-replace-supers@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/helper-replace-supers@7.28.6(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20390,7 +20397,7 @@ snapshots: '@babel/helper-split-export-declaration@7.24.7': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/helper-string-parser@7.27.1': {} @@ -20400,16 +20407,16 @@ snapshots: '@babel/helper-wrap-function@7.28.3': dependencies: - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color '@babel/helpers@7.28.4': dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 '@babel/helpers@7.28.6': dependencies: @@ -20520,19 +20527,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.26.10)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.5 + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.4)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.5 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20600,15 +20607,15 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.28.6)': dependencies: @@ -20618,12 +20625,7 @@ snapshots: '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.4)': dependencies: @@ -20635,6 +20637,11 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20741,36 +20748,45 @@ snapshots: '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.10) - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.26.10)': + '@babel/plugin-transform-async-generator-functions@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.10) - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.4)': + '@babel/plugin-transform-async-generator-functions@7.28.6(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20786,8 +20802,8 @@ snapshots: '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.10) transitivePeerDependencies: - supports-color @@ -20795,26 +20811,35 @@ snapshots: '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.4 '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.26.10) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) transitivePeerDependencies: - supports-color @@ -20843,15 +20868,15 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-block-scoping@7.28.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-block-scoping@7.28.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.28.6)': dependencies: @@ -20866,19 +20891,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -20898,19 +20923,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.26.10)': + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.4)': + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -20922,27 +20947,27 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.4(@babel/core@7.26.10)': + '@babel/plugin-transform-classes@7.28.4(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.26.10) - '@babel/traverse': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.4(@babel/core@7.28.4)': + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) - '@babel/traverse': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.26.10) + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20958,17 +20983,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/template': 7.27.2 - '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/template': 7.27.2 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 + + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21000,17 +21025,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21033,17 +21058,17 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21069,7 +21094,7 @@ snapshots: '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.4) transitivePeerDependencies: - supports-color @@ -21087,15 +21112,15 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-exponentiation-operator@7.28.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-exponentiation-operator@7.28.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21174,15 +21199,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21204,15 +21229,15 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-logical-assignment-operators@7.28.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-logical-assignment-operators@7.28.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21377,30 +21402,30 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21414,25 +21439,25 @@ snapshots: '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/plugin-transform-object-rest-spread@7.28.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.26.10) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.10) - '@babel/traverse': 7.28.5 - transitivePeerDependencies: - - supports-color - '@babel/plugin-transform-object-rest-spread@7.28.4(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.4) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.4) - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.26.10) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.10) + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21471,33 +21496,25 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.26.10)': + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - transitivePeerDependencies: - - supports-color + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -21549,19 +21566,19 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.4 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.26.10 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -21573,21 +21590,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.4 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.26.10 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -21654,32 +21671,32 @@ snapshots: '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.28.6)': + '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21717,8 +21734,8 @@ snapshots: '@babel/plugin-transform-runtime@7.26.10(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.26.10) babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.26.10) @@ -21765,18 +21782,18 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-spread@7.27.1(@babel/core@7.26.10)': + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.4)': dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.4)': + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -21860,17 +21877,17 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21896,17 +21913,17 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.6) '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.26.10) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.26.10) + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21916,41 +21933,41 @@ snapshots: '@babel/preset-env@7.26.9(@babel/core@7.26.10)': dependencies: - '@babel/compat-data': 7.28.5 + '@babel/compat-data': 7.28.6 '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.26.10) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.26.10) '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.26.10) '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.26.10) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.26.10) '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.10) - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.26.10) '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.10) '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.26.10) - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-async-generator-functions': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-block-scoping': 7.28.5(@babel/core@7.26.10) - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.26.10) - '@babel/plugin-transform-classes': 7.28.4(@babel/core@7.26.10) - '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.26.10) - '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-exponentiation-operator': 7.28.5(@babel/core@7.26.10) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-logical-assignment-operators': 7.28.5(@babel/core@7.26.10) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.26.10) @@ -21958,28 +21975,28 @@ snapshots: '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-object-rest-spread': 7.28.4(@babel/core@7.26.10) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.26.10) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.10) - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-regenerator': 7.28.4(@babel/core@7.26.10) - '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-regenerator': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.26.10) '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.26.10) '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.26.10) - '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.26.10) '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.10) babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.26.10) babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) @@ -22006,8 +22023,8 @@ snapshots: '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.4) '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.4) '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.4) - '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.4) - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-async-generator-functions': 7.28.6(@babel/core@7.28.4) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.4) '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.4) '@babel/plugin-transform-block-scoping': 7.28.5(@babel/core@7.28.4) '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.4) @@ -22200,9 +22217,9 @@ snapshots: '@babel/template@7.27.2': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.28.6 '@babel/parser': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/template@7.28.6': dependencies: @@ -22213,7 +22230,7 @@ snapshots: '@babel/traverse@7.28.5': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/generator': 7.28.6 '@babel/helper-globals': 7.28.0 '@babel/parser': 7.28.6 '@babel/template': 7.27.2 @@ -22313,7 +22330,7 @@ snapshots: '@devexpress/callsite-record@4.1.7': dependencies: - '@types/lodash': 4.17.13 + '@types/lodash': 4.17.0 callsite: 1.0.0 chalk: 2.4.2 error-stack-parser: 2.1.4 @@ -25780,7 +25797,7 @@ snapshots: '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/body-parser@1.19.5': dependencies: @@ -25960,7 +25977,7 @@ snapshots: dependencies: '@types/node': 20.12.8 - '@types/lodash@4.17.13': {} + '@types/lodash@4.17.0': {} '@types/mdast@3.0.15': dependencies: @@ -32152,7 +32169,7 @@ snapshots: fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.3)(esbuild@0.26.0)): dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.28.6 chalk: 4.1.2 chokidar: 4.0.1 cosmiconfig: 8.3.6(typescript@5.9.3) @@ -34647,7 +34664,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.14.5 + '@types/node': 20.12.8 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -34794,7 +34811,7 @@ snapshots: jest-snapshot@29.7.0: dependencies: '@babel/core': 7.28.6 - '@babel/generator': 7.28.5 + '@babel/generator': 7.28.6 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6) '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.6) '@babel/types': 7.28.5 @@ -35608,6 +35625,8 @@ snapshots: lodash.uniq@4.5.0: {} + lodash@4.17.21: {} + lodash@4.17.23: {} log-symbols@4.1.0: @@ -37960,8 +37979,8 @@ snapshots: react-docgen@7.1.1: dependencies: '@babel/core': 7.28.6 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 '@types/doctrine': 0.0.9 From 2fed628758f6ba3b17a4e2bb42c3c04e63463970 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Wed, 14 Jan 2026 17:06:10 +0200 Subject: [PATCH 02/30] chore: cleanup migrated localization gulp tasks --- .../devextreme/build/gulp/localization.js | 181 +----------------- 1 file changed, 2 insertions(+), 179 deletions(-) diff --git a/packages/devextreme/build/gulp/localization.js b/packages/devextreme/build/gulp/localization.js index 217bfa0f8458..ecf67b940fc5 100644 --- a/packages/devextreme/build/gulp/localization.js +++ b/packages/devextreme/build/gulp/localization.js @@ -2,116 +2,14 @@ const gulp = require('gulp'); const path = require('path'); -const rename = require('gulp-rename'); -const del = require('del'); -const template = require('gulp-template'); -const lint = require('gulp-eslint-new'); +const shell = require('gulp-shell'); const through = require('through2'); const fs = require('fs'); -const headerPipes = require('./header-pipes.js'); -const compressionPipes = require('./compression-pipes.js'); -const context = require('./context.js'); - -const Cldr = require('cldrjs'); -const locales = require('cldr-core/availableLocales.json').availableLocales.full; -const weekData = require('cldr-core/supplemental/weekData.json'); -const likelySubtags = require('cldr-core/supplemental/likelySubtags.json'); -const parentLocales = require('cldr-core/supplemental/parentLocales.json').supplemental.parentLocales.parentLocale; - -const globalizeEnCldr = require('devextreme-cldr-data/en.json'); -const globalizeSupplementalCldr = require('devextreme-cldr-data/supplemental.json'); - -const PARENT_LOCALE_SEPARATOR = '-'; const DEFAULT_LOCALE = 'en'; - -const getParentLocale = (parentLocales, locale) => { - const parentLocale = parentLocales[locale]; - - if(parentLocale) { - return parentLocale !== 'root' && parentLocale; - } - - return locale.substr(0, locale.lastIndexOf(PARENT_LOCALE_SEPARATOR)); -}; - -const firstDayOfWeekData = function() { - const DAY_INDEXES = { - 'sun': 0, - 'mon': 1, - 'tue': 2, - 'wed': 3, - 'thu': 4, - 'fri': 5, - 'sat': 6 - }; - const DEFAULT_DAY_OF_WEEK_INDEX = 0; - - const result = {}; - - Cldr.load(weekData, likelySubtags); - - const getFirstIndex = (locale) => { - const firstDay = new Cldr(locale).supplemental.weekData.firstDay(); - return DAY_INDEXES[firstDay]; - }; - - locales.forEach(function(locale) { - const firstDayIndex = getFirstIndex(locale); - - const parentLocale = getParentLocale(parentLocales, locale); - if(firstDayIndex !== DEFAULT_DAY_OF_WEEK_INDEX && (!parentLocale || firstDayIndex !== getFirstIndex(parentLocale))) { - result[locale] = firstDayIndex; - } - }); - - return result; -}; - -const accountingFormats = function() { - const result = {}; - - locales.forEach(function(locale) { - const dataFilePath = `../../node_modules/cldr-numbers-full/main/${locale}/numbers.json`; - - if(fs.existsSync(path.join(__dirname, dataFilePath))) { - const numbersData = require(dataFilePath); - result[locale] = numbersData.main[locale].numbers['currencyFormats-numberSystem-latn'].accounting; - } - }); - - return result; -}; - -const RESULT_PATH = path.join(context.RESULT_JS_PATH, 'localization'); const DICTIONARY_SOURCE_FOLDER = 'js/localization/messages'; -const getLocales = function(directory) { - return fs.readdirSync(directory).map(file => { - return file.split('.')[0]; - }); -}; - -const serializeObject = function(obj, shift) { - const tab = ' '; - let result = JSON.stringify(obj, null, tab); - - if(shift) { - result = result.replace(/(\n)/g, '$1' + tab); - } - - return result; -}; - -const getMessages = function(directory, locale) { - const json = require(path.join('../../', directory, locale + '.json')); - - return serializeObject(json, true); -}; - -gulp.task('clean-cldr-data', function() { - return del('js/__internal/core/localization/cldr-data/**', { force: true }); -}); +gulp.task('localization', shell.task('pnpm nx build:localization devextreme')); gulp.task('generate-community-locales', () => { const defaultFile = fs.readFileSync(path.join(DICTIONARY_SOURCE_FOLDER, DEFAULT_LOCALE + '.json')).toString(); @@ -150,78 +48,3 @@ gulp.task('generate-community-locales', () => { })) .pipe(gulp.dest(DICTIONARY_SOURCE_FOLDER)); }); - -gulp.task('localization-messages', gulp.parallel(getLocales(DICTIONARY_SOURCE_FOLDER).map(locale => Object.assign( - function() { - return gulp - .src('build/gulp/localization-template.jst') - .pipe(template({ - json: getMessages(DICTIONARY_SOURCE_FOLDER, locale) - })) - .pipe(rename(['dx', 'messages', locale, 'js'].join('.'))) - .pipe(compressionPipes.beautify()) - .pipe(headerPipes.useStrict()) - .pipe(headerPipes.bangLicense()) - .pipe(gulp.dest(RESULT_PATH)); - }, - { displayName: 'dx.messages.' + locale } -)))); - -gulp.task('localization-generated-sources', gulp.parallel([ - { - data: require('../../js/localization/messages/en.json'), - filename: 'default_messages.ts', - exportName: 'defaultMessages', - destination: 'js/__internal/core/localization' - }, - { - data: parentLocales, - filename: 'parent_locales.ts', - destination: 'js/__internal/core/localization/cldr-data' - }, - { - data: firstDayOfWeekData(), - filename: 'first_day_of_week_data.ts', - destination: 'js/__internal/core/localization/cldr-data' - }, - { - data: accountingFormats(), - filename: 'accounting_formats.ts', - destination: 'js/__internal/core/localization/cldr-data' - - }, - { - data: globalizeEnCldr, - exportName: 'enCldr', - filename: 'en.ts', - destination: 'js/__internal/core/localization/cldr-data' - }, - { - data: globalizeSupplementalCldr, - exportName: 'supplementalCldr', - filename: 'supplemental.ts', - destination: 'js/__internal/core/localization/cldr-data' - } -].map((source) => Object.assign( - function() { - return gulp - .src('build/gulp/generated_js.jst') - .pipe(template({ - exportName: source.exportName, - json: serializeObject(source.data) - })) - .pipe(lint({ fix: true })) - .pipe(lint.format()) - .pipe(rename(source.filename)) - .pipe(gulp.dest(source.destination)); - }, - { displayName: source.filename } -)))); - -gulp.task('localization', - gulp.series( - 'clean-cldr-data', - 'localization-messages', - 'localization-generated-sources' - ) -); From b4c6739a4efe11291e6ee9d2872693e099c3310e Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Wed, 14 Jan 2026 17:08:18 +0200 Subject: [PATCH 03/30] feat(nx-infra-plugin): copy-files, support glob patterns --- packages/nx-infra-plugin/package.json | 2 +- .../executors/copy-files/executor.e2e.spec.ts | 25 ++++++ .../src/executors/copy-files/executor.ts | 84 ++++++++++++++----- .../src/executors/copy-files/schema.json | 10 ++- pnpm-lock.yaml | 12 +-- 5 files changed, 104 insertions(+), 29 deletions(-) diff --git a/packages/nx-infra-plugin/package.json b/packages/nx-infra-plugin/package.json index ec5c04c11b06..6a998082b561 100644 --- a/packages/nx-infra-plugin/package.json +++ b/packages/nx-infra-plugin/package.json @@ -35,7 +35,7 @@ "@types/jest": "29.5.14", "@types/normalize-path": "3.0.2", "@types/node": "18.19.130", - "@types/lodash": "4.17.0", + "@types/lodash": "4.17.13", "prettier": "catalog:tools", "ts-jest": "29.1.3", "typescript": "4.9.5" diff --git a/packages/nx-infra-plugin/src/executors/copy-files/executor.e2e.spec.ts b/packages/nx-infra-plugin/src/executors/copy-files/executor.e2e.spec.ts index 72a266c51719..ac36e37a8999 100644 --- a/packages/nx-infra-plugin/src/executors/copy-files/executor.e2e.spec.ts +++ b/packages/nx-infra-plugin/src/executors/copy-files/executor.e2e.spec.ts @@ -105,4 +105,29 @@ describe('CopyFilesExecutor E2E', () => { expect(content).not.toBe('Old content'); }); }); + + describe('Glob patterns', () => { + it('should copy files using glob pattern', async () => { + const projectDir = path.join(tempDir, 'packages', 'test-lib'); + const srcDir = path.join(projectDir, 'src'); + fs.mkdirSync(srcDir, { recursive: true }); + + await writeFileText(path.join(srcDir, 'file1.ts'), 'export const a = 1;'); + await writeFileText(path.join(srcDir, 'file2.ts'), 'export const b = 2;'); + await writeFileText(path.join(srcDir, 'other.js'), 'module.exports = {};'); + + const options: CopyFilesExecutorSchema = { + files: [{ from: './src/*.ts', to: './dist' }], + }; + + const result = await executor(options, context); + + expect(result.success).toBe(true); + + const distDir = path.join(projectDir, 'dist'); + expect(fs.existsSync(path.join(distDir, 'file1.ts'))).toBe(true); + expect(fs.existsSync(path.join(distDir, 'file2.ts'))).toBe(true); + expect(fs.existsSync(path.join(distDir, 'other.js'))).toBe(false); + }); + }); }); diff --git a/packages/nx-infra-plugin/src/executors/copy-files/executor.ts b/packages/nx-infra-plugin/src/executors/copy-files/executor.ts index fedaad6ed28c..977bb0700066 100644 --- a/packages/nx-infra-plugin/src/executors/copy-files/executor.ts +++ b/packages/nx-infra-plugin/src/executors/copy-files/executor.ts @@ -1,19 +1,72 @@ import { PromiseExecutor, logger } from '@nx/devkit'; import * as path from 'path'; -import * as fs from 'fs/promises'; +import { stat } from 'fs/promises'; +import { glob } from 'glob'; import { CopyFilesExecutorSchema } from './schema'; -import { resolveProjectPath } from '../../utils/path-resolver'; +import { resolveProjectPath, normalizeGlobPathForWindows } from '../../utils/path-resolver'; +import { isWindowsOS } from '../../utils/common'; import { logError } from '../../utils/error-handler'; -import { copyFile, copyRecursive, exists } from '../../utils/file-operations'; +import { copyFile, copyRecursive, exists, ensureDir } from '../../utils/file-operations'; -const ERROR_FILES_MUST_BE_ARRAY = 'Files option must be an array'; -const ERROR_FAILED_TO_COPY = 'Failed to copy files'; +const ERROR_MESSAGES = { + FILES_MUST_BE_ARRAY: 'Files option must be an array', + FAILED_TO_COPY: 'Failed to copy files', + NO_FILES_MATCH_PATTERN: (pattern: string) => `No files found matching pattern: ${pattern}`, + SOURCE_NOT_FOUND: (source: string) => `Source file not found: ${source}`, +} as const; + +function containsGlobPattern(pattern: string): boolean { + return /[*?[\]{}]/.test(pattern); +} + +async function copyGlobPatternFiles( + sourcePath: string, + destPath: string, +): Promise<{ success: boolean }> { + const globPattern = isWindowsOS() ? normalizeGlobPathForWindows(sourcePath) : sourcePath; + const files = await glob(globPattern, { nodir: true }); + + if (files.length === 0) { + logger.error(ERROR_MESSAGES.NO_FILES_MATCH_PATTERN(sourcePath)); + return { success: false }; + } + + await ensureDir(destPath); + + for (const file of files) { + const fileName = path.basename(file); + const destFile = path.join(destPath, fileName); + await copyFile(file, destFile); + logger.info(`Copied file ${file} -> ${destFile}`); + } + + return { success: true }; +} + +async function copyDirectPath(sourcePath: string, destPath: string): Promise<{ success: boolean }> { + if (!(await exists(sourcePath))) { + logger.error(ERROR_MESSAGES.SOURCE_NOT_FOUND(sourcePath)); + return { success: false }; + } + + const sourceStat = await stat(sourcePath); + + if (sourceStat.isDirectory()) { + await copyRecursive(sourcePath, destPath); + logger.info(`Copied directory ${sourcePath} -> ${destPath}`); + return { success: true }; + } + + await copyFile(sourcePath, destPath); + logger.info(`Copied file ${sourcePath} -> ${destPath}`); + return { success: true }; +} const runExecutor: PromiseExecutor = async (options, context) => { const projectRoot = resolveProjectPath(context); if (!options.files || !Array.isArray(options.files)) { - logger.error(ERROR_FILES_MUST_BE_ARRAY); + logger.error(ERROR_MESSAGES.FILES_MUST_BE_ARRAY); return { success: false }; } @@ -22,25 +75,18 @@ const runExecutor: PromiseExecutor = async (options, co const sourcePath = path.resolve(projectRoot, from); const destPath = path.resolve(projectRoot, to); - if (!(await exists(sourcePath))) { - logger.error(`Source file not found: ${sourcePath}`); - return { success: false }; - } + const result = containsGlobPattern(from) + ? await copyGlobPatternFiles(sourcePath, destPath) + : await copyDirectPath(sourcePath, destPath); - const stat = await fs.stat(sourcePath); - - if (stat.isDirectory()) { - await copyRecursive(sourcePath, destPath); - logger.info(`Copied directory ${sourcePath} -> ${destPath}`); - } else { - await copyFile(sourcePath, destPath); - logger.info(`Copied file ${sourcePath} -> ${destPath}`); + if (!result.success) { + return { success: false }; } } return { success: true }; } catch (error) { - logError(ERROR_FAILED_TO_COPY, error); + logError(ERROR_MESSAGES.FAILED_TO_COPY, error); return { success: false }; } }; diff --git a/packages/nx-infra-plugin/src/executors/copy-files/schema.json b/packages/nx-infra-plugin/src/executors/copy-files/schema.json index 7c777b705386..10e9cc609c07 100644 --- a/packages/nx-infra-plugin/src/executors/copy-files/schema.json +++ b/packages/nx-infra-plugin/src/executors/copy-files/schema.json @@ -1,17 +1,21 @@ { + "$schema": "https://json-schema.org/schema", "type": "object", + "description": "Copy files or directories to a destination. Supports glob patterns and recursive directory copying.", "properties": { "files": { "type": "array", - "description": "Files to copy (array of {from, to})", + "description": "Array of file copy operations to perform.", "items": { "type": "object", "properties": { "from": { - "type": "string" + "type": "string", + "description": "Source path relative to project root. Supports glob patterns (e.g., './src/*.ts', './assets/**/*')." }, "to": { - "type": "string" + "type": "string", + "description": "Destination path relative to project root. For glob patterns, this should be a directory." } }, "required": ["from", "to"] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 733a77249ca7..eb732afa3591 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2266,8 +2266,8 @@ importers: specifier: 29.5.14 version: 29.5.14 '@types/lodash': - specifier: 4.17.0 - version: 4.17.0 + specifier: 4.17.13 + version: 4.17.13 '@types/node': specifier: 18.19.130 version: 18.19.130 @@ -6941,8 +6941,8 @@ packages: '@types/jsonfile@6.1.4': resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - '@types/lodash@4.17.0': - resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==} + '@types/lodash@4.17.13': + resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==} '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -22330,7 +22330,7 @@ snapshots: '@devexpress/callsite-record@4.1.7': dependencies: - '@types/lodash': 4.17.0 + '@types/lodash': 4.17.13 callsite: 1.0.0 chalk: 2.4.2 error-stack-parser: 2.1.4 @@ -25977,7 +25977,7 @@ snapshots: dependencies: '@types/node': 20.12.8 - '@types/lodash@4.17.0': {} + '@types/lodash@4.17.13': {} '@types/mdast@3.0.15': dependencies: From 4714daae5c446e85c75c9ce2e7cea6a9f181a50f Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 13:24:42 +0200 Subject: [PATCH 04/30] chore(devextreme): migrate all:build-dev to nx with wrapped as nx targets gulp tasks --- package.json | 2 +- packages/devextreme/package.json | 1 - packages/devextreme/project.json | 165 ++++++++++++++++++++++++++++++- packages/workflows/project.json | 72 ++++++++++++++ tools/scripts/build-all.ts | 39 +++----- 5 files changed, 248 insertions(+), 31 deletions(-) create mode 100644 packages/workflows/project.json diff --git a/package.json b/package.json index 4cf0ccd7c3a5..9b1bb2a4c4f7 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "prepare": "husky install", "all:update-version": "ts-node tools/scripts/update-version.ts", "all:build": "ts-node tools/scripts/build-all.ts", - "all:build-dev": "pnpm run all:build --dev", + "all:build-dev": "nx all:build-dev workflows", "all:pack-and-copy": "nx run-many -t pack-and-copy", "demos:prepare": "nx run devextreme-demos:prepare-js", "demos:start": "http-server ./apps/demos --port 8080 -c-1" diff --git a/packages/devextreme/package.json b/packages/devextreme/package.json index f7347d7154ce..b85a28c78911 100644 --- a/packages/devextreme/package.json +++ b/packages/devextreme/package.json @@ -221,7 +221,6 @@ "lint-dts": "eslint './js/**/*.d.ts'", "lint-staged": "lint-staged", "lint-texts": "node build/linters/validate-non-latin-symbols.js", - "build": "cross-env BUILD_ESM_PACKAGE=true gulp default", "build:dev": "cross-env DEVEXTREME_TEST_CI=TRUE BUILD_ESM_PACKAGE=true gulp default", "build:testcafe": "cross-env DEVEXTREME_TEST_CI=TRUE BUILD_ESM_PACKAGE=true BUILD_TESTCAFE=TRUE gulp default", "build-npm-devextreme": "cross-env BUILD_ESM_PACKAGE=true gulp default", diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index 1f8c425fe69b..5a7b390d0530 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -88,10 +88,171 @@ ], "cache": true }, + "build:transpile": { + "executor": "nx:run-commands", + "options": { + "command": "cross-env BUILD_ESM_PACKAGE=true gulp transpile", + "cwd": "{projectRoot}" + }, + "inputs": [ + "{projectRoot}/js/**/*.js", + "{projectRoot}/build/gulp/transpile.js", + "{projectRoot}/babel.config.cjs" + ], + "outputs": [ + "{projectRoot}/artifacts/transpiled", + "{projectRoot}/artifacts/transpiled-esm-npm", + "{projectRoot}/artifacts/transpiled-renovation-npm" + ], + "cache": true + }, + "bundle:debug": { + "executor": "nx:run-commands", + "options": { + "command": "gulp js-bundles-debug", + "cwd": "{projectRoot}" + }, + "inputs": [ + { "env": "BUILD_TEST_INTERNAL_PACKAGE" }, + "{projectRoot}/artifacts/transpiled/**/*", + "{projectRoot}/artifacts/transpiled-esm/**/*", + "{projectRoot}/build/gulp/js-bundles.js", + "{projectRoot}/webpack.config.js" + ], + "outputs": [ + "{projectRoot}/artifacts/js/dx.all.debug.js", + "{projectRoot}/artifacts/js/dx.all.debug.js.map" + ], + "cache": true + }, + "bundle:prod": { + "executor": "nx:run-commands", + "options": { + "command": "gulp js-bundles-prod", + "cwd": "{projectRoot}" + }, + "inputs": [ + { "env": "BUILD_TEST_INTERNAL_PACKAGE" }, + "{projectRoot}/artifacts/transpiled/**/*", + "{projectRoot}/artifacts/transpiled-esm/**/*", + "{projectRoot}/build/gulp/js-bundles.js", + "{projectRoot}/webpack.config.js" + ], + "outputs": [ + "{projectRoot}/artifacts/js/dx.all.js", + "{projectRoot}/artifacts/js/dx.all.js.map" + ], + "cache": true + }, + "build:vectormap": { + "executor": "nx:run-commands", + "options": { + "command": "gulp vectormap", + "cwd": "{projectRoot}" + }, + "inputs": [ + "{projectRoot}/build/gulp/vectormap.js" + ], + "outputs": [ + "{projectRoot}/artifacts/js/vectormap-data" + ], + "cache": true + }, + "build:aspnet": { + "executor": "nx:run-commands", + "options": { + "command": "gulp aspnet", + "cwd": "{projectRoot}" + }, + "inputs": [ + "{projectRoot}/build/gulp/aspnet.js" + ], + "outputs": [ + "{projectRoot}/artifacts/js/aspnet" + ], + "cache": true + }, + "build:declarations": { + "executor": "nx:run-commands", + "options": { + "command": "gulp ts", + "cwd": "{projectRoot}" + }, + "inputs": [ + "{projectRoot}/ts/**/*.d.ts", + "{projectRoot}/build/gulp/ts.js" + ], + "outputs": [ + "{projectRoot}/artifacts/ts" + ], + "cache": true + }, + "verify:licenses": { + "executor": "nx:run-commands", + "options": { + "command": "gulp check-license-notices", + "cwd": "{projectRoot}" + }, + "cache": false + }, + "copy:vendor": { + "executor": "nx:run-commands", + "options": { + "command": "gulp vendor", + "cwd": "{projectRoot}" + }, + "inputs": [ + "{projectRoot}/build/gulp/vendor.js" + ], + "outputs": [ + "{projectRoot}/artifacts/js/vectormap-utils", + "{projectRoot}/artifacts/js/cldr" + ], + "cache": true + }, + "pack:devextreme-npm": { + "executor": "nx:run-commands", + "options": { + "command": "pnpm pack", + "cwd": "{projectRoot}/artifacts/npm/devextreme" + } + }, + "pack:devextreme-dist-npm": { + "executor": "nx:run-commands", + "options": { + "command": "pnpm pack", + "cwd": "{projectRoot}/artifacts/npm/devextreme-dist" + } + }, + "build:npm": { + "executor": "nx:run-commands", + "options": { + "command": "cross-env BUILD_ESM_PACKAGE=true gulp npm", + "cwd": "{projectRoot}" + }, + "inputs": [ + { "env": "BUILD_TEST_INTERNAL_PACKAGE" }, + "{projectRoot}/artifacts/transpiled/**/*", + "{projectRoot}/artifacts/transpiled-esm-npm/**/*" + ], + "outputs": [ + "{projectRoot}/artifacts/npm/devextreme", + "{projectRoot}/artifacts/npm/devextreme-dist" + ], + "cache": true + }, "build": { - "executor": "nx:run-script", + "executor": "nx:run-commands", "options": { - "script": "build" + "commands": [ + "pnpm nx clean:artifacts devextreme", + "pnpm nx build:localization devextreme", + "pnpm nx build:transpile devextreme", + "pnpm nx run-many --targets=bundle:debug,bundle:prod,build:vectormap,copy:vendor,build:aspnet,build:declarations --projects=devextreme --parallel", + "pnpm nx build:npm devextreme", + "pnpm nx verify:licenses devextreme" + ], + "parallel": false }, "inputs": [ { "env": "BUILD_TEST_INTERNAL_PACKAGE" }, diff --git a/packages/workflows/project.json b/packages/workflows/project.json new file mode 100644 index 000000000000..f2f401df6ba3 --- /dev/null +++ b/packages/workflows/project.json @@ -0,0 +1,72 @@ +{ + "name": "workflows", + "metadata": { + "description": "Build workflow that orchestrates targets across multiple packages for specific use cases like local development, CI/CD, etc." + }, + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "targets": { + "copy:artifacts-to-root": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "../devextreme/artifacts/js", "to": "../../artifacts/js" }, + { "from": "../devextreme/artifacts/css", "to": "../../artifacts/css" } + ] + } + }, + "copy:bootstrap": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "../devextreme-themebuilder/node_modules/bootstrap/dist/js/bootstrap.js", "to": "../../artifacts/js/bootstrap.js" }, + { "from": "../devextreme-themebuilder/node_modules/bootstrap/dist/js/bootstrap.min.js", "to": "../../artifacts/js/bootstrap.min.js" }, + { "from": "../devextreme-themebuilder/node_modules/bootstrap/dist/css/bootstrap.css", "to": "../../artifacts/css/bootstrap.css" }, + { "from": "../devextreme-themebuilder/node_modules/bootstrap/dist/css/bootstrap.min.css", "to": "../../artifacts/css/bootstrap.min.css" } + ] + } + }, + "copy:npm-tgz": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "../devextreme/artifacts/npm/devextreme/*.tgz", "to": "../../artifacts/npm/" }, + { "from": "../devextreme/artifacts/npm/devextreme-dist/*.tgz", "to": "../../artifacts/npm/" } + ] + } + }, + "copy:wrappers-tgz": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "../devextreme-angular/npm/dist/*.tgz", "to": "../../artifacts/npm/" }, + { "from": "../devextreme-react/npm/*.tgz", "to": "../../artifacts/npm/" }, + { "from": "../devextreme-vue/npm/*.tgz", "to": "../../artifacts/npm/" } + ] + } + }, + "all:build-dev": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpm nx build devextreme", + "pnpm nx build devextreme-themebuilder", + "pnpm nx copy:artifacts-to-root workflows", + "pnpm nx copy:bootstrap workflows", + "pnpm run all:pack-and-copy", + "pnpm nx pack devextreme-react", + "pnpm nx pack devextreme-vue", + "pnpm nx pack devextreme-angular", + "pnpm nx pack:devextreme-npm devextreme", + "pnpm nx pack:devextreme-dist-npm devextreme", + "pnpm nx copy:npm-tgz workflows", + "pnpm nx copy:wrappers-tgz workflows" + ], + "parallel": false + }, + "metadata": { + "description": "Build all packages for the local development environment." + } + } + } +} diff --git a/tools/scripts/build-all.ts b/tools/scripts/build-all.ts index 9f7e8aaf3343..d231a22fde9a 100644 --- a/tools/scripts/build-all.ts +++ b/tools/scripts/build-all.ts @@ -1,17 +1,8 @@ import sh from 'shelljs'; import path from 'node:path'; -import yargs from 'yargs'; import { ARTIFACTS_DIR, INTERNAL_TOOLS_ARTIFACTS, ROOT_DIR, NPM_DIR, JS_ARTIFACTS, CSS_ARTIFACTS } from './common/paths'; import { version as devextremeNpmVersion } from '../../packages/devextreme/package.json'; -const argv = yargs - .option('dev', { type: 'boolean', default: false }) - .parseSync(); - -const devMode = argv.dev; - -console.log(`Dev mode: ${devMode}`); - const DEVEXTREME_NPM_DIR = path.join(ROOT_DIR, 'packages/devextreme/artifacts/npm'); const injectDescriptions = () => { @@ -45,26 +36,20 @@ const MAJOR_VERSION = monorepoVersion.split('.').slice(0, 2).join('_'); sh.cd(ROOT_DIR); -if (!devMode) { - // aspnet metadata will be used in Build custom-tasks to inject aspnet descriptions - sh.exec(`pnpx nx run devextreme-metadata:make-aspnet-metadata`); +// aspnet metadata will be used in Build custom-tasks to inject aspnet descriptions +sh.exec(`pnpx nx run devextreme-metadata:make-aspnet-metadata`); - injectDescriptions(); -} +injectDescriptions(); -if (devMode) { - sh.exec('pnpx nx build devextreme'); -} else { - sh.exec('pnpx nx build devextreme-scss'); - sh.exec('pnpx nx build-dist devextreme --skipNxCache', { - env: { - ...sh.env, - BUILD_INTERNAL_PACKAGE: 'false' - } - }); -} +sh.exec('pnpx nx build devextreme-scss'); +sh.exec('pnpx nx build-dist devextreme --skipNxCache', { + env: { + ...sh.env, + BUILD_INTERNAL_PACKAGE: 'false' + } +}); -sh.exec(`pnpx nx build devextreme-themebuilder${devMode ? '' : ' --skipNxCache'}`); +sh.exec('pnpx nx build devextreme-themebuilder --skipNxCache'); // Copy artifacts for DXBuild (Installation) sh.pushd(path.join(ROOT_DIR, 'packages/devextreme/artifacts')); @@ -80,7 +65,7 @@ sh.exec('pnpm run all:pack-and-copy'); sh.exec('pnpx nx pack devextreme-react', { silent: true }); sh.exec('pnpx nx pack devextreme-vue', { silent: true }); -sh.exec(`pnpx nx pack${devMode ? '' : '-with-descriptions'} devextreme-angular`, { silent: true }); +sh.exec('pnpx nx pack-with-descriptions devextreme-angular', { silent: true }); sh.pushd(path.join(DEVEXTREME_NPM_DIR, 'devextreme')); packAndCopy(NPM_DIR); From 0724d35be8b113501ea8681901f10f2b4601ed4c Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 17:46:33 +0200 Subject: [PATCH 05/30] chore: create all:build-testing workflow --- .github/workflows/demos_visual_tests.yml | 5 +---- .github/workflows/publish-demos.yml | 4 +--- .github/workflows/testcafe_tests.yml | 3 +-- .github/workflows/wrapper_tests.yml | 6 +----- .github/workflows/wrapper_tests_e2e.yml | 5 +---- packages/devextreme/project.json | 10 +++++++++- packages/workflows/project.json | 23 +++++++++++++++++++++++ 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/.github/workflows/demos_visual_tests.yml b/.github/workflows/demos_visual_tests.yml index 8c3cea1d6108..819c33fda764 100644 --- a/.github/workflows/demos_visual_tests.yml +++ b/.github/workflows/demos_visual_tests.yml @@ -15,7 +15,6 @@ on: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} - BUILD_TEST_INTERNAL_PACKAGE: true RUN_TESTS: true jobs: @@ -149,9 +148,7 @@ jobs: - name: DevExtreme - Build-all if: needs.determine-framework-tests-scope.outputs.framework-tests-scope != 'none' - env: - BUILD_TEST_INTERNAL_PACKAGE: true - run: pnpm run all:build-dev + run: pnpm nx all:build-testing workflows - name: Zip artifacts (for jQuery tests) working-directory: ./packages/devextreme diff --git a/.github/workflows/publish-demos.yml b/.github/workflows/publish-demos.yml index bfb90c636b9c..ee81704afa95 100644 --- a/.github/workflows/publish-demos.yml +++ b/.github/workflows/publish-demos.yml @@ -38,9 +38,7 @@ jobs: pnpm install --frozen-lockfile - name: DevExtreme - Build-all - env: - BUILD_TEST_INTERNAL_PACKAGE: true - run: pnpm run all:build-dev + run: pnpm nx all:build-testing workflows - name: Move packages run: | diff --git a/.github/workflows/testcafe_tests.yml b/.github/workflows/testcafe_tests.yml index 9a96b37eded1..5eb20ca67bb2 100644 --- a/.github/workflows/testcafe_tests.yml +++ b/.github/workflows/testcafe_tests.yml @@ -15,7 +15,6 @@ on: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} - BUILD_TEST_INTERNAL_PACKAGE: true RUN_TESTS: true jobs: @@ -72,7 +71,7 @@ jobs: NODE_OPTIONS: --max-old-space-size=8192 run: | pnpx nx build devextreme-scss - pnpx nx build devextreme + pnpx nx build devextreme -c testing - name: Zip artifacts working-directory: ./packages/devextreme diff --git a/.github/workflows/wrapper_tests.yml b/.github/workflows/wrapper_tests.yml index 45a67fe5d3c1..50e6025fe0b4 100644 --- a/.github/workflows/wrapper_tests.yml +++ b/.github/workflows/wrapper_tests.yml @@ -10,7 +10,6 @@ on: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} - BUILD_TEST_INTERNAL_PACKAGE: true jobs: build: @@ -49,10 +48,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Build devextreme package - env: - BUILD_TEST_INTERNAL_PACKAGE: true - working-directory: ./packages/devextreme - run: pnpx nx build + run: pnpx nx build devextreme -c testing check-regenerate: runs-on: devextreme-shr2 diff --git a/.github/workflows/wrapper_tests_e2e.yml b/.github/workflows/wrapper_tests_e2e.yml index 49cc1b435d62..022816c61ff6 100644 --- a/.github/workflows/wrapper_tests_e2e.yml +++ b/.github/workflows/wrapper_tests_e2e.yml @@ -15,7 +15,6 @@ on: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} - BUILD_TEST_INTERNAL_PACKAGE: true jobs: build-packages: @@ -55,9 +54,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Build all DevExtreme packages - env: - BUILD_TEST_INTERNAL_PACKAGE: true - run: pnpm run all:build-dev + run: pnpm nx all:build-testing workflows - name: Build wrappers apps working-directory: e2e/wrappers diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index 5a7b390d0530..d304f133e299 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -264,7 +264,15 @@ "{projectRoot}/js/bundles/dx.custom.js", "{projectRoot}/js/common/core/localization/cldr-data", "{projectRoot}/js/common/core/localization/default_messages.js" - ] + ], + "cache": true, + "configurations": { + "testing": { + "env": { + "BUILD_TEST_INTERNAL_PACKAGE": "true" + } + } + } }, "build-dist": { "executor": "nx:run-script", diff --git a/packages/workflows/project.json b/packages/workflows/project.json index f2f401df6ba3..cee8e09854ff 100644 --- a/packages/workflows/project.json +++ b/packages/workflows/project.json @@ -67,6 +67,29 @@ "metadata": { "description": "Build all packages for the local development environment." } + }, + "all:build-testing": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpm nx build devextreme -c testing", + "pnpm nx build devextreme-themebuilder", + "pnpm nx copy:artifacts-to-root workflows", + "pnpm nx copy:bootstrap workflows", + "pnpm run all:pack-and-copy", + "pnpm nx pack devextreme-react", + "pnpm nx pack devextreme-vue", + "pnpm nx pack devextreme-angular", + "pnpm nx pack:devextreme-npm devextreme", + "pnpm nx pack:devextreme-dist-npm devextreme", + "pnpm nx copy:npm-tgz workflows", + "pnpm nx copy:wrappers-tgz workflows" + ], + "parallel": false + }, + "metadata": { + "description": "Build all packages for the testing environment." + } } } } From a1b85d3d6adf7d6c49d2e9bef4205e45ff563149 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Wed, 14 Jan 2026 17:26:39 +0200 Subject: [PATCH 06/30] chore(devextreme): align output paths in nx project config --- packages/devextreme/project.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index d304f133e299..6867a8cb1894 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -261,9 +261,9 @@ ], "outputs": [ "{projectRoot}/artifacts", - "{projectRoot}/js/bundles/dx.custom.js", - "{projectRoot}/js/common/core/localization/cldr-data", - "{projectRoot}/js/common/core/localization/default_messages.js" + "{projectRoot}/build/bundle-templates/dx.custom.js", + "{projectRoot}/js/__internal/core/localization/cldr-data", + "{projectRoot}/js/__internal/core/localization/default_messages.ts" ], "cache": true, "configurations": { @@ -308,9 +308,9 @@ ], "outputs": [ "{projectRoot}/artifacts", - "{projectRoot}/js/bundles/dx.custom.js", - "{projectRoot}/js/common/core/localization/cldr-data", - "{projectRoot}/js/common/core/localization/default_messages.js" + "{projectRoot}/build/bundle-templates/dx.custom.js", + "{projectRoot}/js/__internal/core/localization/cldr-data", + "{projectRoot}/js/__internal/core/localization/default_messages.ts" ], "cache": true }, From 40f6184e647ae8ac92bf55e4a0e09813c21b5427 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 12:32:50 +0200 Subject: [PATCH 07/30] fix: devextreme-angular, correct config is forwarded to target deps --- packages/devextreme-angular/project.json | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/devextreme-angular/project.json b/packages/devextreme-angular/project.json index 00c4391e592b..b96349108499 100644 --- a/packages/devextreme-angular/project.json +++ b/packages/devextreme-angular/project.json @@ -167,7 +167,13 @@ }, "build": { "executor": "nx:run-commands", - "dependsOn": ["^build"], + "dependsOn": [ + { + "dependencies": true, + "target": "build", + "params": "forward" + } + ], "options": { "commands": [ "pnpm --workspace-root nx clean:dist devextreme-angular", @@ -182,7 +188,14 @@ "{projectRoot}/npm/dist" ], "cache": true, - "inputs": ["default"] + "inputs": ["default"], + "configurations": { + "testing": { + "env": { + "BUILD_TEST_INTERNAL_PACKAGE": "true" + } + } + } }, "pack": { "executor": "nx:run-commands", @@ -289,7 +302,7 @@ "executor": "nx:run-commands", "options": { "commands": [ - "pnpm --workspace-root nx build devextreme-angular", + "pnpm --workspace-root nx build devextreme-angular -c testing", "pnpm --workspace-root nx build:tests devextreme-angular", "pnpm --workspace-root nx test:all devextreme-angular" ], From c59a993b69844ecd5a6dced5215d1c06d0ef2dbf Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 13:14:24 +0200 Subject: [PATCH 08/30] chore: remove unnecessary steps from all:build-dev workflow --- packages/workflows/project.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/workflows/project.json b/packages/workflows/project.json index cee8e09854ff..4e9f9cc10063 100644 --- a/packages/workflows/project.json +++ b/packages/workflows/project.json @@ -51,16 +51,11 @@ "commands": [ "pnpm nx build devextreme", "pnpm nx build devextreme-themebuilder", - "pnpm nx copy:artifacts-to-root workflows", - "pnpm nx copy:bootstrap workflows", - "pnpm run all:pack-and-copy", "pnpm nx pack devextreme-react", "pnpm nx pack devextreme-vue", "pnpm nx pack devextreme-angular", "pnpm nx pack:devextreme-npm devextreme", - "pnpm nx pack:devextreme-dist-npm devextreme", - "pnpm nx copy:npm-tgz workflows", - "pnpm nx copy:wrappers-tgz workflows" + "pnpm nx pack:devextreme-dist-npm devextreme" ], "parallel": false }, From 247b8e6deddd436055736f2790ced5ca85c9f373 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 13:14:35 +0200 Subject: [PATCH 09/30] chore: remove unnecessary steps from all:build-testing workflow --- packages/workflows/project.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/workflows/project.json b/packages/workflows/project.json index 4e9f9cc10063..62e5a97dad7a 100644 --- a/packages/workflows/project.json +++ b/packages/workflows/project.json @@ -69,16 +69,11 @@ "commands": [ "pnpm nx build devextreme -c testing", "pnpm nx build devextreme-themebuilder", - "pnpm nx copy:artifacts-to-root workflows", - "pnpm nx copy:bootstrap workflows", - "pnpm run all:pack-and-copy", "pnpm nx pack devextreme-react", "pnpm nx pack devextreme-vue", "pnpm nx pack devextreme-angular", "pnpm nx pack:devextreme-npm devextreme", - "pnpm nx pack:devextreme-dist-npm devextreme", - "pnpm nx copy:npm-tgz workflows", - "pnpm nx copy:wrappers-tgz workflows" + "pnpm nx pack:devextreme-dist-npm devextreme" ], "parallel": false }, From fb294a4be225d8586e37496544acfdda085aa207 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 15:10:05 +0200 Subject: [PATCH 10/30] feat(nx-infra-plugin): make executor output suppressible for cleaner CI logs --- .../executors/add-license-headers/executor.ts | 4 +- .../build-angular-library/executor.ts | 16 ++--- .../executors/build-typescript/executor.ts | 4 +- .../src/executors/clean/executor.ts | 10 ++-- .../src/executors/copy-files/executor.ts | 6 +- .../generate-component-names/executor.ts | 4 +- .../generate-components/angular-generator.ts | 20 +++---- .../executors/generate-components/executor.ts | 26 ++++----- .../src/executors/karma-multi-env/executor.ts | 58 +++++++++---------- .../src/executors/localization/executor.ts | 12 ++-- .../src/executors/pack-npm/executor.ts | 4 +- .../prepare-package-json/executor.ts | 2 +- .../executors/prepare-submodules/executor.ts | 8 +-- 13 files changed, 87 insertions(+), 87 deletions(-) diff --git a/packages/nx-infra-plugin/src/executors/add-license-headers/executor.ts b/packages/nx-infra-plugin/src/executors/add-license-headers/executor.ts index bffce3e121ab..342bc40a22d5 100644 --- a/packages/nx-infra-plugin/src/executors/add-license-headers/executor.ts +++ b/packages/nx-infra-plugin/src/executors/add-license-headers/executor.ts @@ -258,7 +258,7 @@ const runExecutor: PromiseExecutor = async (opt excludePatterns: options.excludePatterns ?? DEFAULTS.EXCLUDE_PATTERNS, }); - logger.info(`Adding license headers to ${files.length} files...`); + logger.verbose(`Adding license headers to ${files.length} files...`); const compiledTemplate = useCustomTemplate ? _.template(bannerTemplate) : null; @@ -277,7 +277,7 @@ const runExecutor: PromiseExecutor = async (opt ), ); - logger.info('License headers added successfully'); + logger.verbose('License headers added successfully'); return { success: true }; } catch (error) { logError('Failed to add license headers', error); diff --git a/packages/nx-infra-plugin/src/executors/build-angular-library/executor.ts b/packages/nx-infra-plugin/src/executors/build-angular-library/executor.ts index 4e22991a7585..31dcab78e85d 100644 --- a/packages/nx-infra-plugin/src/executors/build-angular-library/executor.ts +++ b/packages/nx-infra-plugin/src/executors/build-angular-library/executor.ts @@ -84,14 +84,14 @@ async function executeNgPackagrBuild(config: BuildConfiguration): Promise { return new Promise((resolve, reject) => { - logger.info(`Spawning process: ${options.command} ${options.args.join(' ')}`); + logger.verbose(`Spawning process: ${options.command} ${options.args.join(' ')}`); const child = spawn(options.command, options.args, options.options); child.on('close', (code, signal) => { - logger.info(`Process closed with code: ${code}, signal: ${signal || 'none'}`); + logger.verbose(`Process closed with code: ${code}, signal: ${signal || 'none'}`); const actualExitCode = code === null ? -1 : code; resolve({ exitCode: actualExitCode, signal: signal || undefined }); }); @@ -183,7 +183,7 @@ const runExecutor: PromiseExecutor = async ( context, ) => { try { - logger.info('Building Angular library with ng-packagr...'); + logger.verbose('Building Angular library with ng-packagr...'); const config = resolveBuildConfiguration(options, context); await validateBuildConfiguration(config); diff --git a/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts b/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts index 0e0fe22bc8c9..0cf58cd70a33 100644 --- a/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts +++ b/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts @@ -96,7 +96,7 @@ const runExecutor: PromiseExecutor = async (optio throw new Error(`No source files matched pattern: ${srcPattern}`); } - logger.info(`Building ${module.toUpperCase()} for ${sourceFiles.length} source files...`); + logger.verbose(`Building ${module.toUpperCase()} for ${sourceFiles.length} source files...`); const parsedConfig = ts.parseJsonConfigFileContent( tsconfigContent, @@ -121,7 +121,7 @@ const runExecutor: PromiseExecutor = async (optio return { success: false }; } - logger.info(`✓ ${module.toUpperCase()} build completed successfully`); + logger.verbose(`✓ ${module.toUpperCase()} build completed successfully`); return { success: true }; } catch (error) { logError(`Failed to build ${module.toUpperCase()}`, error); diff --git a/packages/nx-infra-plugin/src/executors/clean/executor.ts b/packages/nx-infra-plugin/src/executors/clean/executor.ts index 5b370238254f..f207c6a3d66f 100644 --- a/packages/nx-infra-plugin/src/executors/clean/executor.ts +++ b/packages/nx-infra-plugin/src/executors/clean/executor.ts @@ -98,12 +98,12 @@ const runExecutor: PromiseExecutor = async (options, contex ); const excludePatterns = options.excludePatterns || []; - logger.info( + logger.verbose( `Cleaning ${targetDirectory}${excludePatterns.length > 0 ? ` with ${excludePatterns.length} exclusions` : ' completely'}...`, ); if (excludePatterns.length > 0) { - logger.info(`Excluding patterns: ${excludePatterns.join(', ')}`); + logger.verbose(`Excluding patterns: ${excludePatterns.join(', ')}`); } try { @@ -111,16 +111,16 @@ const runExecutor: PromiseExecutor = async (options, contex if (excludePatterns.length === 0) { await removeDirectoryCompletely(targetDirectory); - logger.info(`Removed directory: ${targetDirectory}`); + logger.verbose(`Removed directory: ${targetDirectory}`); } else { if (!fs.existsSync(targetDirectory)) { - logger.info(`Directory does not exist: ${targetDirectory}`); + logger.verbose(`Directory does not exist: ${targetDirectory}`); return { success: true }; } await removeDirectoryWithExclusions(targetDirectory, absoluteExcludePaths); - logger.info( + logger.verbose( `Cleaned directory: ${targetDirectory} with ${absoluteExcludePaths.length} exclusions preserved`, ); } diff --git a/packages/nx-infra-plugin/src/executors/copy-files/executor.ts b/packages/nx-infra-plugin/src/executors/copy-files/executor.ts index 977bb0700066..0a0e714ae54e 100644 --- a/packages/nx-infra-plugin/src/executors/copy-files/executor.ts +++ b/packages/nx-infra-plugin/src/executors/copy-files/executor.ts @@ -37,7 +37,7 @@ async function copyGlobPatternFiles( const fileName = path.basename(file); const destFile = path.join(destPath, fileName); await copyFile(file, destFile); - logger.info(`Copied file ${file} -> ${destFile}`); + logger.verbose(`Copied file ${file} -> ${destFile}`); } return { success: true }; @@ -53,12 +53,12 @@ async function copyDirectPath(sourcePath: string, destPath: string): Promise<{ s if (sourceStat.isDirectory()) { await copyRecursive(sourcePath, destPath); - logger.info(`Copied directory ${sourcePath} -> ${destPath}`); + logger.verbose(`Copied directory ${sourcePath} -> ${destPath}`); return { success: true }; } await copyFile(sourcePath, destPath); - logger.info(`Copied file ${sourcePath} -> ${destPath}`); + logger.verbose(`Copied file ${sourcePath} -> ${destPath}`); return { success: true }; } diff --git a/packages/nx-infra-plugin/src/executors/generate-component-names/executor.ts b/packages/nx-infra-plugin/src/executors/generate-component-names/executor.ts index 267c0bb8766c..91ad72e971d0 100644 --- a/packages/nx-infra-plugin/src/executors/generate-component-names/executor.ts +++ b/packages/nx-infra-plugin/src/executors/generate-component-names/executor.ts @@ -45,7 +45,7 @@ const runExecutor: PromiseExecutor = async const projectRoot = resolveProjectPath(context); try { - logger.info(MSG_GENERATING); + logger.verbose(MSG_GENERATING); validateDependencies(); @@ -59,7 +59,7 @@ const runExecutor: PromiseExecutor = async const generator = new AngularComponentNamesGenerator(config); generator.generate(); - logger.info(MSG_GENERATED); + logger.verbose(MSG_GENERATED); return { success: true }; } catch (error) { logError(ERROR_GENERATION_FAILED, error); diff --git a/packages/nx-infra-plugin/src/executors/generate-components/angular-generator.ts b/packages/nx-infra-plugin/src/executors/generate-components/angular-generator.ts index 470053ed3ef8..d1ccf036ccb9 100644 --- a/packages/nx-infra-plugin/src/executors/generate-components/angular-generator.ts +++ b/packages/nx-infra-plugin/src/executors/generate-components/angular-generator.ts @@ -32,7 +32,7 @@ export async function generateAngularComponents( path.join(path.dirname(componentsDir), 'metadata', 'generated'), ); - logger.info('📝 Generating Angular-specific metadata...'); + logger.verbose('📝 Generating Angular-specific metadata...'); const metadataGenerator = new AngularMetadataGenerator(); metadataGenerator.generate({ outputFolderPath: metadataDir, @@ -45,9 +45,9 @@ export async function generateAngularComponents( sourceMetadataFilePath: require.resolve('devextreme-metadata/NGMetaData.json'), imdMetadataFilePath: require.resolve('devextreme-metadata/integration-data.json'), }); - logger.info('✓ Metadata generation completed'); + logger.verbose('✓ Metadata generation completed'); - logger.info('🔨 Generating component TypeScript files...'); + logger.verbose('🔨 Generating component TypeScript files...'); const componentGenerator = new AngularDotGenerator(); componentGenerator.generate({ metadataFolderPath: metadataDir, @@ -58,9 +58,9 @@ export async function generateAngularComponents( nestedPathPart: 'nested', basePathPart: 'base', }); - logger.info('✓ Component files generated'); + logger.verbose('✓ Component files generated'); - logger.info('📦 Generating module facades...'); + logger.verbose('📦 Generating module facades...'); const moduleFacadeGenerator = new AngularModuleFacadeGenerator(); moduleFacadeGenerator.generate({ moduleFacades: { @@ -72,9 +72,9 @@ export async function generateAngularComponents( }, }, }); - logger.info('✓ Module facades generated'); + logger.verbose('✓ Module facades generated'); - logger.info('📋 Generating index facades...'); + logger.verbose('📋 Generating index facades...'); const facadeGenerator = new AngularFacadeGenerator(); facadeGenerator.generate({ facades: { @@ -85,13 +85,13 @@ export async function generateAngularComponents( commonImports: ['./common', './common/grids', './common/charts'], templatingOptions: config.templatingOptions, }); - logger.info('✓ Index facades generated'); + logger.verbose('✓ Index facades generated'); - logger.info('🔗 Generating common reexports...'); + logger.verbose('🔗 Generating common reexports...'); AngularCommonReexportsGenerator.generate({ outputPath: path.dirname(componentsDir), metadata: metaData, templatingOptions: config.templatingOptions, }); - logger.info('✓ Common reexports generated'); + logger.verbose('✓ Common reexports generated'); } diff --git a/packages/nx-infra-plugin/src/executors/generate-components/executor.ts b/packages/nx-infra-plugin/src/executors/generate-components/executor.ts index 0472c98dd704..2cc927b1fae9 100644 --- a/packages/nx-infra-plugin/src/executors/generate-components/executor.ts +++ b/packages/nx-infra-plugin/src/executors/generate-components/executor.ts @@ -91,8 +91,8 @@ function resolveDefaultMetadataPath(): string { } function loadMetadata(metadataPath: string): any { - logger.info(MSG_LOADING_METADATA); - logger.info(` Path: ${metadataPath}`); + logger.verbose(MSG_LOADING_METADATA); + logger.verbose(` Path: ${metadataPath}`); if (!fs.existsSync(metadataPath)) { throw new Error(`Metadata file not found: ${metadataPath}`); @@ -102,7 +102,7 @@ function loadMetadata(metadataPath: string): any { const metaData = JSON.parse(metadataContent); const widgetCount = Object.keys(metaData.Widgets || {}).length; - logger.info(`✓ Loaded ${widgetCount} widget definitions`); + logger.verbose(`✓ Loaded ${widgetCount} widget definitions`); return metaData; } @@ -136,7 +136,7 @@ function loadConfigFromFile(projectRoot: string, configPath: string, framework: const config = require(absoluteConfigPath); const frameworkName = framework.charAt(0).toUpperCase() + framework.slice(1); - logger.info(`✓ Loaded ${frameworkName} configuration from ${configPath}`); + logger.verbose(`✓ Loaded ${frameworkName} configuration from ${configPath}`); return config; } catch (error) { logger.warn(`⚠️ Could not load configuration from ${configPath}: ${getErrorMessage(error)}`); @@ -166,7 +166,7 @@ function loadConfigFromGeneratorsFile( } const messages = createMessages(framework); - logger.info(messages.loadedConfig); + logger.verbose(messages.loadedConfig); return config; } catch (error) { logger.warn(`⚠️ Could not load generators-config.js: ${getErrorMessage(error)}`); @@ -244,26 +244,26 @@ async function executeGeneration( const messages = createMessages(framework); const handler = getFrameworkHandler(framework); - logger.info(messages.generating); + logger.verbose(messages.generating); await handler.executeGeneration(generateComponents, config, metaData); - logger.info(MSG_GENERATION_COMPLETED); + logger.verbose(MSG_GENERATION_COMPLETED); if (fs.existsSync(indexFileName)) { const indexContent = fs.readFileSync(indexFileName, ENCODING_UTF8); const exportCount = (indexContent.match(EXPORT_PATTERN) || []).length; - logger.info(` Exports: ${exportCount}`); + logger.verbose(` Exports: ${exportCount}`); } if (fs.existsSync(componentsDir)) { const dirCount = fs .readdirSync(componentsDir, { withFileTypes: true }) .filter((entry) => entry.isDirectory() && entry.name !== CORE_DIR).length; - logger.info(` Component Directories: ${dirCount}`); + logger.verbose(` Component Directories: ${dirCount}`); } - logger.info(messages.generationSuccess); + logger.verbose(messages.generationSuccess); } const runExecutor: PromiseExecutor = async ( @@ -276,10 +276,10 @@ const runExecutor: PromiseExecutor = asyn const framework: Framework = options.framework || 'react'; const messages = createMessages(framework); - logger.info(messages.starting); + logger.verbose(messages.starting); const projectRelativePath = path.relative(workspaceRoot, absoluteProjectRoot) || DOT_SLASH_PREFIX; - logger.info(` Project root: ${projectRelativePath}`); - logger.info(` Framework: ${framework}`); + logger.verbose(` Project root: ${projectRelativePath}`); + logger.verbose(` Framework: ${framework}`); try { const componentsDir = path.resolve( diff --git a/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts b/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts index 56182a6da8a7..f8c4a6727fcf 100644 --- a/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts +++ b/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts @@ -203,7 +203,7 @@ async function executeSingleRun( return (exitCode: number) => { const duration = Date.now() - startTime; - logger.info( + logger.verbose( `[${environment.toUpperCase()}] Karma callback called with exit code: ${exitCode}`, ); @@ -231,7 +231,7 @@ async function executeSingleRun( }; if (testResult.success) { - logger.info(`\n[${environment.toUpperCase()}] Tests completed successfully`); + logger.verbose(`\n[${environment.toUpperCase()}] Tests completed successfully`); } else { errorHandler.logError(testResult.error!); } @@ -319,7 +319,7 @@ const createWatchModeCallback = ( try { if (server && server.stop) { - logger.info(`[${environment.toUpperCase()}] Stopping Karma server...`); + logger.verbose(`[${environment.toUpperCase()}] Stopping Karma server...`); server.stop(); } } catch (cleanupError) { @@ -343,7 +343,7 @@ const createWatchModeCallback = ( const setupSignalHandlers = (server: any): void => { const handleExit = (signal: string) => { - logger.info(`\n${STATUS_ICONS.STOP} Received ${signal} - stopping watch mode...`); + logger.verbose(`\n${STATUS_ICONS.STOP} Received ${signal} - stopping watch mode...`); if (server && server.stop) { server.stop(); } @@ -403,18 +403,18 @@ const createExecutionResult = ( const logExecutionStart = (plan: ExecutionPlan, options: KarmaMultiEnvExecutorSchema): void => { if (options.watch) return; - logger.info(`Running tests in environments: ${plan.executionOrder.join(', ')}`); + logger.verbose(`Running tests in environments: ${plan.executionOrder.join(', ')}`); if (options.verbose) { - logger.info(`Karma config: ${options.karmaConfig}`); - logger.info(`Timeout: ${plan.timeout}ms`); + logger.verbose(`Karma config: ${options.karmaConfig}`); + logger.verbose(`Timeout: ${plan.timeout}ms`); } }; const logEnvironmentStart = (environment: KarmaEnvironment): void => - logger.info(`\n[${environment.toUpperCase()}] Starting tests...`); + logger.verbose(`\n[${environment.toUpperCase()}] Starting tests...`); const logWatchModeStart = (environment: KarmaEnvironment): void => - logger.info(`[${environment.toUpperCase()}] Watch mode enabled - starting Karma server...`); + logger.verbose(`[${environment.toUpperCase()}] Watch mode enabled - starting Karma server...`); const logTestResults = ( summary: TestSummary, @@ -422,27 +422,27 @@ const logTestResults = ( options: KarmaMultiEnvExecutorSchema, ): void => { if (options.watch) { - logger.info(`\n${STATUS_ICONS.WATCH} Watch mode active for: ${plan.executionOrder.join(', ')}`); + logger.verbose(`\n${STATUS_ICONS.WATCH} Watch mode active for: ${plan.executionOrder.join(', ')}`); if (options.verbose) { - logger.info(`Karma config: ${options.karmaConfig}`); - logger.info('Watching file changes...'); + logger.verbose(`Karma config: ${options.karmaConfig}`); + logger.verbose('Watching file changes...'); } - logger.info('Press CTRL+C to stop watching...'); + logger.verbose('Press CTRL+C to stop watching...'); return; } - logger.info('\n' + '='.repeat(50)); - logger.info(`${STATUS_ICONS.DOCUMENTATION} TEST RESULTS SUMMARY`); - logger.info('='.repeat(50)); - logger.info(`\n${STATUS_ICONS.SUCCESS} Environments tested: ${plan.executionOrder.join(', ')}`); - logger.info(`${STATUS_ICONS.CLOCK} Total duration: ${summary.totalDuration}ms`); + logger.verbose('\n' + '='.repeat(50)); + logger.verbose(`${STATUS_ICONS.DOCUMENTATION} TEST RESULTS SUMMARY`); + logger.verbose('='.repeat(50)); + logger.verbose(`\n${STATUS_ICONS.SUCCESS} Environments tested: ${plan.executionOrder.join(', ')}`); + logger.verbose(`${STATUS_ICONS.CLOCK} Total duration: ${summary.totalDuration}ms`); summary.results.forEach((result) => { const statusIcon = result.success ? STATUS_ICONS.SUCCESS : STATUS_ICONS.FAILURE; const durationText = `${result.duration}ms`; const statusText = result.success ? 'PASS' : 'FAIL'; - logger.info( + logger.verbose( `\n${statusIcon} ${result.environment.toUpperCase()}: ${statusText} (${durationText})`, ); if (!result.success && result.error) { @@ -451,7 +451,7 @@ const logTestResults = ( }); if (summary.summary.failed === 0) { - logger.info(`\n${STATUS_ICONS.CELEBRATION} SUCCESS: All tests passed`); + logger.verbose(`\n${STATUS_ICONS.CELEBRATION} SUCCESS: All tests passed`); } else { logger.error(`\n${STATUS_ICONS.ERROR} FAILURE: Some tests failed`); } @@ -461,7 +461,7 @@ const setupWatchModeEvents = (environment: KarmaEnvironment, server: any): void if (!server.on || typeof server.on !== 'function') return; server.on('browsers_ready', () => { - logger.info( + logger.verbose( `\n${STATUS_ICONS.WATCH} Watch mode active - browsers ready and watching for file changes...`, ); }); @@ -470,13 +470,13 @@ const setupWatchModeEvents = (environment: KarmaEnvironment, server: any): void const statusIcon = results.success ? STATUS_ICONS.SUCCESS : STATUS_ICONS.FAILURE; const statusText = results.success ? 'All tests passed' : 'Some tests failed'; - logger.info(`\n[${environment.toUpperCase()}] Test run completed. Success: ${results.success}`); - logger.info(`${statusIcon} ${statusText} in watch mode - continuing to watch...`); - logger.info('Press CTRL+C to stop watching...'); + logger.verbose(`\n[${environment.toUpperCase()}] Test run completed. Success: ${results.success}`); + logger.verbose(`${statusIcon} ${statusText} in watch mode - continuing to watch...`); + logger.verbose('Press CTRL+C to stop watching...'); }); server.on('file_list_modified', () => { - logger.info(`\n${STATUS_ICONS.REFRESH} File changes detected, re-running tests...`); + logger.verbose(`\n${STATUS_ICONS.REFRESH} File changes detected, re-running tests...`); }); }; @@ -496,7 +496,7 @@ async function executeWatchMode( setupWatchModeEvents(environment, server); setupSignalHandlers(server); - logger.info(`\n${STATUS_ICONS.START} Starting Karma server in watch mode...`); + logger.verbose(`\n${STATUS_ICONS.START} Starting Karma server in watch mode...`); server.start(); }); } @@ -529,10 +529,10 @@ const setupDebugModeEvents = (environment: KarmaEnvironment, server: any): void if (!server.on || typeof server.on !== 'function') return; server.on('browsers_ready', () => { - logger.info( + logger.verbose( `\n${STATUS_ICONS.DEBUG} Debug mode for the ${environment} environment is active. Click the "DEBUG" button in the opened browser window to start debugging.`, ); - logger.info('Press CTRL+C to stop debugging...'); + logger.verbose('Press CTRL+C to stop debugging...'); }); }; @@ -549,7 +549,7 @@ async function launchDebugMode( setupDebugModeEvents(environment, server); setupSignalHandlers(server); - logger.info(`\n${STATUS_ICONS.START} Starting Karma server in debug mode...`); + logger.verbose(`\n${STATUS_ICONS.START} Starting Karma server in debug mode...`); server.start(); }); } diff --git a/packages/nx-infra-plugin/src/executors/localization/executor.ts b/packages/nx-infra-plugin/src/executors/localization/executor.ts index bb5c60969203..787aea32c342 100644 --- a/packages/nx-infra-plugin/src/executors/localization/executor.ts +++ b/packages/nx-infra-plugin/src/executors/localization/executor.ts @@ -223,7 +223,7 @@ async function generateMessageFiles( const locales = getLocales(messagesDir); - logger.info(`Processing ${locales.length} locales...`); + logger.verbose(`Processing ${locales.length} locales...`); await Promise.all( locales.map(async (locale) => { @@ -414,13 +414,13 @@ const runExecutor: PromiseExecutor = async (options, } if (!skipMessageGeneration) { - logger.info('Generating localization message files...'); + logger.verbose('Generating localization message files...'); await generateMessageFiles(messagesDir, messageTemplate, messageOutputDir); - logger.info(`Message files generated in ${messageOutputDir}`); + logger.verbose(`Message files generated in ${messageOutputDir}`); } if (!skipCldrGeneration) { - logger.info('Generating CLDR TypeScript modules...'); + logger.verbose('Generating CLDR TypeScript modules...'); await generateCldrModules( absoluteProjectRoot, messagesDir, @@ -429,10 +429,10 @@ const runExecutor: PromiseExecutor = async (options, defaultMessagesOutputDir, lintGeneratedFiles, ); - logger.info(`CLDR modules generated in ${cldrDataOutputDir}`); + logger.verbose(`CLDR modules generated in ${cldrDataOutputDir}`); } - logger.info('Localization generation completed successfully'); + logger.verbose('Localization generation completed successfully'); return { success: true }; } catch (error) { logError('Localization executor failed', error); diff --git a/packages/nx-infra-plugin/src/executors/pack-npm/executor.ts b/packages/nx-infra-plugin/src/executors/pack-npm/executor.ts index 25b5edc84ec3..9deaacde7b4c 100644 --- a/packages/nx-infra-plugin/src/executors/pack-npm/executor.ts +++ b/packages/nx-infra-plugin/src/executors/pack-npm/executor.ts @@ -21,7 +21,7 @@ const runExecutor: PromiseExecutor = async (options, cont } try { - logger.info(`Running pnpm pack from ${absoluteProjectRoot} (packaging ${distDirectory})...`); + logger.verbose(`Running pnpm pack from ${absoluteProjectRoot} (packaging ${distDirectory})...`); const projectPath = path.join(workspaceRoot, 'packages', context.projectName); @@ -30,7 +30,7 @@ const runExecutor: PromiseExecutor = async (options, cont stdio: 'inherit', }); - logger.info(MSG_PACK_SUCCESS); + logger.verbose(MSG_PACK_SUCCESS); return { success: true }; } catch (error) { logError(MSG_PACK_FAILED, error); diff --git a/packages/nx-infra-plugin/src/executors/prepare-package-json/executor.ts b/packages/nx-infra-plugin/src/executors/prepare-package-json/executor.ts index 8315a808e821..afd664eac3b9 100644 --- a/packages/nx-infra-plugin/src/executors/prepare-package-json/executor.ts +++ b/packages/nx-infra-plugin/src/executors/prepare-package-json/executor.ts @@ -32,7 +32,7 @@ const runExecutor: PromiseExecutor = async (options, c const distPackageJson = path.join(distDirectory, PACKAGE_JSON_FILE); await writeJson(distPackageJson, pkg, JSON_INDENT); - logger.info(`Created ${distPackageJson}`); + logger.verbose(`Created ${distPackageJson}`); return { success: true }; } catch (error) { diff --git a/packages/nx-infra-plugin/src/executors/prepare-submodules/executor.ts b/packages/nx-infra-plugin/src/executors/prepare-submodules/executor.ts index cd955d3a5b42..299d10e21133 100644 --- a/packages/nx-infra-plugin/src/executors/prepare-submodules/executor.ts +++ b/packages/nx-infra-plugin/src/executors/prepare-submodules/executor.ts @@ -44,10 +44,10 @@ const runExecutor: PromiseExecutor = async (opt const distDirectory = path.join(absoluteProjectRoot, options.distDirectory || DEFAULT_DIST_DIR); try { - logger.info(MSG_PREPARING); + logger.verbose(MSG_PREPARING); if (options.submoduleFolders) { - logger.info( + logger.verbose( `Using custom submoduleFolders: ${JSON.stringify(options.submoduleFolders, null, 2)}`, ); } @@ -72,7 +72,7 @@ const runExecutor: PromiseExecutor = async (opt const allModuleParams: PackParam[] = [...packParamsForModules, ...packParamsForFolders]; - logger.info(`Processing ${allModuleParams.length} submodules...`); + logger.verbose(`Processing ${allModuleParams.length} submodules...`); await Promise.all( allModuleParams.map(([folder, moduleFileNames, moduleFilePath]) => @@ -80,7 +80,7 @@ const runExecutor: PromiseExecutor = async (opt ), ); - logger.info(MSG_SUCCESS); + logger.verbose(MSG_SUCCESS); return { success: true }; } catch (error) { logError(ERROR_PREPARE_SUBMODULES, error); From 216c6dc21357f3ab1fd1fadb46ea2515f9f1675a Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Thu, 15 Jan 2026 15:42:38 +0200 Subject: [PATCH 11/30] fix: eslint errors --- .../src/executors/karma-multi-env/executor.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts b/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts index f8c4a6727fcf..37b4969ced3f 100644 --- a/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts +++ b/packages/nx-infra-plugin/src/executors/karma-multi-env/executor.ts @@ -422,7 +422,9 @@ const logTestResults = ( options: KarmaMultiEnvExecutorSchema, ): void => { if (options.watch) { - logger.verbose(`\n${STATUS_ICONS.WATCH} Watch mode active for: ${plan.executionOrder.join(', ')}`); + logger.verbose( + `\n${STATUS_ICONS.WATCH} Watch mode active for: ${plan.executionOrder.join(', ')}`, + ); if (options.verbose) { logger.verbose(`Karma config: ${options.karmaConfig}`); logger.verbose('Watching file changes...'); @@ -434,7 +436,9 @@ const logTestResults = ( logger.verbose('\n' + '='.repeat(50)); logger.verbose(`${STATUS_ICONS.DOCUMENTATION} TEST RESULTS SUMMARY`); logger.verbose('='.repeat(50)); - logger.verbose(`\n${STATUS_ICONS.SUCCESS} Environments tested: ${plan.executionOrder.join(', ')}`); + logger.verbose( + `\n${STATUS_ICONS.SUCCESS} Environments tested: ${plan.executionOrder.join(', ')}`, + ); logger.verbose(`${STATUS_ICONS.CLOCK} Total duration: ${summary.totalDuration}ms`); summary.results.forEach((result) => { @@ -470,7 +474,9 @@ const setupWatchModeEvents = (environment: KarmaEnvironment, server: any): void const statusIcon = results.success ? STATUS_ICONS.SUCCESS : STATUS_ICONS.FAILURE; const statusText = results.success ? 'All tests passed' : 'Some tests failed'; - logger.verbose(`\n[${environment.toUpperCase()}] Test run completed. Success: ${results.success}`); + logger.verbose( + `\n[${environment.toUpperCase()}] Test run completed. Success: ${results.success}`, + ); logger.verbose(`${statusIcon} ${statusText} in watch mode - continuing to watch...`); logger.verbose('Press CTRL+C to stop watching...'); }); From 47eb42adc520ae18cc5b5f03536de726743269fb Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Fri, 16 Jan 2026 16:36:21 +0200 Subject: [PATCH 12/30] fix: correctly lauch devextreme build in demos_visual_tests --- .github/workflows/demos_visual_tests.yml | 4 ++-- apps/demos/project.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/demos_visual_tests.yml b/.github/workflows/demos_visual_tests.yml index 819c33fda764..18703316797c 100644 --- a/.github/workflows/demos_visual_tests.yml +++ b/.github/workflows/demos_visual_tests.yml @@ -144,7 +144,7 @@ jobs: shell: bash run: | pnpx nx build devextreme-scss - pnpx nx build devextreme + pnpx nx build devextreme -c testing - name: DevExtreme - Build-all if: needs.determine-framework-tests-scope.outputs.framework-tests-scope != 'none' @@ -472,7 +472,7 @@ jobs: - name: Prepare JS working-directory: apps/demos - run: pnpm run prepare-js + run: pnpm run prepare-js -c testing - name: Check generated JS demos working-directory: apps/demos diff --git a/apps/demos/project.json b/apps/demos/project.json index 1bfb4686dd9a..1599675608ff 100644 --- a/apps/demos/project.json +++ b/apps/demos/project.json @@ -109,7 +109,7 @@ "script": "prepare-js" }, "dependsOn": [ - { "projects": ["devextreme"], "target": "build" }, + { "projects": ["devextreme"], "target": "build", "params": "forward" }, { "projects": ["devextreme-angular", "devextreme-react", "devextreme-vue"], "target": "pack" } ], "inputs": [ From 5d47a5e4cd7c3efc13bd50bb29ac457b967d8ec9 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Tue, 20 Jan 2026 15:52:29 +0200 Subject: [PATCH 13/30] chore: replace --configuration with -c --- .github/workflows/default_workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/default_workflow.yml b/.github/workflows/default_workflow.yml index 8d6635151055..dab10b791215 100644 --- a/.github/workflows/default_workflow.yml +++ b/.github/workflows/default_workflow.yml @@ -56,7 +56,7 @@ jobs: run: > pnpx nx run-many -t lint,test - --configuration ci + -c ci --exclude devextreme devextreme-themebuilder From f75e7b4f82d47c976887bbafd8d2771c933862b1 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Tue, 20 Jan 2026 15:53:00 +0200 Subject: [PATCH 14/30] docs: update copilot-instructions.md --- .github/copilot-instructions.md | 68 +++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1f7b8b1c0992..19d6a2b65412 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -10,7 +10,7 @@ - **Languages:** TypeScript, JavaScript, SCSS, C# (.NET for test runner) - **Package Manager:** pnpm 9.15.4 (specified in package.json) - **Node Version:** 20.x (required by CI) -- **Build System:** Gulp + Nx + custom build scripts +- **Build System:** Gulp + Nx + custom build scripts + custom Nx executors (via `devextreme-nx-infra-plugin`) - **Test Frameworks:** QUnit, Jest, TestCafe, Karma (Angular) ## Critical Setup Requirements @@ -70,6 +70,8 @@ pnpm install --frozen-lockfile devextreme-themebuilder/ # Theme builder package devextreme-metadata/ # Metadata generation for wrappers devextreme-monorepo-tools/ # Internal tooling + nx-infra-plugin/ # Custom Nx executors for build automation + workflows/ # Reusable CI/CD workflow configurations testcafe-models/ # TestCafe page object models /apps/ @@ -150,13 +152,27 @@ pnpm run clean ``` **Build process includes:** -1. Localization generation +1. Localization generation (via `devextreme-nx-infra-plugin:localization` executor) 2. Component generation (Renovation architecture) 3. Transpilation (Babel) -4. Bundle creation (Webpack) -5. TypeScript declarations +4. Bundle creation (Webpack) - `bundle:debug` and `bundle:prod` targets +5. TypeScript declarations - `build:declarations` target 6. SCSS compilation (from devextreme-scss) -7. NPM package preparation +7. NPM package preparation - `build:npm` target + +**Granular Nx build targets (can be run individually):** +```bash +pnpx nx build:localization devextreme # Generate localization files +pnpx nx build:transpile devextreme # Transpile source code +pnpx nx bundle:debug devextreme # Create debug bundle +pnpx nx bundle:prod devextreme # Create production bundle +pnpx nx build:npm devextreme # Prepare NPM packages +``` + +**Build with testing configuration (for CI):** +```bash +pnpx nx build devextreme -c=testing +``` **Important environment variables:** - `DEVEXTREME_TEST_CI=true` - Enables test mode (skips building npm package) @@ -164,6 +180,33 @@ pnpm run clean - `BUILD_TESTCAFE=true` - Builds for TestCafe tests - `BUILD_TEST_INTERNAL_PACKAGE=true` - Builds internal test package +## Custom Nx Executors (nx-infra-plugin) + +The `packages/nx-infra-plugin` provides custom Nx executors for build automation: + +| Executor | Description | +|----------|-------------| +| `localization` | Generates localization message files and TypeScript CLDR data modules | +| `add-license-headers` | Adds license headers to source files | +| `copy-files` | Copies files with glob pattern support | +| `clean` | Cleans directories with exclude pattern support | +| `build-typescript` | Builds TypeScript projects | +| `generate-components` | Generates Angular/React/Vue wrapper components | +| `karma-multi-env` | Runs Karma tests across multiple Angular environments | + +**Example executor usage in project.json:** +```json +{ + "build:localization:generate": { + "executor": "devextreme-nx-infra-plugin:localization", + "options": { + "messagesDir": "./js/localization/messages", + "cldrDataOutputDir": "./js/__internal/core/localization/cldr-data" + } + } +} +``` + ## Testing ### Test Types and Commands @@ -348,8 +391,8 @@ pnpm run lint-ts -- --fix - `packages/devextreme-react/src/**/*` (except templates) - `packages/devextreme-vue/src/**/*` (except templates) - `packages/devextreme/js/renovation/**/*.j.tsx` -- `packages/devextreme/js/common/core/localization/default_messages.js` -- `packages/devextreme/js/common/core/localization/cldr-data/**/*` +- `packages/devextreme/js/__internal/core/localization/default_messages.ts` +- `packages/devextreme/js/__internal/core/localization/cldr-data/**/*` **Source files (EDIT THESE):** - `packages/devextreme/js/**/*.js` (core logic) @@ -378,6 +421,7 @@ pnpm run lint-ts -- --fix ## Key Facts - **Nx is used for task orchestration** - prefer `pnpx nx` commands over direct npm scripts +- **Custom Nx executors** - `devextreme-nx-infra-plugin` provides specialized executors for localization, file operations, and build tasks - **Frozen lockfile is mandatory** - CI will fail without it - **Build artifacts are in gitignore** - never commit `artifacts/` directories - **Wrappers are generated** - modify generators, not generated code @@ -385,6 +429,7 @@ pnpm run lint-ts -- --fix - **Monorepo uses pnpm workspaces** - dependencies are hoisted - **CI uses custom runners** - `devextreme-shr2` for most jobs, `ubuntu-latest` for some - **Timeouts are strict** - optimize for speed, use caching +- **Granular build caching** - individual build steps have proper Nx caching for faster rebuilds ## Quick Reference @@ -398,6 +443,14 @@ pnpm run all:build-dev # Build (prod) pnpm run all:build +# Build with testing configuration (for CI) +pnpx nx build devextreme -c=testing + +# Build specific targets +pnpx nx build:localization devextreme +pnpx nx build:transpile devextreme +pnpx nx bundle:debug devextreme + # Test pnpx nx run-many -t test pnpm run test-jest # From devextreme package @@ -411,6 +464,7 @@ pnpm run regenerate-all # Clean pnpm run clean # From devextreme package +pnpx nx clean:artifacts devextreme # Clean build artifacts only # Run demos pnpm run webserver # From root, then visit localhost:8080 From bad76be0671342f51f42b0b0a639d387c2f81511 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Tue, 20 Jan 2026 17:05:37 +0200 Subject: [PATCH 15/30] chore: remove unnecessary configuraiton option --- .github/workflows/demos_visual_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/demos_visual_tests.yml b/.github/workflows/demos_visual_tests.yml index 18703316797c..4f0f2a1770df 100644 --- a/.github/workflows/demos_visual_tests.yml +++ b/.github/workflows/demos_visual_tests.yml @@ -472,7 +472,7 @@ jobs: - name: Prepare JS working-directory: apps/demos - run: pnpm run prepare-js -c testing + run: pnpm run prepare-js - name: Check generated JS demos working-directory: apps/demos From c9fe3f2531aa0b67b69b5091dc872add2eb7f458 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Wed, 21 Jan 2026 17:43:09 +0200 Subject: [PATCH 16/30] feat(nx-infra-plugin): create `concatenate-files` executor --- packages/nx-infra-plugin/executors.json | 5 + .../concatenate-files/executor.e2e.spec.ts | 92 +++++++++ .../executors/concatenate-files/executor.ts | 177 ++++++++++++++++++ .../executors/concatenate-files/schema.json | 57 ++++++ .../src/executors/concatenate-files/schema.ts | 17 ++ 5 files changed, 348 insertions(+) create mode 100644 packages/nx-infra-plugin/src/executors/concatenate-files/executor.e2e.spec.ts create mode 100644 packages/nx-infra-plugin/src/executors/concatenate-files/executor.ts create mode 100644 packages/nx-infra-plugin/src/executors/concatenate-files/schema.json create mode 100644 packages/nx-infra-plugin/src/executors/concatenate-files/schema.ts diff --git a/packages/nx-infra-plugin/executors.json b/packages/nx-infra-plugin/executors.json index 30a85f6e44a9..4327c540273a 100644 --- a/packages/nx-infra-plugin/executors.json +++ b/packages/nx-infra-plugin/executors.json @@ -59,6 +59,11 @@ "implementation": "./src/executors/localization/executor", "schema": "./src/executors/localization/schema.json", "description": "Generate localization message files and TypeScript CLDR data modules" + }, + "concatenate-files": { + "implementation": "./src/executors/concatenate-files/executor", + "schema": "./src/executors/concatenate-files/schema.json", + "description": "Concatenate files with optional content extraction and transforms" } } } diff --git a/packages/nx-infra-plugin/src/executors/concatenate-files/executor.e2e.spec.ts b/packages/nx-infra-plugin/src/executors/concatenate-files/executor.e2e.spec.ts new file mode 100644 index 000000000000..7e34cbdd15fb --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/concatenate-files/executor.e2e.spec.ts @@ -0,0 +1,92 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import executor from './executor'; +import { ConcatenateFilesExecutorSchema } from './schema'; +import { createTempDir, cleanupTempDir, createMockContext } from '../../utils/test-utils'; +import { writeFileText, readFileText } from '../../utils'; + +describe('ConcatenateFilesExecutor E2E', () => { + let tempDir: string; + let context = createMockContext(); + let projectDir: string; + + beforeEach(async () => { + tempDir = createTempDir('nx-concatenate-e2e-'); + context = createMockContext({ root: tempDir }); + projectDir = path.join(tempDir, 'packages', 'test-lib'); + fs.mkdirSync(projectDir, { recursive: true }); + }); + + afterEach(() => { + cleanupTempDir(tempDir); + }); + + it('should handle devextreme-bundler-config use case', async () => { + const partsDir = path.join(projectDir, 'build', 'gulp', 'bundler-config'); + fs.mkdirSync(partsDir, { recursive: true }); + + await writeFileText( + path.join(partsDir, '01-header.js'), + `// Some preamble to ignore\r\n/// BUNDLER_PARTS\r\n const VERSION = '24.2';\r\n/// BUNDLER_PARTS_END\r\n// trailing code`, + ); + + await writeFileText( + path.join(partsDir, '02-core.js'), + `/// BUNDLER_PARTS\r\n require('./ui/core');\r\n require('./ui/widgets');\r\n/// BUNDLER_PARTS_END`, + ); + + await writeFileText( + path.join(partsDir, '03-footer.js'), + `/// BUNDLER_PARTS\r\n module.exports = DevExpress;\r\n/// BUNDLER_PARTS_END`, + ); + + const options: ConcatenateFilesExecutorSchema = { + sourceFiles: [ + './build/gulp/bundler-config/01-header.js', + './build/gulp/bundler-config/02-core.js', + './build/gulp/bundler-config/03-footer.js', + ], + outputFile: './artifacts/js/bundler-config.js', + header: '/* DevExtreme Bundler Config */\n/* Generated file - do not edit */\n\n', + footer: '\n\n/* End of bundler config */\n', + separator: '\n', + extractPattern: '[^]*BUNDLER_PARTS.*?$([^]*)^.*?BUNDLER_PARTS_END[^]*', + extractPatternFlags: 'gm', + transforms: [ + { find: '^[ ]{4}', replace: '', flags: 'gm' }, + { find: '\\n{3,}', replace: '\n\n', flags: 'g' }, + ], + }; + + const result = await executor(options, context); + + expect(result.success).toBe(true); + + const output = await readFileText( + path.join(projectDir, 'artifacts', 'js', 'bundler-config.js'), + ); + + expect(output.startsWith('/* DevExtreme Bundler Config */')).toBe(true); + + expect(output.endsWith('/* End of bundler config */\n')).toBe(true); + + expect(output).not.toContain('BUNDLER_PARTS'); + expect(output).not.toContain('Some preamble to ignore'); + expect(output).not.toContain('trailing code'); + + expect(output).toContain("const VERSION = '24.2';"); + expect(output).toContain("require('./ui/core');"); + expect(output).toContain("require('./ui/widgets');"); + expect(output).toContain('module.exports = DevExpress;'); + + expect(output).not.toMatch(/^ /m); + + expect(output).not.toContain('\r\n'); + + const versionPos = output.indexOf("VERSION = '24.2'"); + const requirePos = output.indexOf("require('./ui/core')"); + const exportPos = output.indexOf('module.exports'); + expect(versionPos).toBeLessThan(requirePos); + expect(requirePos).toBeLessThan(exportPos); + }); +}); diff --git a/packages/nx-infra-plugin/src/executors/concatenate-files/executor.ts b/packages/nx-infra-plugin/src/executors/concatenate-files/executor.ts new file mode 100644 index 000000000000..39a1d8ca3a3c --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/concatenate-files/executor.ts @@ -0,0 +1,177 @@ +import { PromiseExecutor, logger } from '@nx/devkit'; +import * as path from 'path'; +import { glob } from 'glob'; +import { ConcatenateFilesExecutorSchema, TransformRule } from './schema'; +import { resolveProjectPath, normalizeGlobPathForWindows } from '../../utils/path-resolver'; +import { isWindowsOS } from '../../utils/common'; +import { logError } from '../../utils/error-handler'; +import { readFileText, writeFileText, exists } from '../../utils/file-operations'; + +const ERROR_MESSAGES = { + SOURCE_FILES_EMPTY: 'sourceFiles must contain at least one file', + SOURCE_NOT_FOUND: (source: string) => `Source file not found: ${source}`, + NO_FILES_MATCH_PATTERN: (pattern: string) => `No files found matching pattern: ${pattern}`, + NO_FILES_RESOLVED: 'No source files found after resolving patterns', + FAILED_TO_CONCATENATE: 'Failed to concatenate files', +} as const; + +function containsGlobPattern(pattern: string): boolean { + return /[*?[\]{}]/.test(pattern); +} + +function extractContent(content: string, pattern: string, flags: string): string { + try { + const regex = new RegExp(pattern, flags); + const match = regex.exec(content); + return match?.[1] ?? content; + } catch { + logger.verbose(`Invalid extractPattern: ${pattern}. Using original content.`); + return content; + } +} + +function applyTransforms(content: string, transforms: TransformRule[]): string { + return transforms.reduce((result, { find, replace, flags = 'g' }) => { + try { + return result.replace(new RegExp(find, flags), replace); + } catch { + logger.verbose(`Invalid transform pattern: ${find}. Skipping.`); + return result; + } + }, content); +} + +function normalizeLineEndings(content: string): string { + return content.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); +} + +function applyHeaderFooter(content: string, header?: string, footer?: string): string { + let result = content; + if (header) result = header + result; + if (footer) result = result + footer; + return result; +} + +async function resolveGlobPattern(pattern: string, projectRoot: string): Promise { + const sourcePath = path.resolve(projectRoot, pattern); + const globPattern = isWindowsOS() ? normalizeGlobPathForWindows(sourcePath) : sourcePath; + const files = await glob(globPattern, { nodir: true }); + + if (files.length === 0) { + logger.verbose(ERROR_MESSAGES.NO_FILES_MATCH_PATTERN(pattern)); + } + + return files.sort(); +} + +async function resolveExactFile(source: string, projectRoot: string): Promise { + const sourcePath = path.resolve(projectRoot, source); + if (!(await exists(sourcePath))) { + throw new Error(ERROR_MESSAGES.SOURCE_NOT_FOUND(source)); + } + return sourcePath; +} + +async function resolveSourceFiles(sourceFiles: string[], projectRoot: string): Promise { + const resolvedFiles: string[] = []; + + for (const source of sourceFiles) { + if (containsGlobPattern(source)) { + const files = await resolveGlobPattern(source, projectRoot); + resolvedFiles.push(...files); + } else { + const file = await resolveExactFile(source, projectRoot); + resolvedFiles.push(file); + } + } + + return resolvedFiles; +} + +async function processFileContent( + filePath: string, + extractPattern?: string, + extractPatternFlags?: string, +): Promise { + const content = await readFileText(filePath); + + if (extractPattern) { + return extractContent(content, extractPattern, extractPatternFlags || 'gm'); + } + + return content; +} + +async function readAndProcessFiles( + files: string[], + projectRoot: string, + options: Pick, +): Promise { + return Promise.all( + files.map(async (filePath) => { + const content = await processFileContent( + filePath, + options.extractPattern, + options.extractPatternFlags, + ); + logger.verbose(`Processed: ${path.relative(projectRoot, filePath)}`); + return content; + }), + ); +} + +function buildOutput( + contents: string[], + options: Pick< + ConcatenateFilesExecutorSchema, + 'separator' | 'normalizeLineEndings' | 'header' | 'footer' | 'transforms' + >, +): string { + let output = contents.join(options.separator ?? '\n'); + + if (options.normalizeLineEndings !== false) { + output = normalizeLineEndings(output); + } + + output = applyHeaderFooter(output, options.header, options.footer); + + if (options.transforms?.length) { + output = applyTransforms(output, options.transforms); + } + + return output; +} + +const runExecutor: PromiseExecutor = async (options, context) => { + const projectRoot = resolveProjectPath(context); + + if (!options.sourceFiles?.length) { + logger.error(ERROR_MESSAGES.SOURCE_FILES_EMPTY); + return { success: false }; + } + + try { + const resolvedFiles = await resolveSourceFiles(options.sourceFiles, projectRoot); + + if (resolvedFiles.length === 0) { + logger.error(ERROR_MESSAGES.NO_FILES_RESOLVED); + return { success: false }; + } + + logger.verbose(`Concatenating ${resolvedFiles.length} files...`); + + const contents = await readAndProcessFiles(resolvedFiles, projectRoot, options); + const output = buildOutput(contents, options); + + const outputPath = path.resolve(projectRoot, options.outputFile); + await writeFileText(outputPath, output); + logger.verbose(`Created: ${path.relative(projectRoot, outputPath)}`); + + return { success: true }; + } catch (error) { + logError(ERROR_MESSAGES.FAILED_TO_CONCATENATE, error); + return { success: false }; + } +}; + +export default runExecutor; diff --git a/packages/nx-infra-plugin/src/executors/concatenate-files/schema.json b/packages/nx-infra-plugin/src/executors/concatenate-files/schema.json new file mode 100644 index 000000000000..0bea5d738af6 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/concatenate-files/schema.json @@ -0,0 +1,57 @@ +{ + "$schema": "https://json-schema.org/schema", + "type": "object", + "description": "Concatenate files with optional content extraction and transforms.", + "properties": { + "sourceFiles": { + "type": "array", + "description": "Ordered list of files or glob patterns to concatenate.", + "items": { "type": "string" } + }, + "outputFile": { + "type": "string", + "description": "Output file path relative to project root." + }, + "extractPattern": { + "type": "string", + "description": "Regex pattern to extract content from each file. Uses capture group $1." + }, + "extractPatternFlags": { + "type": "string", + "description": "Regex flags for extractPattern (default: 'gm')", + "default": "gm" + }, + "header": { + "type": "string", + "description": "Header to prepend to output." + }, + "footer": { + "type": "string", + "description": "Footer to append to output." + }, + "transforms": { + "type": "array", + "description": "Regex find/replace transforms applied after concatenation.", + "items": { + "type": "object", + "properties": { + "find": { "type": "string" }, + "replace": { "type": "string" }, + "flags": { "type": "string", "default": "g" } + }, + "required": ["find", "replace"] + } + }, + "normalizeLineEndings": { + "type": "boolean", + "description": "Normalize to LF line endings (default: true)", + "default": true + }, + "separator": { + "type": "string", + "description": "Separator between concatenated files (default: '\\n')", + "default": "\n" + } + }, + "required": ["sourceFiles", "outputFile"] +} diff --git a/packages/nx-infra-plugin/src/executors/concatenate-files/schema.ts b/packages/nx-infra-plugin/src/executors/concatenate-files/schema.ts new file mode 100644 index 000000000000..4e22150e5d5b --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/concatenate-files/schema.ts @@ -0,0 +1,17 @@ +export interface TransformRule { + find: string; + replace: string; + flags?: string; +} + +export interface ConcatenateFilesExecutorSchema { + sourceFiles: string[]; + outputFile: string; + extractPattern?: string; + extractPatternFlags?: string; + header?: string; + footer?: string; + transforms?: TransformRule[]; + normalizeLineEndings?: boolean; + separator?: string; +} From c29ed274b1e13cda492bf7908c14d88933142cf0 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Wed, 21 Jan 2026 17:45:47 +0200 Subject: [PATCH 17/30] chore(devextreme): create nx targets to replace the `bundler-config` gulp task --- packages/devextreme/project.json | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index 6867a8cb1894..e35e3533dd06 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -88,6 +88,53 @@ ], "cache": true }, + "build:devextreme-bundler-config:generate": { + "executor": "devextreme-nx-infra-plugin:concatenate-files", + "options": { + "sourceFiles": [ + "./build/bundle-templates/modules/parts/core.js", + "./build/bundle-templates/modules/parts/data.js", + "./build/bundle-templates/modules/parts/widgets-base.js", + "./build/bundle-templates/modules/parts/widgets-web.js", + "./build/bundle-templates/modules/parts/viz.js", + "./build/bundle-templates/modules/parts/aspnet.js" + ], + "outputFile": "./build/bundle-templates/dx.custom.js", + "extractPattern": "[^]*BUNDLER_PARTS.*?$([^]*)^.*?BUNDLER_PARTS_END[^]*", + "extractPatternFlags": "gm", + "header": "\"use strict\";\n\n/* Comment lines below for the widgets you don't require and run \"devextreme-bundler\" in this directory, then include dx.custom.js in your project */\n\n", + "transforms": [ + { + "find": "require *\\( *[\"']..\\/\\.\\.\\/", + "replace": "require('" + }, + { "find": "^[ ]{4}", "replace": "", "flags": "gm" }, + { "find": "\\n{3,}", "replace": "\n\n", "flags": "g" } + ] + }, + "inputs": ["{projectRoot}/build/bundle-templates/modules/parts/**/*.js"], + "outputs": ["{projectRoot}/build/bundle-templates/dx.custom.js"], + "cache": true + }, + "build:devextreme-bundler-config:prod": { + "dependsOn": ["build:devextreme-bundler-config:generate"], + "executor": "devextreme-nx-infra-plugin:concatenate-files", + "options": { + "sourceFiles": ["./build/bundle-templates/dx.custom.js"], + "outputFile": "./artifacts/npm/devextreme/bundles/dx.custom.config.js", + "transforms": [ + { + "find": "require *\\( *[\"']\\.\\.\\/", + "replace": "require('devextreme/" + } + ] + }, + "inputs": ["{projectRoot}/build/bundle-templates/dx.custom.js"], + "outputs": [ + "{projectRoot}/artifacts/npm/devextreme/bundles/dx.custom.config.js" + ], + "cache": true + }, "build:transpile": { "executor": "nx:run-commands", "options": { From 4ea1a5917ff1f98ac061c91db4987cb0ae32f000 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Fri, 23 Jan 2026 17:36:58 +0200 Subject: [PATCH 18/30] feat(nx-infra-plugin): add babel-transform executor for CJS/ESM transpilation --- packages/nx-infra-plugin/executors.json | 5 + packages/nx-infra-plugin/jest-resolver.js | 23 + packages/nx-infra-plugin/jest.config.ts | 2 + packages/nx-infra-plugin/package.json | 33 + .../babel-transform/executor.e2e.spec.ts | 157 +++ .../src/executors/babel-transform/executor.ts | 136 +++ .../src/executors/babel-transform/schema.json | 44 + .../src/executors/babel-transform/schema.ts | 9 + pnpm-lock.yaml | 1020 ++++++++++++++--- 9 files changed, 1297 insertions(+), 132 deletions(-) create mode 100644 packages/nx-infra-plugin/jest-resolver.js create mode 100644 packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts create mode 100644 packages/nx-infra-plugin/src/executors/babel-transform/executor.ts create mode 100644 packages/nx-infra-plugin/src/executors/babel-transform/schema.json create mode 100644 packages/nx-infra-plugin/src/executors/babel-transform/schema.ts diff --git a/packages/nx-infra-plugin/executors.json b/packages/nx-infra-plugin/executors.json index 4327c540273a..6dcdf6cd6818 100644 --- a/packages/nx-infra-plugin/executors.json +++ b/packages/nx-infra-plugin/executors.json @@ -64,6 +64,11 @@ "implementation": "./src/executors/concatenate-files/executor", "schema": "./src/executors/concatenate-files/schema.json", "description": "Concatenate files with optional content extraction and transforms" + }, + "babel-transform": { + "implementation": "./src/executors/babel-transform/executor", + "schema": "./src/executors/babel-transform/schema.json", + "description": "Transform JavaScript/TypeScript files using Babel with configurable presets" } } } diff --git a/packages/nx-infra-plugin/jest-resolver.js b/packages/nx-infra-plugin/jest-resolver.js new file mode 100644 index 000000000000..f048221ec13d --- /dev/null +++ b/packages/nx-infra-plugin/jest-resolver.js @@ -0,0 +1,23 @@ +const isModuleNotFoundInPnpmSymlinks = (error) => error.code === 'MODULE_NOT_FOUND'; + +const resolveWithJest = (request, options) => options.defaultResolver(request, options); + +const resolveWithNodeFollowingPnpmSymlinks = (request, basedir) => + require.resolve(request, { paths: [basedir] }); + +function pnpmCompatibleResolver(request, options) { + try { + return resolveWithJest(request, options); + } catch (jestFailedToFollowPnpmSymlinks) { + if (isModuleNotFoundInPnpmSymlinks(jestFailedToFollowPnpmSymlinks)) { + try { + return resolveWithNodeFollowingPnpmSymlinks(request, options.basedir); + } catch { + throw jestFailedToFollowPnpmSymlinks; + } + } + throw jestFailedToFollowPnpmSymlinks; + } +} + +module.exports = pnpmCompatibleResolver; diff --git a/packages/nx-infra-plugin/jest.config.ts b/packages/nx-infra-plugin/jest.config.ts index e4469f98d5f8..3018f786939b 100644 --- a/packages/nx-infra-plugin/jest.config.ts +++ b/packages/nx-infra-plugin/jest.config.ts @@ -6,5 +6,7 @@ export default { transform: { '^.+\\.ts$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], }, + transformIgnorePatterns: ['node_modules', '\\.js$', '\\.cjs$', '\\.json$'], moduleFileExtensions: ['ts', 'js', 'html'], + resolver: '/jest-resolver.js', }; diff --git a/packages/nx-infra-plugin/package.json b/packages/nx-infra-plugin/package.json index 6a998082b561..7bd7404a1af6 100644 --- a/packages/nx-infra-plugin/package.json +++ b/packages/nx-infra-plugin/package.json @@ -19,10 +19,42 @@ "rimraf": "3.0.2" }, "peerDependencies": { + "@babel/core": ">=7.0.0", + "@babel/plugin-transform-modules-commonjs": ">=7.0.0", + "@babel/plugin-transform-object-rest-spread": ">=7.0.0", + "@babel/plugin-transform-runtime": ">=7.0.0", + "@babel/preset-env": ">=7.0.0", + "babel-plugin-add-module-exports": ">=1.0.0", + "babel-plugin-inferno": ">=6.0.0", + "core-js-compat": ">=3.0.0", "karma": ">=6.0.0", "ng-packagr": ">=19.0.0" }, "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@babel/plugin-transform-modules-commonjs": { + "optional": true + }, + "@babel/plugin-transform-object-rest-spread": { + "optional": true + }, + "@babel/plugin-transform-runtime": { + "optional": true + }, + "@babel/preset-env": { + "optional": true + }, + "babel-plugin-add-module-exports": { + "optional": true + }, + "babel-plugin-inferno": { + "optional": true + }, + "core-js-compat": { + "optional": true + }, "karma": { "optional": true }, @@ -31,6 +63,7 @@ } }, "devDependencies": { + "@types/babel__core": "7.20.5", "@types/fs-extra": "11.0.4", "@types/jest": "29.5.14", "@types/normalize-path": "3.0.2", diff --git a/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts b/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts new file mode 100644 index 000000000000..9b8f5810b493 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts @@ -0,0 +1,157 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import executor from './executor'; +import { BabelTransformExecutorSchema } from './schema'; +import { + createTempDir, + cleanupTempDir, + createMockContext, + findWorkspaceRoot, +} from '../../utils/test-utils'; +import { writeFileText, readFileText } from '../../utils'; + +const WORKSPACE_ROOT = findWorkspaceRoot(); + +const BABEL_CONFIG = ` +'use strict'; + +const common = { + plugins: [ + ['babel-plugin-inferno', { 'imports': true }], + ['@babel/plugin-transform-object-rest-spread', { loose: true }], + ], + ignore: ['**/*.json'], +}; + +const targets = { ios: 15, android: 95, samsung: 13 }; + +module.exports = { + cjs: Object.assign({}, common, { + presets: [['@babel/preset-env', { targets }]], + plugins: common.plugins.concat([ + ['add-module-exports', { addDefaultProperty: true }], + ['@babel/plugin-transform-modules-commonjs', { strict: true }] + ]) + }), + esm: Object.assign({}, common, { + presets: [['@babel/preset-env', { targets, modules: false }]], + plugins: common.plugins.concat([ + ['@babel/plugin-transform-runtime', { useESModules: true, version: '7.5.0' }] + ]) + }) +}; +`; + +describe('BabelTransformExecutor E2E', () => { + let tempDir: string; + let context = createMockContext(); + let projectDir: string; + + beforeEach(async () => { + tempDir = createTempDir('nx-babel-e2e-'); + context = createMockContext({ root: tempDir }); + projectDir = path.join(tempDir, 'packages', 'test-lib'); + fs.mkdirSync(projectDir, { recursive: true }); + + const workspaceNodeModules = path.join(WORKSPACE_ROOT, 'node_modules'); + const tempNodeModules = path.join(projectDir, 'node_modules'); + fs.symlinkSync(workspaceNodeModules, tempNodeModules, 'junction'); + + const buildDir = path.join(projectDir, 'build', 'gulp'); + fs.mkdirSync(buildDir, { recursive: true }); + await writeFileText(path.join(buildDir, 'transpile-config.js'), BABEL_CONFIG); + + const jsDir = path.join(projectDir, 'js'); + fs.mkdirSync(jsDir, { recursive: true }); + + await writeFileText( + path.join(jsDir, 'module.js'), + `import { helper } from './utils'; + +export default function greet(name) { + return \`Hello, \${name}!\`; +} + +export const add = (a, b) => a + b; +`, + ); + + await writeFileText( + path.join(jsDir, 'utils.js'), + `export const something = 'test'; + +//#DEBUG +console.log('This is debug code'); +const debugOnly = true; +//#ENDDEBUG + +export function helper() { + return 42; +} +`, + ); + }); + + afterEach(() => { + cleanupTempDir(tempDir); + }); + + describe.each([ + { + configKey: 'cjs', + outDir: './artifacts/transpiled', + shouldContain: ['exports'], + shouldNotContain: ['export default function'], + }, + { + configKey: 'esm', + outDir: './artifacts/esm', + shouldContain: ['export'], + shouldNotContain: ['module.exports'], + }, + ])('$configKey config', ({ configKey, outDir, shouldContain, shouldNotContain }) => { + it('should transform files correctly', async () => { + const options: BabelTransformExecutorSchema = { + babelConfigPath: './build/gulp/transpile-config.js', + configKey, + sourcePattern: './js/**/*.js', + outDir, + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const outputDir = path.join(projectDir, outDir.replace('./', '')); + + expect(fs.existsSync(path.join(outputDir, 'module.js'))).toBe(true); + expect(fs.existsSync(path.join(outputDir, 'utils.js'))).toBe(true); + + const moduleContent = await readFileText(path.join(outputDir, 'module.js')); + + shouldContain.forEach((text) => expect(moduleContent).toContain(text)); + shouldNotContain.forEach((text) => expect(moduleContent).not.toContain(text)); + }, 30000); + }); + + it('should remove DEBUG blocks', async () => { + const options: BabelTransformExecutorSchema = { + babelConfigPath: './build/gulp/transpile-config.js', + configKey: 'cjs', + sourcePattern: './js/**/*.js', + outDir: './artifacts/transpiled-prod', + removeDebug: true, + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const utilsContent = await readFileText( + path.join(projectDir, 'artifacts', 'transpiled-prod', 'utils.js'), + ); + + expect(utilsContent).not.toContain('This is debug code'); + expect(utilsContent).not.toContain('debugOnly'); + expect(utilsContent).toContain('helper'); + expect(utilsContent).toContain('something'); + }, 30000); +}); diff --git a/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts b/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts new file mode 100644 index 000000000000..bba985f5a9f0 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts @@ -0,0 +1,136 @@ +import { PromiseExecutor, logger } from '@nx/devkit'; +import * as path from 'path'; +import * as fs from 'fs-extra'; +import * as babel from '@babel/core'; +import { glob } from 'glob'; +import { BabelTransformExecutorSchema } from './schema'; +import { resolveProjectPath, normalizeGlobPathForWindows } from '../../utils/path-resolver'; +import { isWindowsOS } from '../../utils/common'; + +function removeDebugBlocks(content: string): string { + return content.replace(/\/{2,}\s*#DEBUG[\s\S]*?\/{2,}\s*#ENDDEBUG/g, ''); +} + +function loadBabelConfig( + projectRoot: string, + configPath: string, + configKey: string, +): babel.TransformOptions { + const fullConfigPath = path.join(projectRoot, configPath); + + if (!fs.existsSync(fullConfigPath)) { + throw new Error(`Babel config not found: ${fullConfigPath}`); + } + + const config = require(fullConfigPath); + + if (!config[configKey]) { + const availableKeys = Object.keys(config).join(', '); + throw new Error(`Config key '${configKey}' not found. Available: ${availableKeys}`); + } + + return config[configKey]; +} + +function applyExtensionRenames(filePath: string, renameExtensions: Record): string { + const ext = path.extname(filePath); + + if (ext && ext in renameExtensions) { + return filePath.slice(0, -ext.length) + renameExtensions[ext]; + } + + return filePath; +} + +async function transformFile( + filePath: string, + projectRoot: string, + outDir: string, + sourcePattern: string, + babelConfig: babel.TransformOptions, + removeDebug: boolean, + renameExtensions: Record, +): Promise { + let content = await fs.readFile(filePath, 'utf-8'); + + if (removeDebug) { + content = removeDebugBlocks(content); + } + + const result = await babel.transformAsync(content, { + ...babelConfig, + filename: filePath, + }); + + if (!result?.code) { + throw new Error(`Babel returned no code for ${filePath}`); + } + + const cleanPattern = sourcePattern.replace(/^\.\//, ''); + const globIndex = cleanPattern.search(/\*+/); + const patternBase = + globIndex > 0 + ? cleanPattern.substring(0, globIndex).replace(/\/$/, '') + : cleanPattern.split('/')[0]; + const sourceBase = path.join(projectRoot, patternBase); + const relativePath = path.relative(sourceBase, filePath); + + const renamedRelativePath = applyExtensionRenames(relativePath, renameExtensions); + const outputPath = path.join(projectRoot, outDir, renamedRelativePath); + + await fs.ensureDir(path.dirname(outputPath)); + await fs.writeFile(outputPath, result.code); +} + +const runExecutor: PromiseExecutor = async (options, context) => { + const projectRoot = resolveProjectPath(context); + + try { + const babelConfig = loadBabelConfig(projectRoot, options.babelConfigPath, options.configKey); + const removeDebug = options.removeDebug ?? false; + const renameExtensions = options.renameExtensions ?? {}; + + const sourcePath = path.join(projectRoot, options.sourcePattern); + const globPattern = isWindowsOS() ? normalizeGlobPathForWindows(sourcePath) : sourcePath; + + const sourceFiles = await glob(globPattern, { + absolute: true, + ignore: options.excludePatterns || [], + }); + + if (sourceFiles.length === 0) { + logger.warn('No files matched the source pattern'); + return { success: false }; + } + + logger.verbose( + `Transforming ${sourceFiles.length} files with config '${options.configKey}'...`, + ); + if (removeDebug) { + logger.verbose('Debug blocks will be removed (production mode)'); + } + + await Promise.all( + sourceFiles.map((file) => + transformFile( + file, + projectRoot, + options.outDir, + options.sourcePattern, + babelConfig, + removeDebug, + renameExtensions, + ), + ), + ); + + logger.verbose(`Successfully transformed ${sourceFiles.length} files to ${options.outDir}`); + return { success: true }; + } catch (error) { + const errorMsg = error instanceof Error ? error.message : String(error); + logger.error(`Babel transform failed: ${errorMsg}`); + return { success: false }; + } +}; + +export default runExecutor; diff --git a/packages/nx-infra-plugin/src/executors/babel-transform/schema.json b/packages/nx-infra-plugin/src/executors/babel-transform/schema.json new file mode 100644 index 000000000000..0cd7adbb88ec --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/babel-transform/schema.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json-schema.org/schema", + "type": "object", + "title": "Babel Transform Executor", + "properties": { + "babelConfigPath": { + "type": "string", + "description": "Path to Babel config file relative to project root (e.g., './build/gulp/transpile-config.js')" + }, + "configKey": { + "type": "string", + "description": "Key in the config object to use (e.g., 'cjs', 'tsCjs', 'esm')" + }, + "sourcePattern": { + "type": "string", + "description": "Primary glob pattern for source files to transform (e.g., './js/**/*.js')" + }, + "excludePatterns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Glob patterns to exclude from processing" + }, + "outDir": { + "type": "string", + "description": "Output directory relative to project root where transformed files will be written" + }, + "removeDebug": { + "type": "boolean", + "default": false, + "description": "Remove #DEBUG...#ENDDEBUG blocks before transpilation (for production builds)" + }, + "renameExtensions": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Map of file extension renames to apply to output files" + } + }, + "required": ["babelConfigPath", "configKey", "sourcePattern", "outDir"], + "additionalProperties": false +} diff --git a/packages/nx-infra-plugin/src/executors/babel-transform/schema.ts b/packages/nx-infra-plugin/src/executors/babel-transform/schema.ts new file mode 100644 index 000000000000..ff5b4b72d787 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/babel-transform/schema.ts @@ -0,0 +1,9 @@ +export interface BabelTransformExecutorSchema { + babelConfigPath: string; + configKey: string; + sourcePattern: string; + excludePatterns?: string[]; + outDir: string; + removeDebug?: boolean; + renameExtensions?: Record; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb732afa3591..e80d4e367e21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2237,6 +2237,30 @@ importers: packages/nx-infra-plugin: dependencies: + '@babel/core': + specifier: '>=7.0.0' + version: 7.28.5 + '@babel/plugin-transform-modules-commonjs': + specifier: '>=7.0.0' + version: 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-object-rest-spread': + specifier: '>=7.0.0' + version: 7.28.6(@babel/core@7.28.5) + '@babel/plugin-transform-runtime': + specifier: '>=7.0.0' + version: 7.28.5(@babel/core@7.28.5) + '@babel/preset-env': + specifier: '>=7.0.0' + version: 7.28.5(@babel/core@7.28.5) + babel-plugin-add-module-exports: + specifier: '>=1.0.0' + version: 1.0.4 + babel-plugin-inferno: + specifier: '>=6.0.0' + version: 6.8.5(@babel/core@7.28.5) + core-js-compat: + specifier: '>=3.0.0' + version: 3.48.0 fs-extra: specifier: 11.2.0 version: 11.2.0 @@ -2259,6 +2283,9 @@ importers: specifier: 3.0.2 version: 3.0.2 devDependencies: + '@types/babel__core': + specifier: 7.20.5 + version: 7.20.5 '@types/fs-extra': specifier: 11.0.4 version: 11.0.4 @@ -2279,7 +2306,7 @@ importers: version: 3.5.3 ts-jest: specifier: 29.1.3 - version: 29.1.3(@babel/core@7.28.6)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.6))(jest@29.7.0(@types/node@18.19.130)(babel-plugin-macros@3.1.0)(node-notifier@9.0.1)(ts-node@10.9.2(@swc/core@1.15.3)(@types/node@20.12.8)(typescript@5.9.3)))(typescript@4.9.5) + version: 29.1.3(@babel/core@7.28.5)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.5))(jest@29.7.0(@types/node@18.19.130)(babel-plugin-macros@3.1.0)(node-notifier@9.0.1)(ts-node@10.9.2(@swc/core@1.15.3)(@types/node@20.12.8)(typescript@5.9.3)))(typescript@4.9.5) typescript: specifier: 4.9.5 version: 4.9.5 @@ -2820,6 +2847,10 @@ packages: resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} engines: {node: '>=6.9.0'} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + '@babel/core@7.28.6': resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} engines: {node: '>=6.9.0'} @@ -3540,18 +3571,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.25.9': - resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-object-rest-spread@7.28.4': - resolution: {integrity: sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.28.6': resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} engines: {node: '>=6.9.0'} @@ -3810,6 +3829,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/preset-env@7.28.5': + resolution: {integrity: sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/preset-env@7.28.6': resolution: {integrity: sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==} engines: {node: '>=6.9.0'} @@ -6788,9 +6813,6 @@ packages: '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} @@ -9269,8 +9291,8 @@ packages: peerDependencies: webpack: ^5.1.0 - core-js-compat@3.45.1: - resolution: {integrity: sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==} + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} core-js@2.6.12: resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} @@ -17174,12 +17196,10 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me teex@1.0.1: resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} @@ -19954,11 +19974,31 @@ snapshots: - supports-color '@babel/core@7.28.4': + dependencies: + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.6 + '@babel/template': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/core@7.28.5': dependencies: '@babel/code-frame': 7.27.1 '@babel/generator': 7.28.6 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) '@babel/helpers': 7.28.4 '@babel/parser': 7.28.6 '@babel/template': 7.27.2 @@ -20012,7 +20052,7 @@ snapshots: '@babel/generator@7.28.3': dependencies: '@babel/parser': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -20031,7 +20071,7 @@ snapshots: '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/helper-compilation-targets@7.27.2': dependencies: @@ -20057,7 +20097,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.25.9 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.6) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -20075,6 +20115,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.5 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20128,6 +20181,13 @@ snapshots: regexpu-core: 6.2.0 semver: 6.3.1 + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.2.0 + semver: 6.3.1 + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20174,8 +20234,8 @@ snapshots: '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.11 @@ -20185,8 +20245,19 @@ snapshots: '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.11 @@ -20196,8 +20267,8 @@ snapshots: '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.11 @@ -20246,7 +20317,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20255,7 +20326,16 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20264,7 +20344,7 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20295,6 +20375,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20334,6 +20423,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.3 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20361,6 +20459,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20440,7 +20547,7 @@ snapshots: '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@babel/parser@7.28.6': dependencies: @@ -20450,7 +20557,7 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20458,7 +20565,15 @@ snapshots: dependencies: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20466,7 +20581,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20480,6 +20595,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20495,6 +20615,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20505,7 +20630,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.26.10) + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.26.10) transitivePeerDependencies: - supports-color @@ -20514,7 +20639,16 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.4) + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.4) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5) transitivePeerDependencies: - supports-color @@ -20523,7 +20657,7 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.6) transitivePeerDependencies: - supports-color @@ -20535,6 +20669,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20555,7 +20697,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.28.6) transitivePeerDependencies: - supports-color @@ -20568,50 +20710,83 @@ snapshots: dependencies: '@babel/core': 7.28.4 + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20630,12 +20805,17 @@ snapshots: '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.26.10)': dependencies: @@ -20647,14 +20827,31 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.6)': @@ -20667,45 +20864,93 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + optional: true '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.6)': dependencies: @@ -20724,6 +20969,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20740,6 +20991,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20768,7 +21024,16 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.4) - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.5) + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -20826,6 +21091,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20863,6 +21137,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -20873,6 +21152,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-block-scoping@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20887,7 +21171,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -20899,6 +21183,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20919,7 +21211,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -20931,6 +21223,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20959,6 +21259,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-classes@7.28.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -20989,6 +21301,12 @@ snapshots: '@babel/helper-plugin-utils': 7.28.6 '@babel/template': 7.28.6 + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21005,7 +21323,7 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21013,7 +21331,15 @@ snapshots: dependencies: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21021,7 +21347,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21031,6 +21357,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21053,6 +21385,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21064,6 +21401,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21086,6 +21429,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21099,6 +21447,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21110,13 +21466,18 @@ snapshots: '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-exponentiation-operator@7.28.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-exponentiation-operator@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21137,6 +21498,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21145,7 +21511,7 @@ snapshots: '@babel/plugin-transform-flow-strip-types@7.25.9(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.28.6) '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.26.10)': @@ -21164,6 +21530,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21177,7 +21551,7 @@ snapshots: '@babel/core': 7.26.10 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21186,7 +21560,16 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21195,7 +21578,7 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21204,6 +21587,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21224,6 +21612,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21234,6 +21627,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-logical-assignment-operators@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21254,6 +21652,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21275,6 +21678,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21283,6 +21694,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21307,6 +21726,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21321,7 +21748,7 @@ snapshots: '@babel/helper-module-transforms': 7.28.3(@babel/core@7.26.10) '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21331,7 +21758,17 @@ snapshots: '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21341,7 +21778,7 @@ snapshots: '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.6) '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21361,6 +21798,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21381,6 +21826,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21397,6 +21848,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21407,6 +21863,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21422,6 +21883,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21432,14 +21898,18 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.28.6)': + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) + '@babel/core': 7.26.10 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.26.10) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.10) + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-object-rest-spread@7.28.4(@babel/core@7.28.4)': + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.28.6 @@ -21450,13 +21920,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.26.10)': + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.5 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.26.10) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.26.10) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.5) '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color @@ -21488,6 +21958,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21501,6 +21979,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21511,6 +21994,14 @@ snapshots: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 @@ -21519,17 +22010,25 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.26.10)': + '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.10 + '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.28.4)': + '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.4 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: @@ -21553,6 +22052,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21562,7 +22066,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color @@ -21574,6 +22078,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21599,6 +22111,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21627,6 +22148,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21635,7 +22161,7 @@ snapshots: '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.6)': dependencies: @@ -21647,12 +22173,12 @@ snapshots: '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.28.6)': dependencies: @@ -21669,13 +22195,18 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21692,6 +22223,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21714,6 +22251,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21722,8 +22264,8 @@ snapshots: '@babel/plugin-transform-runtime@7.23.3(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.6) babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.28.6) babel-plugin-polyfill-regenerator: 0.5.5(@babel/core@7.28.6) @@ -21755,6 +22297,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-runtime@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.5) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.5) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.5) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-runtime@7.28.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21777,6 +22331,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21790,6 +22349,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21816,6 +22383,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21831,6 +22403,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21846,6 +22423,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21872,6 +22454,11 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21883,6 +22470,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -21907,6 +22500,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 @@ -21919,6 +22518,12 @@ snapshots: '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.4) '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.26.10)': dependencies: '@babel/core': 7.26.10 @@ -22001,7 +22606,7 @@ snapshots: babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.26.10) babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.10) babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.26.10) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -22010,7 +22615,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.5 '@babel/core': 7.28.4 - '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.28.4) @@ -22053,7 +22658,7 @@ snapshots: '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.4) '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.4) '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.4) - '@babel/plugin-transform-object-rest-spread': 7.28.4(@babel/core@7.28.4) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.4) '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.4) '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.4) '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.4) @@ -22077,7 +22682,83 @@ snapshots: babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.4) babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.4) babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.4) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-env@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.28.5) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.5) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.5) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.5) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-block-scoping': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.28.5) + '@babel/plugin-transform-classes': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.5) + '@babel/plugin-transform-exponentiation-operator': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-logical-assignment-operators': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.5) + '@babel/plugin-transform-modules-systemjs': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.5) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.5) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-regenerator': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.5) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.5) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.5) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.5) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.5) + core-js-compat: 3.48.0 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -22153,7 +22834,7 @@ snapshots: babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.6) babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.6) babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.6) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -22161,7 +22842,7 @@ snapshots: '@babel/preset-flow@7.25.9(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-transform-flow-strip-types': 7.25.9(@babel/core@7.28.6) @@ -22169,27 +22850,34 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 esutils: 2.0.3 '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 + esutils: 2.0.3 + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.28.6 esutils: 2.0.3 '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 esutils: 2.0.3 '@babel/preset-react@7.28.5(@babel/core@7.28.6)': dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.6) '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.28.6) @@ -22229,12 +22917,12 @@ snapshots: '@babel/traverse@7.28.5': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.28.6 '@babel/generator': 7.28.6 '@babel/helper-globals': 7.28.0 '@babel/parser': 7.28.6 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -25780,20 +26468,16 @@ snapshots: '@babel/types': 7.28.5 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 + '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/babel__template@7.4.4': dependencies: '@babel/parser': 7.28.6 - '@babel/types': 7.28.5 - - '@types/babel__traverse@7.20.6': - dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/babel__traverse@7.28.0': dependencies: @@ -27781,6 +28465,20 @@ snapshots: transitivePeerDependencies: - supports-color + babel-jest@29.7.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.28.5) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + optional: true + babel-jest@29.7.0(@babel/core@7.28.6): dependencies: '@babel/core': 7.28.6 @@ -27816,12 +28514,19 @@ snapshots: babel-plugin-const-enum@1.2.0(@babel/core@7.28.6): dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.6) - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color + babel-plugin-inferno@6.8.5(@babel/core@7.28.5): + dependencies: + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/types': 7.28.5 + transitivePeerDependencies: + - '@babel/core' + babel-plugin-inferno@6.8.5(@babel/core@7.28.6): dependencies: '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.6) @@ -27844,7 +28549,7 @@ snapshots: '@babel/template': 7.27.2 '@babel/types': 7.28.5 '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 + '@types/babel__traverse': 7.28.0 babel-plugin-macros@2.8.0: dependencies: @@ -27869,7 +28574,7 @@ snapshots: babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.26.10): dependencies: - '@babel/compat-data': 7.28.6 + '@babel/compat-data': 7.28.5 '@babel/core': 7.26.10 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.26.10) semver: 6.3.1 @@ -27878,16 +28583,25 @@ snapshots: babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.4): dependencies: - '@babel/compat-data': 7.28.6 + '@babel/compat-data': 7.28.5 '@babel/core': 7.28.4 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.4) semver: 6.3.1 transitivePeerDependencies: - supports-color + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.5): + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.6): dependencies: - '@babel/compat-data': 7.28.6 + '@babel/compat-data': 7.28.5 '@babel/core': 7.28.6 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) semver: 6.3.1 @@ -27898,7 +28612,7 @@ snapshots: dependencies: '@babel/core': 7.26.10 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.26.10) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color @@ -27906,7 +28620,15 @@ snapshots: dependencies: '@babel/core': 7.28.4 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.4) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color @@ -27914,7 +28636,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color @@ -27922,7 +28644,7 @@ snapshots: dependencies: '@babel/core': 7.28.6 '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.28.6) - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 transitivePeerDependencies: - supports-color @@ -27947,6 +28669,13 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.6): dependencies: '@babel/core': 7.28.6 @@ -27989,10 +28718,30 @@ snapshots: babel-plugin-transform-typescript-metadata@0.3.2(@babel/core@7.28.6)(@babel/traverse@7.28.6): dependencies: '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 optionalDependencies: '@babel/traverse': 7.28.6 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.5) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.5) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.5) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.5) + optional: true + babel-preset-current-node-syntax@1.1.0(@babel/core@7.28.6): dependencies: '@babel/core': 7.28.6 @@ -28012,6 +28761,13 @@ snapshots: '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6) + babel-preset-jest@29.6.3(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.28.5) + optional: true + babel-preset-jest@29.6.3(@babel/core@7.28.6): dependencies: '@babel/core': 7.28.6 @@ -29160,7 +29916,7 @@ snapshots: tinyglobby: 0.2.15 webpack: 5.102.1(@swc/core@1.15.3)(esbuild@0.25.0) - core-js-compat@3.45.1: + core-js-compat@3.48.0: dependencies: browserslist: 4.28.1 @@ -31295,7 +32051,7 @@ snapshots: change-case: 5.4.4 ci-info: 4.3.0 clean-regexp: 1.0.0 - core-js-compat: 3.45.1 + core-js-compat: 3.48.0 eslint: 9.18.0(jiti@2.6.1) esquery: 1.6.0 find-up-simple: 1.0.1 @@ -37994,7 +38750,7 @@ snapshots: react-docgen@8.0.2: dependencies: '@babel/core': 7.28.6 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 '@babel/types': 7.28.5 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 @@ -40612,7 +41368,7 @@ snapshots: '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.28.6) '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.6) '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.28.6) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6) '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.28.6) '@babel/plugin-transform-runtime': 7.23.3(@babel/core@7.28.6) '@babel/preset-env': 7.28.6(@babel/core@7.28.6) @@ -40961,7 +41717,7 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.28.6) - ts-jest@29.1.3(@babel/core@7.28.6)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.6))(jest@29.7.0(@types/node@18.19.130)(babel-plugin-macros@3.1.0)(node-notifier@9.0.1)(ts-node@10.9.2(@swc/core@1.15.3)(@types/node@20.12.8)(typescript@5.9.3)))(typescript@4.9.5): + ts-jest@29.1.3(@babel/core@7.28.5)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.5))(jest@29.7.0(@types/node@18.19.130)(babel-plugin-macros@3.1.0)(node-notifier@9.0.1)(ts-node@10.9.2(@swc/core@1.15.3)(@types/node@20.12.8)(typescript@5.9.3)))(typescript@4.9.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -40974,10 +41730,10 @@ snapshots: typescript: 4.9.5 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.28.6 + '@babel/core': 7.28.5 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.6) + babel-jest: 29.7.0(@babel/core@7.28.5) ts-jest@29.1.3(@babel/core@7.28.6)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.6))(jest@29.7.0(@types/node@20.14.5)(babel-plugin-macros@3.1.0)(node-notifier@9.0.1)(ts-node@10.9.2(@swc/core@1.15.3)(@types/node@20.12.8)(typescript@5.9.3)))(typescript@4.9.5): dependencies: From 995c239127a46bd3eeaa4fbb5d33425e8bc9563c Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 26 Jan 2026 13:09:28 +0200 Subject: [PATCH 19/30] chore(devextreme): add nx targets for transpile task --- packages/devextreme/project.json | 248 +++++++++++++++++- .../src/executors/copy-files/schema.json | 6 +- 2 files changed, 243 insertions(+), 11 deletions(-) diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index e35e3533dd06..d723e024e9c0 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -135,23 +135,257 @@ ], "cache": true }, - "build:transpile": { + "clean:dist-ts": { + "executor": "devextreme-nx-infra-plugin:clean", + "options": { + "targetDirectory": "./artifacts/dist_ts" + } + }, + "build:ts:internal": { "executor": "nx:run-commands", "options": { - "command": "cross-env BUILD_ESM_PACKAGE=true gulp transpile", + "command": "gulp ts-compile-internal", "cwd": "{projectRoot}" }, "inputs": [ - "{projectRoot}/js/**/*.js", - "{projectRoot}/build/gulp/transpile.js", - "{projectRoot}/babel.config.cjs" + "{projectRoot}/js/__internal/**/*.{ts,tsx}", + "!{projectRoot}/js/__internal/**/__tests__/**/*", + "{projectRoot}/js/__internal/tsconfig.json" + ], + "outputs": ["{projectRoot}/artifacts/dist_ts"], + "cache": true + }, + "build:cjs": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "cjs", + "sourcePattern": "./js/**/*.{js,jsx}", + "excludePatterns": ["./js/**/*.d.ts", "./js/__internal/**/*"], + "outDir": "./artifacts/transpiled" + }, + "configurations": { + "production": { + "outDir": "./artifacts/transpiled-renovation-npm", + "removeDebug": true + } + }, + "inputs": [ + "{projectRoot}/js/**/*.{js,jsx}", + "!{projectRoot}/js/**/*.d.ts", + "!{projectRoot}/js/__internal/**/*" + ], + "outputs": ["{projectRoot}/artifacts/transpiled"], + "cache": true + }, + "copy:json:transpiled": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "./js/localization/messages", "to": "./artifacts/transpiled/localization/messages" }, + { "from": "./js/viz/vector_map.utils/_settings.json", "to": "./artifacts/transpiled/viz/vector_map.utils/_settings.json" } + ] + }, + "inputs": ["{projectRoot}/js/**/*.json", "!{projectRoot}/js/__internal/**/*"], + "outputs": ["{projectRoot}/artifacts/transpiled/**/*.json"], + "cache": true + }, + "copy:json:transpiled-production": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "./js/localization/messages", "to": "./artifacts/transpiled-renovation-npm/localization/messages" }, + { "from": "./js/viz/vector_map.utils/_settings.json", "to": "./artifacts/transpiled-renovation-npm/viz/vector_map.utils/_settings.json" } + ] + }, + "inputs": ["{projectRoot}/js/**/*.json", "!{projectRoot}/js/__internal/**/*"], + "outputs": ["{projectRoot}/artifacts/transpiled-renovation-npm/**/*.json"], + "cache": true + }, + "copy:json:esm-npm": { + "executor": "devextreme-nx-infra-plugin:copy-files", + "options": { + "files": [ + { "from": "./js/localization/messages", "to": "./artifacts/transpiled-esm-npm/esm/localization/messages" }, + { "from": "./js/viz/vector_map.utils/_settings.json", "to": "./artifacts/transpiled-esm-npm/esm/viz/vector_map.utils/_settings.json" }, + { "from": "./js/localization/messages", "to": "./artifacts/transpiled-esm-npm/cjs/localization/messages" }, + { "from": "./js/viz/vector_map.utils/_settings.json", "to": "./artifacts/transpiled-esm-npm/cjs/viz/vector_map.utils/_settings.json" } + ] + }, + "inputs": ["{projectRoot}/js/**/*.json", "!{projectRoot}/js/__internal/**/*"], + "outputs": ["{projectRoot}/artifacts/transpiled-esm-npm/**/*.json"], + "cache": true + }, + "build:npm:esm": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "esm", + "sourcePattern": "./js/**/*.{js,jsx}", + "excludePatterns": ["./js/**/*.d.ts", "./js/__internal/**/*"], + "outDir": "./artifacts/transpiled-esm-npm/esm", + "removeDebug": true + }, + "inputs": [ + "{projectRoot}/js/**/*.{js,jsx}", + "!{projectRoot}/js/**/*.d.ts", + "!{projectRoot}/js/__internal/**/*" + ], + "outputs": ["{projectRoot}/artifacts/transpiled-esm-npm/esm"], + "cache": true + }, + "build:npm:cjs": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "cjs", + "sourcePattern": "./js/**/*.{js,jsx}", + "excludePatterns": ["./js/**/*.d.ts", "./js/__internal/**/*"], + "outDir": "./artifacts/transpiled-esm-npm/cjs", + "removeDebug": true + }, + "inputs": [ + "{projectRoot}/js/**/*.{js,jsx}", + "!{projectRoot}/js/**/*.d.ts", + "!{projectRoot}/js/__internal/**/*" + ], + "outputs": ["{projectRoot}/artifacts/transpiled-esm-npm/cjs"], + "cache": true + }, + "build:cjs:internal": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "tsCjs", + "sourcePattern": "./artifacts/dist_ts/__internal/**/*.{js,jsx}", + "outDir": "./artifacts/transpiled/__internal", + "renameExtensions": { ".jsx": ".js" } + }, + "configurations": { + "production": { + "outDir": "./artifacts/transpiled-renovation-npm/__internal", + "removeDebug": true + } + }, + "inputs": ["{projectRoot}/artifacts/dist_ts/__internal/**/*.{js,jsx}"], + "outputs": ["{projectRoot}/artifacts/transpiled/__internal"], + "cache": true + }, + "build:npm:esm:internal": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "esm", + "sourcePattern": "./artifacts/dist_ts/__internal/**/*.{js,jsx}", + "outDir": "./artifacts/transpiled-esm-npm/esm/__internal", + "removeDebug": true, + "renameExtensions": { ".jsx": ".js" } + }, + "inputs": ["{projectRoot}/artifacts/dist_ts/__internal/**/*.{js,jsx}"], + "outputs": ["{projectRoot}/artifacts/transpiled-esm-npm/esm/__internal"], + "cache": true + }, + "build:npm:cjs:internal": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "tsCjs", + "sourcePattern": "./artifacts/dist_ts/__internal/**/*.{js,jsx}", + "outDir": "./artifacts/transpiled-esm-npm/cjs/__internal", + "removeDebug": true, + "renameExtensions": { ".jsx": ".js" } + }, + "inputs": ["{projectRoot}/artifacts/dist_ts/__internal/**/*.{js,jsx}"], + "outputs": ["{projectRoot}/artifacts/transpiled-esm-npm/cjs/__internal"], + "cache": true + }, + "build:cjs:bundles": { + "executor": "devextreme-nx-infra-plugin:babel-transform", + "options": { + "babelConfigPath": "./build/gulp/transpile-config.js", + "configKey": "cjs", + "sourcePattern": "./build/bundle-templates/**/*.js", + "outDir": "./artifacts/transpiled/bundles", + "removeDebug": true + }, + "configurations": { + "production": { + "outDir": "./artifacts/transpiled-renovation-npm/bundles" + }, + "esm-npm": { + "outDir": "./artifacts/transpiled-esm-npm/bundles" + } + }, + "inputs": ["{projectRoot}/build/bundle-templates/**/*.js"], + "outputs": ["{projectRoot}/artifacts/transpiled/bundles"], + "cache": true + }, + "build:npm:dual-mode": { + "executor": "nx:run-commands", + "options": { + "command": "cross-env BUILD_ESM_PACKAGE=true gulp esm-dual-mode-manifests", + "cwd": "{projectRoot}" + }, + "inputs": [ + "{projectRoot}/artifacts/transpiled-esm-npm/esm/**/*", + "{projectRoot}/artifacts/transpiled-esm-npm/cjs/**/*", + "{projectRoot}/js/**/*.d.ts" + ], + "outputs": [ + "{projectRoot}/artifacts/transpiled-esm-npm/**/package.json" + ], + "cache": true + }, + "build:transpile": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "pnpm nx build:devextreme-bundler-config:generate devextreme", + "pnpm nx build:ts:internal devextreme", + "pnpm nx run-many --targets=build:cjs,build:cjs:internal,build:cjs:bundles --projects=devextreme --parallel", + "pnpm nx copy:json:transpiled devextreme", + "pnpm nx run-many --targets=build:cjs,build:cjs:internal,build:cjs:bundles --projects=devextreme --parallel -c production", + "pnpm nx copy:json:transpiled-production devextreme", + "pnpm nx run-many --targets=build:npm:esm,build:npm:esm:internal,build:npm:cjs,build:npm:cjs:internal --projects=devextreme --parallel", + "pnpm nx copy:json:esm-npm devextreme", + "pnpm nx build:cjs:bundles devextreme -c esm-npm", + "pnpm nx build:npm:dual-mode devextreme", + "pnpm nx clean:dist-ts devextreme" + ], + "cwd": "{projectRoot}", + "parallel": false + }, + "inputs": [ + "{projectRoot}/js/**/*.{js,ts,tsx}", + "!{projectRoot}/js/**/*.d.ts", + "{projectRoot}/build/bundle-templates/**/*.js" ], "outputs": [ "{projectRoot}/artifacts/transpiled", "{projectRoot}/artifacts/transpiled-esm-npm", - "{projectRoot}/artifacts/transpiled-renovation-npm" + "{projectRoot}/artifacts/transpiled-renovation-npm", + "{projectRoot}/build/bundle-templates/dx.custom.js" ], - "cache": true + "cache": true, + "configurations": { + "ci": { + "commands": [ + "pnpm nx build:devextreme-bundler-config:generate devextreme", + "pnpm nx build:ts:internal devextreme", + "pnpm nx run-many --targets=build:cjs,build:cjs:internal,build:cjs:bundles --projects=devextreme --parallel", + "pnpm nx copy:json:transpiled devextreme", + "pnpm nx run-many --targets=build:cjs,build:cjs:internal,build:cjs:bundles --projects=devextreme --parallel -c production", + "pnpm nx copy:json:transpiled-production devextreme", + "pnpm nx run-many --targets=build:npm:cjs,build:npm:cjs:internal --projects=devextreme --parallel", + "pnpm nx clean:dist-ts devextreme" + ], + "outputs": [ + "{projectRoot}/artifacts/transpiled", + "{projectRoot}/artifacts/transpiled-renovation-npm", + "{projectRoot}/build/bundle-templates/dx.custom.js" + ] + } + } }, "bundle:debug": { "executor": "nx:run-commands", diff --git a/packages/nx-infra-plugin/src/executors/copy-files/schema.json b/packages/nx-infra-plugin/src/executors/copy-files/schema.json index 10e9cc609c07..08f65d656642 100644 --- a/packages/nx-infra-plugin/src/executors/copy-files/schema.json +++ b/packages/nx-infra-plugin/src/executors/copy-files/schema.json @@ -1,17 +1,15 @@ { - "$schema": "https://json-schema.org/schema", + "$schema": "http://json-schema.org/schema", "type": "object", - "description": "Copy files or directories to a destination. Supports glob patterns and recursive directory copying.", "properties": { "files": { "type": "array", - "description": "Array of file copy operations to perform.", "items": { "type": "object", "properties": { "from": { "type": "string", - "description": "Source path relative to project root. Supports glob patterns (e.g., './src/*.ts', './assets/**/*')." + "description": "Source path relative to project root. Can be a file, directory, or glob pattern." }, "to": { "type": "string", From 930e86f3c127993bd9f53bc3a2cf0fd64b397179 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 26 Jan 2026 13:12:13 +0200 Subject: [PATCH 20/30] chore(devextreme): remove transpile code migrated to nx executors --- packages/devextreme/build/gulp/transpile.js | 106 ++------------------ packages/devextreme/gulpfile.js | 6 ++ 2 files changed, 16 insertions(+), 96 deletions(-) diff --git a/packages/devextreme/build/gulp/transpile.js b/packages/devextreme/build/gulp/transpile.js index 4d9ee7d19c93..d4d9f8297aff 100644 --- a/packages/devextreme/build/gulp/transpile.js +++ b/packages/devextreme/build/gulp/transpile.js @@ -3,7 +3,6 @@ const babel = require('gulp-babel'); const flatMap = require('gulp-flatmap'); const fs = require('fs'); -const del = require('del'); const gulp = require('gulp'); const normalize = require('normalize-path'); @@ -13,11 +12,9 @@ const plumber = require('gulp-plumber'); const rename = require('gulp-rename'); const replace = require('gulp-replace'); const watch = require('gulp-watch'); -const cache = require('gulp-cache'); const removeDebug = require('./compression-pipes.js').removeDebug; const ctx = require('./context.js'); -const { ifEsmPackage } = require('./utils'); const testsConfig = require('../../testing/tests.babelrc.json'); const transpileConfig = require('./transpile-config'); @@ -58,7 +55,6 @@ const generatedTs = [ ]; const TS_OUTPUT_BASE_DIR = 'artifacts/dist_ts'; -const TS_OUTPUT_SRC = [`${TS_OUTPUT_BASE_DIR}/__internal/**/*.{js,jsx}`]; const TS_COMPILER_CONFIG = { baseAbsPath: path.resolve(__dirname, '../..'), relativePath: { @@ -112,83 +108,17 @@ const transpileTs = (compiler, src) => { return task; }; -const transpileTsClean = () => - async() => await del(TS_OUTPUT_BASE_DIR, { force: true }); - - -const createTranspileTask = (input, output, pipes) => - () => { - let result = gulp.src(input); - - pipes.forEach(pipe => { - result = result.pipe(pipe); - }); - - return result.pipe(gulp.dest(output)); - }; - - -const transpile = (src, dist, { jsPipes, tsPipes }) => { - const transpilePipes = []; - - if(tsPipes) { - const transpileTS = createTranspileTask(TS_OUTPUT_SRC, `${dist}/__internal`, tsPipes); - transpileTS.displayName = `transpile TS: ${dist}`; - transpilePipes.push(transpileTS); - } - - if(jsPipes) { - const transpileJS = createTranspileTask(src, dist, jsPipes); - transpileJS.displayName = `transpile JS: ${dist}`; - transpilePipes.push(transpileJS); - } - - - return gulp.series(...transpilePipes); -}; - -const cachedJsBabelCjs = () => - cache(babel(transpileConfig.cjs), { name: 'babel-cjs' }); - -const bundlesSrc = 'build/bundle-templates/**/*.js'; - -const transpileBundles = (dist) => transpile(bundlesSrc, path.join(dist, './bundles'), { - jsPipes: [ removeDebug(), cachedJsBabelCjs() ], +gulp.task('ts-compile-internal', (done) => { + createTsCompiler(TS_COMPILER_CONFIG).then((compiler) => { + transpileTs(compiler, srcTsPattern)() + .on('end', done) + .on('error', done); + }); }); -const transpileDefault = () => gulp.series( - transpile(src, ctx.TRANSPILED_PATH, { - jsPipes: [ cachedJsBabelCjs() ], - tsPipes: [ babel(transpileConfig.tsCjs) ], - }), - transpileBundles(ctx.TRANSPILED_PATH), -); - -const transpileProd = (dist, isEsm) => transpile( - src, - dist, - { - jsPipes: [ - removeDebug(), - isEsm ? babel(transpileConfig.esm) : cachedJsBabelCjs() - ], - tsPipes: [ - removeDebug(), - isEsm ? babel(transpileConfig.esm) : babel(transpileConfig.tsCjs), - ] - }, -); - -const transpileRenovationProd = (watch) => gulp.series( - transpileProd(ctx.TRANSPILED_PROD_RENOVATION_PATH, false, watch), - transpileBundles(ctx.TRANSPILED_PROD_RENOVATION_PATH), -); - -const transpileEsm = (dist) => gulp.series.apply(gulp, [ - transpileProd(path.join(dist, './cjs'), false), - transpileProd(path.join(dist, './esm'), true), - transpileBundles(dist), - () => gulp +gulp.task('esm-dual-mode-manifests', () => { + const dist = ctx.TRANSPILED_PROD_ESM_PATH; + return gulp .src(esmTranspileSrc) .pipe(flatMap((stream, file) => { const filePath = file.path; @@ -213,25 +143,9 @@ const transpileEsm = (dist) => gulp.series.apply(gulp, [ fPath.extname = '.json'; })); })) - .pipe(gulp.dest(dist)) -]); - -gulp.task('transpile-esm', transpileEsm(ctx.TRANSPILED_PROD_ESM_PATH)); - -gulp.task('transpile', (done) => { - createTsCompiler(TS_COMPILER_CONFIG).then((compiler) => { - gulp.series( - 'bundler-config', - transpileTs(compiler, srcTsPattern), - transpileDefault(), - transpileRenovationProd(), - ifEsmPackage('transpile-esm'), - transpileTsClean(), - )(done); - }); + .pipe(gulp.dest(dist)); }); - const watchJsTask = () => { const watchTask = watch(src) .on('ready', () => console.log('transpile JS is watching for changes...')) diff --git a/packages/devextreme/gulpfile.js b/packages/devextreme/gulpfile.js index 5b7f67fd296b..899e35357cf8 100644 --- a/packages/devextreme/gulpfile.js +++ b/packages/devextreme/gulpfile.js @@ -41,6 +41,12 @@ require('./build/gulp/check_licenses'); require('./build/gulp/systemjs'); require('./build/gulp/state_manager'); +gulp.task('transpile', shell.task( + env.TEST_CI + ? 'pnpm nx run devextreme:build:transpile -c ci' + : 'pnpm nx run devextreme:build:transpile' +)); + if(env.TEST_CI) { console.warn('Using test CI mode!'); } From 03366a4a828a054ba3dc772d41d523a0dc11d81f Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Tue, 27 Jan 2026 12:48:43 +0200 Subject: [PATCH 21/30] fix(devextreme): add missing bundler-config:prod to build:transpile pipeline --- packages/devextreme/project.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index d723e024e9c0..bb9e851651a1 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -341,6 +341,7 @@ "options": { "commands": [ "pnpm nx build:devextreme-bundler-config:generate devextreme", + "pnpm nx build:devextreme-bundler-config:prod devextreme", "pnpm nx build:ts:internal devextreme", "pnpm nx run-many --targets=build:cjs,build:cjs:internal,build:cjs:bundles --projects=devextreme --parallel", "pnpm nx copy:json:transpiled devextreme", @@ -364,13 +365,15 @@ "{projectRoot}/artifacts/transpiled", "{projectRoot}/artifacts/transpiled-esm-npm", "{projectRoot}/artifacts/transpiled-renovation-npm", - "{projectRoot}/build/bundle-templates/dx.custom.js" + "{projectRoot}/build/bundle-templates/dx.custom.js", + "{projectRoot}/artifacts/npm/devextreme/bundles/dx.custom.config.js" ], "cache": true, "configurations": { "ci": { "commands": [ "pnpm nx build:devextreme-bundler-config:generate devextreme", + "pnpm nx build:devextreme-bundler-config:prod devextreme", "pnpm nx build:ts:internal devextreme", "pnpm nx run-many --targets=build:cjs,build:cjs:internal,build:cjs:bundles --projects=devextreme --parallel", "pnpm nx copy:json:transpiled devextreme", @@ -382,7 +385,8 @@ "outputs": [ "{projectRoot}/artifacts/transpiled", "{projectRoot}/artifacts/transpiled-renovation-npm", - "{projectRoot}/build/bundle-templates/dx.custom.js" + "{projectRoot}/build/bundle-templates/dx.custom.js", + "{projectRoot}/artifacts/npm/devextreme/bundles/dx.custom.config.js" ] } } From 45ee74751ea8ddb7c12d4bf25d8df81235fbaab1 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Tue, 27 Jan 2026 13:11:00 +0200 Subject: [PATCH 22/30] fix(nx-infra-plugin): fix babel-transform E2E tests failing under pnpx nx --- .../executors/babel-transform/executor.e2e.spec.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts b/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts index 9b8f5810b493..439f71b4f1c8 100644 --- a/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts +++ b/packages/nx-infra-plugin/src/executors/babel-transform/executor.e2e.spec.ts @@ -46,16 +46,25 @@ describe('BabelTransformExecutor E2E', () => { let tempDir: string; let context = createMockContext(); let projectDir: string; + let savedCwd: string; beforeEach(async () => { + savedCwd = process.cwd(); tempDir = createTempDir('nx-babel-e2e-'); context = createMockContext({ root: tempDir }); projectDir = path.join(tempDir, 'packages', 'test-lib'); fs.mkdirSync(projectDir, { recursive: true }); - const workspaceNodeModules = path.join(WORKSPACE_ROOT, 'node_modules'); + const infraPluginNodeModules = path.join( + WORKSPACE_ROOT, + 'packages', + 'nx-infra-plugin', + 'node_modules', + ); const tempNodeModules = path.join(projectDir, 'node_modules'); - fs.symlinkSync(workspaceNodeModules, tempNodeModules, 'junction'); + fs.symlinkSync(infraPluginNodeModules, tempNodeModules, 'junction'); + + process.chdir(projectDir); const buildDir = path.join(projectDir, 'build', 'gulp'); fs.mkdirSync(buildDir, { recursive: true }); @@ -93,6 +102,7 @@ export function helper() { }); afterEach(() => { + process.chdir(savedCwd); cleanupTempDir(tempDir); }); From 1e4c988250487f5349df8a2834e8eb4d5762f5c4 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 22 Dec 2025 15:53:15 +0200 Subject: [PATCH 23/30] chore(devextreme): create the localization gulp task alternative based on nx --- pnpm-lock.yaml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e80d4e367e21..31bcb6cd9795 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13055,10 +13055,6 @@ packages: js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - js-yaml@3.14.2: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true @@ -24095,7 +24091,7 @@ snapshots: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 - js-yaml: 3.14.1 + js-yaml: 3.14.2 resolve-from: 5.0.0 '@istanbuljs/schema@0.1.3': {} @@ -35766,11 +35762,6 @@ snapshots: js-tokens@9.0.1: {} - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - js-yaml@3.14.2: dependencies: argparse: 1.0.10 From 7794a083b0e5312718b4112327f843599d283293 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Fri, 23 Jan 2026 17:36:59 +0200 Subject: [PATCH 24/30] feat(nx-infra-plugin): add create-dual-mode-manifest executor --- .../build/gulp/side-effects-finder.js | 76 ------ packages/nx-infra-plugin/executors.json | 5 + packages/nx-infra-plugin/package.json | 2 + .../executor.e2e.spec.ts | 198 ++++++++++++++++ .../create-dual-mode-manifest/executor.ts | 219 ++++++++++++++++++ .../create-dual-mode-manifest/schema.json | 40 ++++ .../create-dual-mode-manifest/schema.ts | 8 + .../side-effect-finder.ts | 75 ++++++ pnpm-lock.yaml | 6 + 9 files changed, 553 insertions(+), 76 deletions(-) delete mode 100644 packages/devextreme/build/gulp/side-effects-finder.js create mode 100644 packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.e2e.spec.ts create mode 100644 packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.ts create mode 100644 packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.json create mode 100644 packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.ts create mode 100644 packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/side-effect-finder.ts diff --git a/packages/devextreme/build/gulp/side-effects-finder.js b/packages/devextreme/build/gulp/side-effects-finder.js deleted file mode 100644 index 2df1e4c1ee35..000000000000 --- a/packages/devextreme/build/gulp/side-effects-finder.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); - -class SideEffectFinder { - checkedPaths = new Map(); - recursiveHandlingPaths = new Set(); - - getModuleSideEffectFiles(moduleFilePath) { - try { - const moduleSideEffectFiles = [...this.findSideEffectsInModule(moduleFilePath)] - .map((importPath) => importPath.replace(/\\/g, '/')); - - return moduleSideEffectFiles; - } catch(e) { - const message = (e instanceof Error) ? e.message : e; - throw (`Exception while check side effects. in ${moduleFilePath} \nException: ` + message + '\n'); - } - } - - findSideEffectsInModule(moduleFilePath) { - let foundPaths = this.checkedPaths.get(moduleFilePath); - - if(!foundPaths) { - const code = fs.readFileSync(moduleFilePath, 'utf8'); - - foundPaths = this.findSideEffectsInImports(moduleFilePath, code); - } - - foundPaths = foundPaths || new Set(); - - this.checkedPaths.set(moduleFilePath, foundPaths); - - return foundPaths; - } - - findSideEffectsInImports(modulePath, code) { - const relativePathRegExp = /['"]\.?\.\/.+['"]/; - const isSideEffectImportRegExp = /^\s*import\s+['"]/ms; - - const imports = code.match(/^\s*import[^;]+;/mg) || []; - let foundPaths = new Set(); - - imports.filter((str) => relativePathRegExp.test(str)) - .forEach((str) => { - let importPath = str.match(relativePathRegExp)[0].replace(/(^['"]|['"]$)/g, ''); - - importPath = path.join(path.dirname(modulePath), importPath) + '.js'; - - if(!fs.existsSync(importPath)) { - importPath = importPath.replace(/\.js$/, '/index.js'); - } - - if(isSideEffectImportRegExp.test(str)) { - foundPaths.add(importPath); - } - - const isInLoop = this.recursiveHandlingPaths.has(importPath); - - if(!isInLoop) { - this.recursiveHandlingPaths.add(importPath); - - foundPaths = new Set([...foundPaths, ...this.findSideEffectsInModule(importPath)]); - - this.recursiveHandlingPaths.delete(importPath); - } - }); - - return foundPaths; - } -} - -module.exports = { - SideEffectFinder -}; diff --git a/packages/nx-infra-plugin/executors.json b/packages/nx-infra-plugin/executors.json index 6dcdf6cd6818..c235c8b68ce3 100644 --- a/packages/nx-infra-plugin/executors.json +++ b/packages/nx-infra-plugin/executors.json @@ -69,6 +69,11 @@ "implementation": "./src/executors/babel-transform/executor", "schema": "./src/executors/babel-transform/schema.json", "description": "Transform JavaScript/TypeScript files using Babel with configurable presets" + }, + "create-dual-mode-manifest": { + "implementation": "./src/executors/create-dual-mode-manifest/executor", + "schema": "./src/executors/create-dual-mode-manifest/schema.json", + "description": "Generate package.json files for dual-mode (ESM + CJS) package support" } } } diff --git a/packages/nx-infra-plugin/package.json b/packages/nx-infra-plugin/package.json index 7bd7404a1af6..8919cc7ac835 100644 --- a/packages/nx-infra-plugin/package.json +++ b/packages/nx-infra-plugin/package.json @@ -14,6 +14,7 @@ "dependencies": { "fs-extra": "11.2.0", "glob": "11.1.0", + "minimatch": "9.0.5", "normalize-path": "3.0.0", "lodash": "4.17.21", "rimraf": "3.0.2" @@ -69,6 +70,7 @@ "@types/normalize-path": "3.0.2", "@types/node": "18.19.130", "@types/lodash": "4.17.13", + "@types/minimatch": "5.1.2", "prettier": "catalog:tools", "ts-jest": "29.1.3", "typescript": "4.9.5" diff --git a/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.e2e.spec.ts b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.e2e.spec.ts new file mode 100644 index 000000000000..2b13b37dd718 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.e2e.spec.ts @@ -0,0 +1,198 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import executor from './executor'; +import { CreateDualModeManifestExecutorSchema } from './schema'; +import { createTempDir, cleanupTempDir, createMockContext } from '../../utils/test-utils'; +import { writeFileText, readFileText } from '../../utils'; + +describe('CreateDualModeManifest Executor E2E', () => { + let tempDir: string; + let context = createMockContext(); + let projectDir: string; + + beforeEach(async () => { + tempDir = createTempDir('nx-dual-mode-manifest-e2e-'); + context = createMockContext({ root: tempDir }); + projectDir = path.join(tempDir, 'packages', 'test-lib'); + fs.mkdirSync(projectDir, { recursive: true }); + + const esmDir = path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'esm'); + fs.mkdirSync(esmDir, { recursive: true }); + + const cjsDir = path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'cjs'); + fs.mkdirSync(cjsDir, { recursive: true }); + + const srcDir = path.join(projectDir, 'js'); + fs.mkdirSync(srcDir, { recursive: true }); + + await writeFileText( + path.join(esmDir, 'core.js'), + `export function coreFunction() { return 'core'; }`, + ); + + await writeFileText( + path.join(esmDir, 'utils.js'), + `export function utilFunction() { return 'util'; }`, + ); + + const esmSubDir = path.join(esmDir, 'ui'); + fs.mkdirSync(esmSubDir, { recursive: true }); + await writeFileText(path.join(esmSubDir, 'index.js'), `export { Button } from './button';`); + await writeFileText(path.join(esmSubDir, 'button.js'), `export const Button = () => {};`); + + await writeFileText( + path.join(cjsDir, 'core.js'), + `"use strict"; module.exports.coreFunction = function() { return 'core'; };`, + ); + await writeFileText( + path.join(cjsDir, 'utils.js'), + `"use strict"; module.exports.utilFunction = function() { return 'util'; };`, + ); + + const cjsSubDir = path.join(cjsDir, 'ui'); + fs.mkdirSync(cjsSubDir, { recursive: true }); + await writeFileText( + path.join(cjsSubDir, 'index.js'), + `"use strict"; var button = require('./button'); module.exports.Button = button.Button;`, + ); + await writeFileText( + path.join(cjsSubDir, 'button.js'), + `"use strict"; module.exports.Button = function() {};`, + ); + await writeFileText( + path.join(srcDir, 'core.d.ts'), + `export declare function coreFunction(): string;`, + ); + + const srcSubDir = path.join(srcDir, 'ui'); + fs.mkdirSync(srcSubDir, { recursive: true }); + }); + + afterEach(() => { + cleanupTempDir(tempDir); + }); + + describe('Main functionality', () => { + it('should create package.json files for each JS module', async () => { + const options: CreateDualModeManifestExecutorSchema = { + esmDir: './artifacts/transpiled-esm-npm/esm', + cjsDir: './artifacts/transpiled-esm-npm/cjs', + outputDir: './artifacts/transpiled-esm-npm', + srcDir: './js', + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const outputDir = path.join(projectDir, 'artifacts', 'transpiled-esm-npm'); + + expect(fs.existsSync(path.join(outputDir, 'core', 'package.json'))).toBe(true); + expect(fs.existsSync(path.join(outputDir, 'utils', 'package.json'))).toBe(true); + + expect(fs.existsSync(path.join(outputDir, 'ui', 'package.json'))).toBe(true); + + expect(fs.existsSync(path.join(outputDir, 'ui', 'button', 'package.json'))).toBe(true); + }, 30000); + + it('should include main, module, and sideEffects fields', async () => { + const options: CreateDualModeManifestExecutorSchema = { + esmDir: './artifacts/transpiled-esm-npm/esm', + cjsDir: './artifacts/transpiled-esm-npm/cjs', + outputDir: './artifacts/transpiled-esm-npm', + srcDir: './js', + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const packageJson = JSON.parse( + await readFileText( + path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'core', 'package.json'), + ), + ); + + expect(packageJson.main).toBeDefined(); + expect(packageJson.main).toContain('cjs'); + expect(packageJson.main).toContain('core.js'); + + expect(packageJson.module).toBeDefined(); + expect(packageJson.module).toContain('esm'); + expect(packageJson.module).toContain('core.js'); + + expect(packageJson.sideEffects).toBe(false); + }, 30000); + + it('should include typings field when .d.ts file exists', async () => { + const options: CreateDualModeManifestExecutorSchema = { + esmDir: './artifacts/transpiled-esm-npm/esm', + cjsDir: './artifacts/transpiled-esm-npm/cjs', + outputDir: './artifacts/transpiled-esm-npm', + srcDir: './js', + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const corePackageJson = JSON.parse( + await readFileText( + path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'core', 'package.json'), + ), + ); + expect(corePackageJson.typings).toBeDefined(); + expect(corePackageJson.typings).toContain('core.d.ts'); + + const utilsPackageJson = JSON.parse( + await readFileText( + path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'utils', 'package.json'), + ), + ); + expect(utilsPackageJson.typings).toBeUndefined(); + }, 30000); + }); + + describe('Index file handling', () => { + it('should place package.json in same directory for index.js files', async () => { + const options: CreateDualModeManifestExecutorSchema = { + esmDir: './artifacts/transpiled-esm-npm/esm', + cjsDir: './artifacts/transpiled-esm-npm/cjs', + outputDir: './artifacts/transpiled-esm-npm', + srcDir: './js', + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const indexPackageJson = JSON.parse( + await readFileText( + path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'ui', 'package.json'), + ), + ); + + expect(indexPackageJson.main).toBeDefined(); + expect(indexPackageJson.module).toBeDefined(); + }, 30000); + }); + + describe('Generated .d.ts files', () => { + it('should include typings for generated .d.ts files', async () => { + const options: CreateDualModeManifestExecutorSchema = { + esmDir: './artifacts/transpiled-esm-npm/esm', + cjsDir: './artifacts/transpiled-esm-npm/cjs', + outputDir: './artifacts/transpiled-esm-npm', + srcDir: './js', + generatedDtsFiles: ['utils.d.ts'], + }; + + const result = await executor(options, context); + expect(result.success).toBe(true); + + const utilsPackageJson = JSON.parse( + await readFileText( + path.join(projectDir, 'artifacts', 'transpiled-esm-npm', 'utils', 'package.json'), + ), + ); + expect(utilsPackageJson.typings).toBeDefined(); + expect(utilsPackageJson.typings).toContain('utils.d.ts'); + }, 30000); + }); +}); diff --git a/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.ts b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.ts new file mode 100644 index 000000000000..0ce9a4e6c8c3 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/executor.ts @@ -0,0 +1,219 @@ +import { PromiseExecutor, logger } from '@nx/devkit'; +import * as path from 'path'; +import { glob } from 'glob'; +import { minimatch } from 'minimatch'; +import { CreateDualModeManifestExecutorSchema } from './schema'; +import { SideEffectFinder } from './side-effect-finder'; +import { resolveProjectPath, normalizeGlobPathForWindows } from '../../utils/path-resolver'; +import { isWindowsOS } from '../../utils/common'; +import { logError } from '../../utils/error-handler'; +import { exists, ensureDir, writeFileText } from '../../utils/file-operations'; + +const ERROR_MESSAGES = { + ESM_DIR_NOT_FOUND: (dir: string) => `ESM directory does not exist: ${dir}`, + CJS_DIR_NOT_FOUND: (dir: string) => `CJS directory does not exist: ${dir}`, + FAILED_TO_CREATE_MANIFEST: 'Failed to create dual-mode manifest files', +} as const; + +function normalizePackagePath(p: string): string { + return p.replace(/\\/g, '/'); +} + +function createModuleConfig( + fileName: string, + fileDir: string, + esmFilePath: string, + srcDir: string, + generatedDtsFiles: string[], + sideEffectFinder: SideEffectFinder, +): string { + const isIndex = fileName === 'index.js'; + const relative = path.join('./', fileDir.replace(srcDir, ''), fileName); + const currentPath = isIndex ? path.join(relative, '../') : relative; + + const esmFile = path.relative(currentPath, path.join('./esm', relative)); + const cjsFile = path.relative(currentPath, path.join('./cjs', relative)); + + const dtsRelative = relative.replace(/\.js$/, '.d.ts'); + const realDtsPath = path.join(fileDir, fileName.replace(/\.js$/, '.d.ts')); + const hasGeneratedDts = generatedDtsFiles.includes( + normalizePackagePath(dtsRelative.replace(/^\.\//, '')), + ); + + const relativeEsmBase = normalizePackagePath(esmFile).match(/^.*\/esm\//)?.[0] || './esm/'; + let sideEffectFiles: string[] | false = false; + + try { + const moduleSideEffects = sideEffectFinder.getModuleSideEffectFiles(esmFilePath); + if (moduleSideEffects.length > 0) { + sideEffectFiles = moduleSideEffects.map((importPath) => + importPath.replace(/^.*\/esm\//, relativeEsmBase), + ); + } + } catch (e) { + logger.verbose(`Side effect analysis failed for ${esmFilePath}: ${e}`); + } + + const result: Record = { + sideEffects: sideEffectFiles, + main: normalizePackagePath(cjsFile), + module: normalizePackagePath(esmFile), + }; + + const hasRealDts = require('fs').existsSync(realDtsPath); + const hasDts = hasRealDts || hasGeneratedDts; + + if (hasDts) { + const typingFile = fileName.replace(/\.js$/, '.d.ts'); + result['typings'] = `${isIndex ? './' : '../'}${typingFile}`; + } + + return JSON.stringify(result, null, 2); +} + +function getPackageJsonOutputPath( + fileName: string, + fileDir: string, + srcDir: string, + outputDir: string, +): string { + const relativePath = fileDir.replace(srcDir, ''); + const baseName = path.basename(fileName, '.js'); + const isIndex = fileName === 'index.js'; + + if (isIndex) { + return path.join(outputDir, relativePath, 'package.json'); + } else { + return path.join(outputDir, relativePath, baseName, 'package.json'); + } +} + +async function validateDirectories(esmDir: string, cjsDir: string): Promise { + if (!(await exists(esmDir))) { + throw new Error(ERROR_MESSAGES.ESM_DIR_NOT_FOUND(esmDir)); + } + + if (!(await exists(cjsDir))) { + throw new Error(ERROR_MESSAGES.CJS_DIR_NOT_FOUND(cjsDir)); + } +} + +async function discoverJsFiles(esmDir: string): Promise { + const pattern = path.join(esmDir, '**/*.js'); + const globPattern = isWindowsOS() ? normalizeGlobPathForWindows(pattern) : pattern; + + return glob(globPattern, { + nodir: true, + ignore: ['**/node_modules/**'], + }); +} + +function shouldExcludeFile(relativeFilePath: string, excludePatterns: string[]): boolean { + return excludePatterns.some((pattern) => minimatch(relativeFilePath, pattern, { dot: true })); +} + +async function processFile( + file: string, + esmDir: string, + srcDir: string, + outputDir: string, + excludePatterns: string[], + generatedDtsFiles: string[], + sideEffectFinder: SideEffectFinder, +): Promise { + const fileName = path.basename(file); + const fileDir = path.dirname(file); + + const relativeFromEsm = path.relative(esmDir, fileDir); + const relativeFilePath = normalizePackagePath(path.join(relativeFromEsm, fileName)); + + if (shouldExcludeFile(relativeFilePath, excludePatterns)) { + logger.verbose(`Skipping excluded file: ${relativeFilePath}`); + return false; + } + + const correspondingSrcDir = path.join(srcDir, relativeFromEsm); + + const moduleConfig = createModuleConfig( + fileName, + correspondingSrcDir, + file, + srcDir, + generatedDtsFiles, + sideEffectFinder, + ); + + const packageJsonPath = getPackageJsonOutputPath( + fileName, + correspondingSrcDir, + srcDir, + outputDir, + ); + + await ensureDir(path.dirname(packageJsonPath)); + await writeFileText(packageJsonPath, moduleConfig); + + logger.verbose(`Created: ${path.relative(outputDir, packageJsonPath)}`); + return true; +} + +const runExecutor: PromiseExecutor = async ( + options, + context, +) => { + const projectRoot = resolveProjectPath(context); + + const esmDir = path.resolve(projectRoot, options.esmDir); + const cjsDir = path.resolve(projectRoot, options.cjsDir); + const outputDir = path.resolve(projectRoot, options.outputDir); + const srcDir = path.resolve(projectRoot, options.srcDir); + const excludePatterns = options.excludePatterns || []; + const generatedDtsFiles = options.generatedDtsFiles || []; + + logger.verbose(`Creating dual-mode manifest files...`); + logger.verbose(` ESM dir: ${esmDir}`); + logger.verbose(` CJS dir: ${cjsDir}`); + logger.verbose(` Output dir: ${outputDir}`); + logger.verbose(` Source dir: ${srcDir}`); + logger.verbose(` Exclude patterns: ${excludePatterns.join(', ') || '(none)'}`); + + try { + await validateDirectories(esmDir, cjsDir); + + const files = await discoverJsFiles(esmDir); + + if (files.length === 0) { + logger.warn(`No JS files found in ESM directory: ${esmDir}`); + return { success: true }; + } + + logger.verbose(`Found ${files.length} JS files to process`); + + const sideEffectFinder = new SideEffectFinder(); + let createdCount = 0; + + for (const file of files) { + const created = await processFile( + file, + esmDir, + srcDir, + outputDir, + excludePatterns, + generatedDtsFiles, + sideEffectFinder, + ); + if (created) { + createdCount++; + } + } + + logger.info(`Created ${createdCount} package.json manifest files`); + + return { success: true }; + } catch (error) { + logError(ERROR_MESSAGES.FAILED_TO_CREATE_MANIFEST, error); + return { success: false }; + } +}; + +export default runExecutor; diff --git a/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.json b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.json new file mode 100644 index 000000000000..333abe0493c0 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/schema", + "type": "object", + "title": "Create Dual-Mode Manifest Executor", + "description": "Generate package.json files for dual-mode (ESM + CJS) package support with main, module, typings, and sideEffects fields", + "properties": { + "esmDir": { + "type": "string", + "description": "Directory containing ESM transpiled files (e.g., './artifacts/transpiled-esm-npm/esm')" + }, + "cjsDir": { + "type": "string", + "description": "Directory containing CJS transpiled files (e.g., './artifacts/transpiled-esm-npm/cjs')" + }, + "outputDir": { + "type": "string", + "description": "Base output directory where package.json files will be created (e.g., './artifacts/transpiled-esm-npm')" + }, + "srcDir": { + "type": "string", + "description": "Source directory for .d.ts file lookup (e.g., './js')" + }, + "excludePatterns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Glob patterns to exclude from processing (matched against relative path from esmDir)" + }, + "generatedDtsFiles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of generated .d.ts files that don't exist in srcDir but are generated during build (paths relative to srcDir)" + } + }, + "required": ["esmDir", "cjsDir", "outputDir", "srcDir"], + "additionalProperties": false +} diff --git a/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.ts b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.ts new file mode 100644 index 000000000000..8f9bf7159e78 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/schema.ts @@ -0,0 +1,8 @@ +export interface CreateDualModeManifestExecutorSchema { + esmDir: string; + cjsDir: string; + outputDir: string; + srcDir: string; + excludePatterns?: string[]; + generatedDtsFiles?: string[]; +} diff --git a/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/side-effect-finder.ts b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/side-effect-finder.ts new file mode 100644 index 000000000000..f2bc64430fb0 --- /dev/null +++ b/packages/nx-infra-plugin/src/executors/create-dual-mode-manifest/side-effect-finder.ts @@ -0,0 +1,75 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export class SideEffectFinder { + private checkedPaths: Map> = new Map(); + private recursiveHandlingPaths: Set = new Set(); + + getModuleSideEffectFiles(moduleFilePath: string): string[] { + try { + const moduleSideEffectFiles = [...this.findSideEffectsInModule(moduleFilePath)].map( + (importPath) => importPath.replace(/\\/g, '/'), + ); + return moduleSideEffectFiles; + } catch (e) { + const message = e instanceof Error ? e.message : String(e); + throw new Error( + `Exception while checking side effects in ${moduleFilePath}\nException: ${message}`, + ); + } + } + + private findSideEffectsInModule(moduleFilePath: string): Set { + let foundPaths = this.checkedPaths.get(moduleFilePath); + + if (!foundPaths) { + if (!fs.existsSync(moduleFilePath)) { + return new Set(); + } + + const code = fs.readFileSync(moduleFilePath, 'utf8'); + foundPaths = this.findSideEffectsInImports(moduleFilePath, code); + } + + foundPaths = foundPaths || new Set(); + this.checkedPaths.set(moduleFilePath, foundPaths); + + return foundPaths; + } + + private findSideEffectsInImports(modulePath: string, code: string): Set { + const relativePathRegExp = /['"]\.?\.\/.+['"]/; + const isSideEffectImportRegExp = /^\s*import\s+['"]/ms; + + const imports = code.match(/^\s*import[^;]+;/gm) || []; + let foundPaths = new Set(); + + imports + .filter((str) => relativePathRegExp.test(str)) + .forEach((str) => { + const match = str.match(relativePathRegExp); + if (!match) return; + + let importPath = match[0].replace(/(^['"]|['"]$)/g, ''); + importPath = path.join(path.dirname(modulePath), importPath) + '.js'; + + if (!fs.existsSync(importPath)) { + importPath = importPath.replace(/\.js$/, '/index.js'); + } + + if (isSideEffectImportRegExp.test(str)) { + foundPaths.add(importPath); + } + + const isInLoop = this.recursiveHandlingPaths.has(importPath); + + if (!isInLoop) { + this.recursiveHandlingPaths.add(importPath); + foundPaths = new Set([...foundPaths, ...this.findSideEffectsInModule(importPath)]); + this.recursiveHandlingPaths.delete(importPath); + } + }); + + return foundPaths; + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31bcb6cd9795..e7a6d4c32f49 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2273,6 +2273,9 @@ importers: lodash: specifier: 4.17.21 version: 4.17.21 + minimatch: + specifier: 9.0.5 + version: 9.0.5 ng-packagr: specifier: '>=19.0.0' version: 19.2.2(@angular/compiler-cli@21.0.8(@angular/compiler@21.0.8)(typescript@4.9.5))(tslib@2.8.1)(typescript@4.9.5) @@ -2295,6 +2298,9 @@ importers: '@types/lodash': specifier: 4.17.13 version: 4.17.13 + '@types/minimatch': + specifier: 5.1.2 + version: 5.1.2 '@types/node': specifier: 18.19.130 version: 18.19.130 From 6cb7bf768d09a51a2bf3e0323c58a126fc5869c4 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Fri, 23 Jan 2026 17:36:59 +0200 Subject: [PATCH 25/30] feat(nx-infra-plugin): enhance build-typescript executor with new options --- packages/nx-infra-plugin/package.json | 3 +- .../build-typescript/executor.e2e.spec.ts | 121 ++++---- .../executors/build-typescript/executor.ts | 291 +++++++++++++----- .../executors/build-typescript/schema.json | 19 +- .../src/executors/build-typescript/schema.ts | 2 + pnpm-lock.yaml | 3 + 6 files changed, 308 insertions(+), 131 deletions(-) diff --git a/packages/nx-infra-plugin/package.json b/packages/nx-infra-plugin/package.json index 8919cc7ac835..ccefc5797919 100644 --- a/packages/nx-infra-plugin/package.json +++ b/packages/nx-infra-plugin/package.json @@ -17,7 +17,8 @@ "minimatch": "9.0.5", "normalize-path": "3.0.0", "lodash": "4.17.21", - "rimraf": "3.0.2" + "rimraf": "3.0.2", + "tsc-alias": "1.8.10" }, "peerDependencies": { "@babel/core": ">=7.0.0", diff --git a/packages/nx-infra-plugin/src/executors/build-typescript/executor.e2e.spec.ts b/packages/nx-infra-plugin/src/executors/build-typescript/executor.e2e.spec.ts index 11c77f2b9e7b..46f72350a0f9 100644 --- a/packages/nx-infra-plugin/src/executors/build-typescript/executor.e2e.spec.ts +++ b/packages/nx-infra-plugin/src/executors/build-typescript/executor.e2e.spec.ts @@ -8,24 +8,27 @@ import { writeFileText, writeJson, readFileText } from '../../utils'; describe('BuildTypescriptExecutor E2E', () => { let tempDir: string; let context = createMockContext(); + let projectDir: string; beforeEach(async () => { tempDir = createTempDir('nx-build-ts-e2e-'); context = createMockContext({ root: tempDir }); - - const projectDir = path.join(tempDir, 'packages', 'test-lib'); + projectDir = path.join(tempDir, 'packages', 'test-lib'); const srcDir = path.join(projectDir, 'src'); fs.mkdirSync(srcDir, { recursive: true }); + const utilsDir = path.join(srcDir, 'utils'); + fs.mkdirSync(utilsDir, { recursive: true }); + await writeFileText( - path.join(srcDir, 'index.ts'), - `export function hello(name: string): string {\n return \`Hello, \${name}!\`;\n}\n`, + path.join(utilsDir, 'index.ts'), + `export const add = (a: number, b: number): number => a + b;\n`, ); await writeFileText( - path.join(srcDir, 'utils.ts'), - `export const add = (a: number, b: number): number => a + b;\n`, + path.join(srcDir, 'index.ts'), + `import { add } from '@lib/utils';\nexport function hello(name: string): string {\n return \`Hello, \${name}! Sum: \${add(1, 2)}\`;\n}\n`, ); fs.mkdirSync(path.join(srcDir, '__tests__'), { recursive: true }); @@ -46,6 +49,10 @@ describe('BuildTypescriptExecutor E2E', () => { strict: true, esModuleInterop: true, skipLibCheck: true, + baseUrl: './src', + paths: { + '@lib/*': ['./*'], + }, }, include: ['src/**/*'], exclude: ['**/*.spec.ts', '**/__tests__/**'], @@ -63,6 +70,10 @@ describe('BuildTypescriptExecutor E2E', () => { strict: true, esModuleInterop: true, skipLibCheck: true, + baseUrl: './src', + paths: { + '@lib/*': ['./*'], + }, }, include: ['src/**/*'], exclude: ['**/*.spec.ts', '**/__tests__/**'], @@ -73,92 +84,92 @@ describe('BuildTypescriptExecutor E2E', () => { cleanupTempDir(tempDir); }); - describe('ESM build', () => { - it('should compile TypeScript to ESM successfully', async () => { + describe.each([ + { + moduleType: 'esm' as const, + tsconfig: './tsconfig.esm.json', + outDir: './npm/esm', + expectedExport: 'export', + unexpectedExport: 'module.exports', + }, + { + moduleType: 'cjs' as const, + tsconfig: './tsconfig.json', + outDir: './npm/cjs', + expectedExport: 'exports', + unexpectedExport: 'export function', + }, + ])('$moduleType build', ({ moduleType, tsconfig, outDir, expectedExport, unexpectedExport }) => { + it('should compile and exclude test files', async () => { const options: BuildTypescriptExecutorSchema = { - module: 'esm', + module: moduleType, srcPattern: './src/**/*.{ts,tsx}', excludePatterns: ['./src/**/__tests__/**/*'], - tsconfig: './tsconfig.esm.json', - outDir: './npm/esm', + tsconfig, + outDir, }; const result = await executor(options, context); expect(result.success).toBe(true); - const projectDir = path.join(tempDir, 'packages', 'test-lib'); - const outDir = path.join(projectDir, 'npm', 'esm'); + const outputDir = path.join(projectDir, outDir.replace('./', '')); + + expect(fs.existsSync(path.join(outputDir, 'index.js'))).toBe(true); + expect(fs.existsSync(path.join(outputDir, 'utils', 'index.js'))).toBe(true); + expect(fs.existsSync(path.join(outputDir, 'index.d.ts'))).toBe(true); - expect(fs.existsSync(path.join(outDir, 'index.js'))).toBe(true); - expect(fs.existsSync(path.join(outDir, 'utils.js'))).toBe(true); + expect(fs.existsSync(path.join(outputDir, '__tests__'))).toBe(false); - expect(fs.existsSync(path.join(outDir, 'index.d.ts'))).toBe(true); - expect(fs.existsSync(path.join(outDir, 'utils.d.ts'))).toBe(true); + const indexContent = await readFileText(path.join(outputDir, 'index.js')); + expect(indexContent).toContain(expectedExport); + expect(indexContent).not.toContain(unexpectedExport); - const indexContent = await readFileText(path.join(outDir, 'index.js')); - expect(indexContent).toContain('export'); - expect(indexContent).not.toContain('module.exports'); + expect(indexContent).toContain('@lib/utils'); }, 10000); - }); - describe('CJS build', () => { - it('should compile TypeScript to CommonJS successfully', async () => { + it('should resolve path aliases when resolvePaths is enabled', async () => { const options: BuildTypescriptExecutorSchema = { - module: 'cjs', + module: moduleType, srcPattern: './src/**/*.{ts,tsx}', excludePatterns: ['./src/**/__tests__/**/*'], - tsconfig: './tsconfig.json', - outDir: './npm/cjs', + tsconfig, + outDir, + resolvePaths: true, + resolvePathsBaseDir: './src', }; const result = await executor(options, context); expect(result.success).toBe(true); - const projectDir = path.join(tempDir, 'packages', 'test-lib'); - const outDir = path.join(projectDir, 'npm', 'cjs'); - - expect(fs.existsSync(path.join(outDir, 'index.js'))).toBe(true); - expect(fs.existsSync(path.join(outDir, 'utils.js'))).toBe(true); + const outputDir = path.join(projectDir, outDir.replace('./', '')); + const indexContent = await readFileText(path.join(outputDir, 'index.js')); - const indexContent = await readFileText(path.join(outDir, 'index.js')); - expect(indexContent).toContain('exports'); - expect(indexContent).not.toContain('export function'); + expect(indexContent).not.toContain('@lib/utils'); + expect(indexContent).toContain('./utils'); }, 10000); }); describe('Error handling', () => { - it('should handle missing tsconfig file', async () => { - const projectDir = path.join(tempDir, 'packages', 'test-lib'); - + it('should fail when tsconfig is missing', async () => { fs.unlinkSync(path.join(projectDir, 'tsconfig.esm.json')); - const options: BuildTypescriptExecutorSchema = { - module: 'esm', - tsconfig: './tsconfig.esm.json', - }; - - const result = await executor(options, context); + const result = await executor({ tsconfig: './tsconfig.esm.json' }, context); expect(result.success).toBe(false); }); - it('should handle empty source directory', async () => { - const projectDir = path.join(tempDir, 'packages', 'test-lib'); - - fs.rmSync(path.join(projectDir, 'src'), { recursive: true, force: true }); - fs.mkdirSync(path.join(projectDir, 'src')); - - fs.writeFileSync(path.join(projectDir, 'src', 'empty.ts'), ''); + it('should fail when no files match pattern', async () => { + const result = await executor({ srcPattern: './nonexistent/**/*.ts' }, context); - const options: BuildTypescriptExecutorSchema = { - module: 'esm', - }; + expect(result.success).toBe(false); + }); - const result = await executor(options, context); + it('should fail when resolvePaths is true but resolvePathsBaseDir is missing', async () => { + const result = await executor({ resolvePaths: true }, context); - expect(result).toHaveProperty('success'); + expect(result.success).toBe(false); }); }); }); diff --git a/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts b/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts index 0cf58cd70a33..dd26950c6c45 100644 --- a/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts +++ b/packages/nx-infra-plugin/src/executors/build-typescript/executor.ts @@ -2,42 +2,160 @@ import { PromiseExecutor, logger } from '@nx/devkit'; import * as ts from 'typescript'; import * as path from 'path'; import { glob } from 'glob'; +import { prepareSingleFileReplaceTscAliasPaths } from 'tsc-alias'; import { BuildTypescriptExecutorSchema } from './schema'; import { TsConfig, CompilerOptions } from '../../utils/types'; import { resolveProjectPath, normalizeGlobPathForWindows } from '../../utils/path-resolver'; import { isWindowsOS } from '../../utils/common'; import { logError } from '../../utils/error-handler'; -import { readFileText, exists, ensureDir } from '../../utils/file-operations'; +import { exists, ensureDir, writeFileText } from '../../utils/file-operations'; -const MODULE_TYPE_ESM = 'esm'; -const MODULE_TYPE_CJS = 'cjs'; +type AliasTranspileFunc = (filePath: string, fileContents: string) => string; -const DEFAULT_MODULE_TYPE = MODULE_TYPE_ESM; -const DEFAULT_TSCONFIG_CJS = './tsconfig.json'; -const DEFAULT_TSCONFIG_ESM = './tsconfig.esm.json'; -const DEFAULT_OUT_DIR_CJS = './npm/cjs'; -const DEFAULT_OUT_DIR_ESM = './npm/esm'; +const DEFAULT_MODULE_TYPE = 'esm'; +const DEFAULT_TSCONFIG = './tsconfig.esm.json'; +const DEFAULT_OUT_DIR = './npm/esm'; const DEFAULT_SRC_PATTERN = './src/**/*.{ts,tsx}'; -const ERROR_COMPILATION_FAILED = 'Compilation failed'; - const NEWLINE_CHAR = '\n'; +const ERROR_MESSAGES = { + COMPILATION_FAILED: 'Compilation failed', + TSCONFIG_NOT_FOUND: (filePath: string) => `TypeScript config file not found: ${filePath}`, + TSCONFIG_PARSE_ERROR: (message: string) => `Error reading tsconfig: ${message}`, + NO_SOURCE_FILES: (pattern: string) => `No source files matched pattern: ${pattern}`, + RESOLVE_PATHS_REQUIRES_BASE_DIR: 'resolvePathsBaseDir is required when resolvePaths is enabled', + BUILD_FAILED: (moduleType: string) => `Failed to build ${moduleType}`, +} as const; + +interface ResolvedConfig { + projectRoot: string; + moduleType: string; + tsconfigPath: string; + outDir: string; + srcPattern: string; + excludePatterns: string[]; + resolvePaths: boolean; + resolvePathsBaseDir?: string; +} + +interface EmitProgramResult { + success: boolean; +} + +interface EmitOptions { + aliasTranspileFunc?: AliasTranspileFunc; + outDir: string; + aliasPath?: string; +} + +function resolveExecutorConfig( + options: BuildTypescriptExecutorSchema, + context: Parameters>[1], +): ResolvedConfig { + const projectRoot = resolveProjectPath(context); + + return { + projectRoot, + moduleType: options.module || DEFAULT_MODULE_TYPE, + tsconfigPath: path.join(projectRoot, options.tsconfig || DEFAULT_TSCONFIG), + outDir: path.join(projectRoot, options.outDir || DEFAULT_OUT_DIR), + srcPattern: options.srcPattern || DEFAULT_SRC_PATTERN, + excludePatterns: options.excludePatterns || [], + resolvePaths: options.resolvePaths ?? false, + resolvePathsBaseDir: options.resolvePathsBaseDir + ? path.join(projectRoot, options.resolvePathsBaseDir) + : undefined, + }; +} + +function validateOptions(config: ResolvedConfig): void { + if (config.resolvePaths && !config.resolvePathsBaseDir) { + throw new Error(ERROR_MESSAGES.RESOLVE_PATHS_REQUIRES_BASE_DIR); + } +} + +async function createAliasTranspileFunc( + tsconfigPath: string, + aliasRoot: string, +): Promise { + const transpileFunc = await prepareSingleFileReplaceTscAliasPaths({ + configFile: tsconfigPath, + outDir: aliasRoot, + }); + + return (filePath: string, fileContents: string): string => { + return transpileFunc({ fileContents, filePath }); + }; +} + async function loadTsConfig( tsconfigPath: string, ): Promise<{ content: TsConfig; compilerOptions: CompilerOptions }> { if (!(await exists(tsconfigPath))) { - throw new Error(`TypeScript config file not found: ${tsconfigPath}`); + throw new Error(ERROR_MESSAGES.TSCONFIG_NOT_FOUND(tsconfigPath)); } - const tsconfigContentRaw = await readFileText(tsconfigPath); - const content = JSON.parse(tsconfigContentRaw) as TsConfig; + const { config, error } = ts.readConfigFile(tsconfigPath, ts.sys.readFile); + + if (error) { + const message = ts.flattenDiagnosticMessageText(error.messageText, NEWLINE_CHAR); + throw new Error(ERROR_MESSAGES.TSCONFIG_PARSE_ERROR(message)); + } + + const content = config as TsConfig; return { content, compilerOptions: content.compilerOptions || {}, }; } +async function resolveSourceFiles( + projectRoot: string, + srcPattern: string, + excludePatterns: string[], +): Promise { + const globPattern = isWindowsOS() + ? normalizeGlobPathForWindows(path.join(projectRoot, srcPattern)) + : path.join(projectRoot, srcPattern); + + const resolvedExcludes = excludePatterns.map((pattern) => { + const result = path.join(projectRoot, pattern); + return isWindowsOS() ? normalizeGlobPathForWindows(result) : result; + }); + + const files = await glob(globPattern, { + absolute: true, + nodir: true, + ignore: resolvedExcludes, + }); + + if (files.length === 0) { + throw new Error(ERROR_MESSAGES.NO_SOURCE_FILES(srcPattern)); + } + + return files; +} + +function buildCompilerOptions( + tsconfigContent: TsConfig, + tsconfigPath: string, + outDir: string, + resolvePaths: boolean, +): ts.CompilerOptions { + const parsedConfig = ts.parseJsonConfigFileContent( + tsconfigContent, + ts.sys, + path.dirname(tsconfigPath), + ); + + return { + ...parsedConfig.options, + outDir, + paths: resolvePaths ? parsedConfig.options.paths : {}, + }; +} + function formatDiagnostics(diagnostics: ts.Diagnostic[]): string[] { return diagnostics.map((diagnostic) => { if (diagnostic.file) { @@ -49,82 +167,113 @@ function formatDiagnostics(diagnostics: ts.Diagnostic[]): string[] { }); } -function compile(sourceFiles: string[], compilerOptions: ts.CompilerOptions): ts.Program { - return ts.createProgram(sourceFiles, compilerOptions); +async function emitWithAliasResolution( + program: ts.Program, + options: EmitOptions, +): Promise<{ success: boolean; diagnostics: ts.Diagnostic[] }> { + const { aliasTranspileFunc, outDir, aliasPath } = options; + const emittedFiles: Array<{ path: string; content: string }> = []; + + const result = program.emit(undefined, (filePath, fileData) => { + let finalContent = fileData; + + if (aliasTranspileFunc && aliasPath) { + const normalizedFilePath = filePath.replace(outDir, aliasPath); + finalContent = aliasTranspileFunc(normalizedFilePath, fileData); + } + + emittedFiles.push({ path: filePath, content: finalContent }); + }); + + for (const file of emittedFiles) { + const dir = path.dirname(file.path); + await ensureDir(dir); + await writeFileText(file.path, file.content); + } + + const diagnostics = ts.getPreEmitDiagnostics(program).concat(result.diagnostics); + return { success: !result.emitSkipped, diagnostics }; } -const runExecutor: PromiseExecutor = async (options, context) => { - const absoluteProjectRoot = resolveProjectPath(context); - const module = options.module || DEFAULT_MODULE_TYPE; +async function emitWithPathAliasResolution( + program: ts.Program, + config: ResolvedConfig, +): Promise { + const aliasTranspileFunc = await createAliasTranspileFunc( + config.tsconfigPath, + config.resolvePathsBaseDir!, + ); - const defaultTsconfigPath = - module === MODULE_TYPE_CJS ? DEFAULT_TSCONFIG_CJS : DEFAULT_TSCONFIG_ESM; - const tsconfigPath = path.join(absoluteProjectRoot, options.tsconfig || defaultTsconfigPath); + logger.verbose(`Path alias resolution enabled with base dir: ${config.resolvePathsBaseDir}`); - const defaultOutDir = module === MODULE_TYPE_CJS ? DEFAULT_OUT_DIR_CJS : DEFAULT_OUT_DIR_ESM; - const outDir = path.join(absoluteProjectRoot, options.outDir || defaultOutDir); + const { success, diagnostics } = await emitWithAliasResolution(program, { + aliasTranspileFunc, + outDir: config.outDir, + aliasPath: config.resolvePathsBaseDir, + }); + + if (!success) { + logger.error(ERROR_MESSAGES.COMPILATION_FAILED); + formatDiagnostics(diagnostics).forEach((msg) => logger.error(msg)); + } + + return { success }; +} + +function emitStandard(program: ts.Program): EmitProgramResult { + const result = program.emit(); + + if (result.emitSkipped) { + logger.error(ERROR_MESSAGES.COMPILATION_FAILED); + const diagnostics = ts.getPreEmitDiagnostics(program).concat(result.diagnostics); + formatDiagnostics(diagnostics).forEach((msg) => logger.error(msg)); + return { success: false }; + } + + return { success: true }; +} + +const runExecutor: PromiseExecutor = async (options, context) => { + const config = resolveExecutorConfig(options, context); try { - const { content: tsconfigContent, compilerOptions } = await loadTsConfig(tsconfigPath); - compilerOptions.outDir = outDir; - await ensureDir(outDir); - - const srcPattern = options.srcPattern || DEFAULT_SRC_PATTERN; - const globPattern = isWindowsOS() - ? normalizeGlobPathForWindows(path.join(absoluteProjectRoot, srcPattern)) - : path.join(absoluteProjectRoot, srcPattern); - - const excludePatterns = options.excludePatterns - ? options.excludePatterns.map((pattern) => { - const result = path.join(absoluteProjectRoot, pattern); - - if (isWindowsOS()) { - return normalizeGlobPathForWindows(result); - } - - return result; - }) - : []; - - const sourceFiles = await glob(globPattern, { - absolute: true, - nodir: true, - ignore: excludePatterns, - }); - - if (sourceFiles.length === 0) { - throw new Error(`No source files matched pattern: ${srcPattern}`); - } + validateOptions(config); - logger.verbose(`Building ${module.toUpperCase()} for ${sourceFiles.length} source files...`); + const { content: tsconfigContent, compilerOptions } = await loadTsConfig(config.tsconfigPath); + compilerOptions.outDir = config.outDir; + await ensureDir(config.outDir); - const parsedConfig = ts.parseJsonConfigFileContent( - tsconfigContent, - ts.sys, - path.dirname(tsconfigPath), + const sourceFiles = await resolveSourceFiles( + config.projectRoot, + config.srcPattern, + config.excludePatterns, ); - const finalCompilerOptions: ts.CompilerOptions = { - ...parsedConfig.options, - outDir: compilerOptions.outDir, - paths: {}, - }; + logger.verbose( + `Building ${config.moduleType.toUpperCase()} for ${sourceFiles.length} files...`, + ); - const program = compile(sourceFiles, finalCompilerOptions); - const result = program.emit(); + const finalCompilerOptions = buildCompilerOptions( + tsconfigContent, + config.tsconfigPath, + config.outDir, + config.resolvePaths, + ); - if (result.emitSkipped) { - logger.error(ERROR_COMPILATION_FAILED); - const diagnostics = ts.getPreEmitDiagnostics(program).concat(result.diagnostics); + const program = ts.createProgram(sourceFiles, finalCompilerOptions); + const emitResult = + config.resolvePaths && config.resolvePathsBaseDir + ? await emitWithPathAliasResolution(program, config) + : emitStandard(program); - formatDiagnostics(diagnostics).forEach((msg) => logger.error(msg)); + if (!emitResult.success) { return { success: false }; } - logger.verbose(`✓ ${module.toUpperCase()} build completed successfully`); + logger.verbose(`✓ ${config.moduleType.toUpperCase()} build completed successfully`); return { success: true }; } catch (error) { - logError(`Failed to build ${module.toUpperCase()}`, error); + logError(ERROR_MESSAGES.BUILD_FAILED(config.moduleType.toUpperCase()), error); return { success: false }; } }; diff --git a/packages/nx-infra-plugin/src/executors/build-typescript/schema.json b/packages/nx-infra-plugin/src/executors/build-typescript/schema.json index 4e4a6b930cca..69d9b88102ad 100644 --- a/packages/nx-infra-plugin/src/executors/build-typescript/schema.json +++ b/packages/nx-infra-plugin/src/executors/build-typescript/schema.json @@ -6,13 +6,13 @@ "properties": { "module": { "type": "string", - "description": "Target module format. 'esm' generates ES modules with import/export statements, 'cjs' generates CommonJS with require/module.exports. This affects output file structure, TypeScript compiler module settings, and determines the default tsconfig and output directory.", + "description": "Target module format", "enum": ["cjs", "esm"], "default": "esm" }, "srcPattern": { "type": "string", - "description": "Glob pattern for source files to include in compilation. Supports standard glob syntax with wildcards. Default pattern includes all .ts and .tsx files in src directory recursively.", + "description": "Glob pattern for source files to include in compilation. Supports standard glob syntax with wildcards.", "default": "./src/**/*.{ts,tsx}" }, "excludePatterns": { @@ -24,11 +24,22 @@ }, "tsconfig": { "type": "string", - "description": "Path to TypeScript configuration file relative to project root. If not specified, defaults to './tsconfig.json' for CJS builds or './tsconfig.esm.json' for ESM builds. The tsconfig should contain appropriate module and target settings for the desired output format." + "default": "./tsconfig.esm.json", + "description": "Path to TypeScript configuration file relative to project root." }, "outDir": { "type": "string", - "description": "Output directory path relative to project root where compiled JavaScript and declaration files will be written. If not specified, defaults to './npm/cjs' for CJS builds or './npm/esm' for ESM builds. Directory will be created if it doesn't exist." + "default": "./npm/esm", + "description": "Output directory path relative to project root where compiled JavaScript and declaration files will be written. Directory will be created if it doesn't exist." + }, + "resolvePaths": { + "type": "boolean", + "default": false, + "description": "Enable path alias resolution using tsc-alias. When true, transforms import paths like '@ts/*' to relative paths based on tsconfig paths configuration. Requires resolvePathsBaseDir to be set." + }, + "resolvePathsBaseDir": { + "type": "string", + "description": "Base directory for path alias resolution (used as aliasRoot for tsc-alias). Relative to project root. Required when resolvePaths is true. Example: './js' for DevExtreme's __internal TypeScript compilation." } }, "required": [], diff --git a/packages/nx-infra-plugin/src/executors/build-typescript/schema.ts b/packages/nx-infra-plugin/src/executors/build-typescript/schema.ts index 933163f7a5bc..1fa42424af72 100644 --- a/packages/nx-infra-plugin/src/executors/build-typescript/schema.ts +++ b/packages/nx-infra-plugin/src/executors/build-typescript/schema.ts @@ -4,4 +4,6 @@ export interface BuildTypescriptExecutorSchema { excludePatterns?: string[]; tsconfig?: string; outDir?: string; + resolvePaths?: boolean; + resolvePathsBaseDir?: string; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7a6d4c32f49..8e7e3478f58e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2285,6 +2285,9 @@ importers: rimraf: specifier: 3.0.2 version: 3.0.2 + tsc-alias: + specifier: 1.8.10 + version: 1.8.10 devDependencies: '@types/babel__core': specifier: 7.20.5 From f2ea395913aa2e2c7ea2d587172a49f0ec188b53 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 26 Jan 2026 13:56:23 +0200 Subject: [PATCH 26/30] chore(devextreme): replace gulp wrappers with native nx executors --- packages/devextreme/project.json | 35 ++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index bb9e851651a1..0fe94944bf82 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -142,10 +142,14 @@ } }, "build:ts:internal": { - "executor": "nx:run-commands", + "executor": "devextreme-nx-infra-plugin:build-typescript", "options": { - "command": "gulp ts-compile-internal", - "cwd": "{projectRoot}" + "srcPattern": "./js/__internal/**/*.{ts,tsx}", + "excludePatterns": ["./js/__internal/**/__tests__/**/*"], + "tsconfig": "./js/__internal/tsconfig.json", + "outDir": "./artifacts/dist_ts", + "resolvePaths": true, + "resolvePathsBaseDir": "./js" }, "inputs": [ "{projectRoot}/js/__internal/**/*.{ts,tsx}", @@ -321,10 +325,29 @@ "cache": true }, "build:npm:dual-mode": { - "executor": "nx:run-commands", + "executor": "devextreme-nx-infra-plugin:create-dual-mode-manifest", "options": { - "command": "cross-env BUILD_ESM_PACKAGE=true gulp esm-dual-mode-manifests", - "cwd": "{projectRoot}" + "esmDir": "./artifacts/transpiled-esm-npm/esm", + "cjsDir": "./artifacts/transpiled-esm-npm/cjs", + "outputDir": "./artifacts/transpiled-esm-npm", + "srcDir": "./js", + "excludePatterns": [ + "__internal/**/*", + "viz/docs/**/*", + "bundles/**/*" + ], + "generatedDtsFiles": [ + "events/click.d.ts", + "events/contextmenu.d.ts", + "events/dblclick.d.ts", + "events/drag.d.ts", + "events/hold.d.ts", + "events/hover.d.ts", + "events/pointer.d.ts", + "events/swipe.d.ts", + "events/transform.d.ts", + "integration/jquery.d.ts" + ] }, "inputs": [ "{projectRoot}/artifacts/transpiled-esm-npm/esm/**/*", From 8f05d738ce88cb82c6bd78dd29405a86cca8b62f Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 26 Jan 2026 13:57:44 +0200 Subject: [PATCH 27/30] chore(devextreme): remove transpile code migrated to nx executors --- packages/devextreme/build/gulp/transpile.js | 110 -------------------- 1 file changed, 110 deletions(-) diff --git a/packages/devextreme/build/gulp/transpile.js b/packages/devextreme/build/gulp/transpile.js index d4d9f8297aff..30af8ab122ba 100644 --- a/packages/devextreme/build/gulp/transpile.js +++ b/packages/devextreme/build/gulp/transpile.js @@ -1,28 +1,18 @@ 'use strict'; const babel = require('gulp-babel'); -const flatMap = require('gulp-flatmap'); -const fs = require('fs'); const gulp = require('gulp'); - -const normalize = require('normalize-path'); const notify = require('gulp-notify'); const path = require('path'); const plumber = require('gulp-plumber'); -const rename = require('gulp-rename'); -const replace = require('gulp-replace'); const watch = require('gulp-watch'); const removeDebug = require('./compression-pipes.js').removeDebug; const ctx = require('./context.js'); const testsConfig = require('../../testing/tests.babelrc.json'); const transpileConfig = require('./transpile-config'); - const createTsCompiler = require('./typescript/compiler'); -const { SideEffectFinder } = require('./side-effects-finder'); - -const sideEffectFinder = new SideEffectFinder(); const src = [ 'js/**/*.*', '!js/**/*.d.ts', @@ -30,30 +20,6 @@ const src = [ '!js/__internal/**/*.*', ]; -const esmTranspileSrc = src.concat([ - '!js/viz/docs/**/*', - '!**/*.json' -]); - -const srcTsPattern = 'js/__internal/**/*.{ts,tsx}'; -const srcTsIgnorePatterns = [ - '**/__tests__/**/*' -]; - -const srcDir = path.join(process.cwd(), './js'); -const generatedTs = [ - 'events/click.d.ts', - 'events/contextmenu.d.ts', - 'events/dblclick.d.ts', - 'events/drag.d.ts', - 'events/hold.d.ts', - 'events/hover.d.ts', - 'events/pointer.d.ts', - 'events/swipe.d.ts', - 'events/transform.d.ts', - 'integration/jquery.d.ts' -]; - const TS_OUTPUT_BASE_DIR = 'artifacts/dist_ts'; const TS_COMPILER_CONFIG = { baseAbsPath: path.resolve(__dirname, '../..'), @@ -70,82 +36,6 @@ const TS_COMPILER_CONFIG = { }, }; -const createModuleConfig = (name, dir, filePath, dist) => { - const isIndex = name === 'index.js'; - const relative = path.join('./', dir.replace(srcDir, ''), name); - const currentPath = isIndex ? path.join(relative, '../') : relative; - const esmFile = path.relative(currentPath, path.join('./esm', relative)); - const esmFilePath = path.join(dist, './esm', dir.replace(srcDir, ''), name); - const cjsFile = path.relative(currentPath, path.join('./cjs', relative)); - const hasRealDTS = fs.existsSync(filePath.replace(/\.js$/, '.d.ts')); - const hasGeneratedDTS = generatedTs.indexOf(relative.replace(/\.js$/, '.d.ts')) !== -1; - const hasDTS = hasRealDTS || hasGeneratedDTS; - const relativeEsmBase = normalize(esmFile).match(/^.*\/esm\//)[0]; - const sideEffectFiles = sideEffectFinder.getModuleSideEffectFiles(esmFilePath) - .map((importPath) => importPath.replace(/^.*\/esm\//, relativeEsmBase)); - - const result = { - sideEffects: sideEffectFiles.length ? sideEffectFiles : false, - main: normalize(cjsFile), - module: normalize(esmFile), - }; - - if(hasDTS) { - const typingFile = name.replace(/\.js$/, '.d.ts'); - - result['typings'] = `${isIndex ? './' : '../'}${typingFile}`; - } - - return JSON.stringify(result, null, 2); -}; - -const transpileTs = (compiler, src) => { - const task = () => compiler - .compileTs(src, srcTsIgnorePatterns) - .pipe(gulp.dest(TS_OUTPUT_BASE_DIR)); - - task.displayName = 'transpile TS'; - return task; -}; - -gulp.task('ts-compile-internal', (done) => { - createTsCompiler(TS_COMPILER_CONFIG).then((compiler) => { - transpileTs(compiler, srcTsPattern)() - .on('end', done) - .on('error', done); - }); -}); - -gulp.task('esm-dual-mode-manifests', () => { - const dist = ctx.TRANSPILED_PROD_ESM_PATH; - return gulp - .src(esmTranspileSrc) - .pipe(flatMap((stream, file) => { - const filePath = file.path; - const parsedPath = path.parse(filePath); - const fileName = parsedPath.base; - const fileDir = parsedPath.dir; - - // NOTE: flatmap thinks that the 'js/viz/vector_map.utils' folder is a file. - if(file.extname === '.utils') return stream; - - return stream - .pipe(replace(/[\s\S]*/, createModuleConfig(fileName, fileDir, filePath, dist))) - .pipe(rename(fPath => { - const isIndexFile = parsedPath.base === 'index.js'; - const shouldBePlacedInSeparateDir = !isIndexFile; - - if(shouldBePlacedInSeparateDir) { - fPath.dirname = path.join(fPath.dirname, fPath.basename); - } - - fPath.basename = 'package'; - fPath.extname = '.json'; - })); - })) - .pipe(gulp.dest(dist)); -}); - const watchJsTask = () => { const watchTask = watch(src) .on('ready', () => console.log('transpile JS is watching for changes...')) From 1f6aed315b80b556e7ca9fbd41906eac922a32f7 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Tue, 27 Jan 2026 16:59:35 +0200 Subject: [PATCH 28/30] docs: update copilot-instructions.md --- .github/copilot-instructions.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 19d6a2b65412..74fc770575f8 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -71,7 +71,7 @@ pnpm install --frozen-lockfile devextreme-metadata/ # Metadata generation for wrappers devextreme-monorepo-tools/ # Internal tooling nx-infra-plugin/ # Custom Nx executors for build automation - workflows/ # Reusable CI/CD workflow configurations + workflows/ # Cross-package NX build orchestration (all:build-dev, all:build-testing) testcafe-models/ # TestCafe page object models /apps/ @@ -154,7 +154,7 @@ pnpm run clean **Build process includes:** 1. Localization generation (via `devextreme-nx-infra-plugin:localization` executor) 2. Component generation (Renovation architecture) -3. Transpilation (Babel) +3. Transpilation (via native NX executors: `babel-transform` for JS, `build-typescript` for TS) 4. Bundle creation (Webpack) - `bundle:debug` and `bundle:prod` targets 5. TypeScript declarations - `build:declarations` target 6. SCSS compilation (from devextreme-scss) @@ -186,13 +186,21 @@ The `packages/nx-infra-plugin` provides custom Nx executors for build automation | Executor | Description | |----------|-------------| -| `localization` | Generates localization message files and TypeScript CLDR data modules | -| `add-license-headers` | Adds license headers to source files | -| `copy-files` | Copies files with glob pattern support | -| `clean` | Cleans directories with exclude pattern support | -| `build-typescript` | Builds TypeScript projects | -| `generate-components` | Generates Angular/React/Vue wrapper components | -| `karma-multi-env` | Runs Karma tests across multiple Angular environments | +| `add-license-headers` | Adds DevExtreme license headers to compiled files with version information | +| `babel-transform` | Transforms JS/TS files using Babel with configurable presets, debug block removal, and extension renaming | +| `build-angular-library` | Builds Angular libraries using ng-packagr programmatically | +| `build-typescript` | Compiles TypeScript to CJS or ESM modules with configurable output format, tsconfig, and path alias resolution | +| `clean` | Removes directories and files with support for exclusion patterns | +| `concatenate-files` | Concatenates files with optional content extraction via regex, header/footer, and find/replace transforms | +| `copy-files` | Copies files and directories to specified destinations with glob pattern support | +| `create-dual-mode-manifest` | Generates package.json files for dual-mode (ESM + CJS) support with main, module, typings, and sideEffects | +| `generate-component-names` | Generates TypeScript file with component name constants for test automation | +| `generate-components` | Generates framework components (React/Vue/Angular) from DevExtreme metadata | +| `karma-multi-env` | Runs Karma tests across multiple Angular environments (client, server, hydration) | +| `localization` | Generates CLDR data and compiles localization message files from JSON to JavaScript | +| `pack-npm` | Creates npm packages using `pnpm pack` for distribution | +| `prepare-package-json` | Creates distribution-ready package.json with cleaned dependencies for npm publishing | +| `prepare-submodules` | Creates package.json entry points for submodule exports | **Example executor usage in project.json:** ```json From 417646d295e2ce01fb24e27acc0f2871c9820925 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 2 Feb 2026 09:34:43 +0200 Subject: [PATCH 29/30] fix(nx-infra-plugin): resolve babel-transform excludePatterns to absolute paths --- .../src/executors/babel-transform/executor.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts b/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts index bba985f5a9f0..8809328cdb68 100644 --- a/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts +++ b/packages/nx-infra-plugin/src/executors/babel-transform/executor.ts @@ -93,9 +93,15 @@ const runExecutor: PromiseExecutor = async (option const sourcePath = path.join(projectRoot, options.sourcePattern); const globPattern = isWindowsOS() ? normalizeGlobPathForWindows(sourcePath) : sourcePath; + const rawExcludePatterns = options.excludePatterns ?? []; + const excludePatterns = rawExcludePatterns.map((pattern) => { + const resolved = path.isAbsolute(pattern) ? pattern : path.join(projectRoot, pattern); + return isWindowsOS() ? normalizeGlobPathForWindows(resolved) : resolved; + }); + const sourceFiles = await glob(globPattern, { absolute: true, - ignore: options.excludePatterns || [], + ignore: excludePatterns, }); if (sourceFiles.length === 0) { From 52dfc197a82b56dd174d632cbbf9bf3852a26dc0 Mon Sep 17 00:00:00 2001 From: Adel Khamatov Date: Mon, 2 Feb 2026 09:34:48 +0200 Subject: [PATCH 30/30] fix(devextreme): include all config output dirs in target outputs for Nx caching --- packages/devextreme/project.json | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/devextreme/project.json b/packages/devextreme/project.json index 0fe94944bf82..cb95f6d0af11 100644 --- a/packages/devextreme/project.json +++ b/packages/devextreme/project.json @@ -179,7 +179,10 @@ "!{projectRoot}/js/**/*.d.ts", "!{projectRoot}/js/__internal/**/*" ], - "outputs": ["{projectRoot}/artifacts/transpiled"], + "outputs": [ + "{projectRoot}/artifacts/transpiled", + "{projectRoot}/artifacts/transpiled-renovation-npm" + ], "cache": true }, "copy:json:transpiled": { @@ -272,7 +275,10 @@ } }, "inputs": ["{projectRoot}/artifacts/dist_ts/__internal/**/*.{js,jsx}"], - "outputs": ["{projectRoot}/artifacts/transpiled/__internal"], + "outputs": [ + "{projectRoot}/artifacts/transpiled/__internal", + "{projectRoot}/artifacts/transpiled-renovation-npm/__internal" + ], "cache": true }, "build:npm:esm:internal": { @@ -321,7 +327,11 @@ } }, "inputs": ["{projectRoot}/build/bundle-templates/**/*.js"], - "outputs": ["{projectRoot}/artifacts/transpiled/bundles"], + "outputs": [ + "{projectRoot}/artifacts/transpiled/bundles", + "{projectRoot}/artifacts/transpiled-renovation-npm/bundles", + "{projectRoot}/artifacts/transpiled-esm-npm/bundles" + ], "cache": true }, "build:npm:dual-mode": {