From 90bd053c93b61f545aed45324d798f743713808b Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 17 Jan 2024 15:09:32 +0100 Subject: [PATCH 01/23] fix: only fall back to deprecated browserTarget attribute on older angular versions relates to #89 --- .github/workflows/node.js.yml | 2 +- package-lock.json | 46 ++++++++++++++++++++++++++++++++++- package.json | 3 ++- src/builder.ts | 5 +++- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 9e7aa02..3a798b5 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -43,7 +43,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: rm package-lock.json # otherwise we cannot overwrite the peerDependencies version of @angular-devkit/build-angular below - - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" + - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" - run: npm i - run: npm ls || true - run: npm run build diff --git a/package-lock.json b/package-lock.json index 28e76ee..47cd03b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,8 @@ "node": ">=14.0.0" }, "peerDependencies": { - "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "@angular/core": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "node_modules/@ampproject/remapping": { @@ -390,6 +391,22 @@ "typescript": ">=5.2 <5.3" } }, + "node_modules/@angular/core": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.0.1.tgz", + "integrity": "sha512-yVwU+oz0G8g6Q5ORyOCpgqMPdSiCdfW+uQhjI37WROnXHja3jY843AqrYTKE6mMx1r6q9h1wbDy+x2E61OWP7A==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.14.0" + } + }, "node_modules/@assemblyscript/loader": { "version": "0.10.1", "license": "Apache-2.0", @@ -13046,6 +13063,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zone.js": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.3.tgz", + "integrity": "sha512-jYoNqF046Q+JfcZSItRSt+oXFcpXL88yq7XAZjb/NKTS7w2hHpKjRJ3VlFD1k75wMaRRXNUt5vrZVlygiMyHbA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + } } }, "dependencies": { @@ -13271,6 +13297,15 @@ "yargs": "^17.2.1" } }, + "@angular/core": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.0.1.tgz", + "integrity": "sha512-yVwU+oz0G8g6Q5ORyOCpgqMPdSiCdfW+uQhjI37WROnXHja3jY843AqrYTKE6mMx1r6q9h1wbDy+x2E61OWP7A==", + "peer": true, + "requires": { + "tslib": "^2.3.0" + } + }, "@assemblyscript/loader": { "version": "0.10.1", "peer": true @@ -21461,6 +21496,15 @@ "yocto-queue": { "version": "0.1.0", "devOptional": true + }, + "zone.js": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.3.tgz", + "integrity": "sha512-jYoNqF046Q+JfcZSItRSt+oXFcpXL88yq7XAZjb/NKTS7w2hHpKjRJ3VlFD1k75wMaRRXNUt5vrZVlygiMyHbA==", + "peer": true, + "requires": { + "tslib": "^2.3.0" + } } } } diff --git a/package.json b/package.json index 45e7681..26ec32d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "xmldoc": "^1.1.2" }, "peerDependencies": { - "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "@angular-devkit/build-angular": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "@angular/core": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" }, "devDependencies": { "@types/jest": "^28.1.8 || ^29.0.0", diff --git a/src/builder.ts b/src/builder.ts index 848bfef..96635f9 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,6 +8,7 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; +import {VERSION} from "@angular/core"; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -106,8 +107,10 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); + const angularMajorVersion = parseInt(VERSION.major); + const targetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { - browserTarget: options.browserTarget, + [targetAttribute]: options.browserTarget, outputPath: dirname(sourcePath), outFile: basename(sourcePath), format, From 1998ee91cac4d94c615ac3fb5252b2f60920e33d Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 17 Jan 2024 15:09:55 +0100 Subject: [PATCH 02/23] ci: adding ci for nodejs 20 --- .github/workflows/node.js.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 3a798b5..6b5e40c 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -15,10 +15,11 @@ jobs: strategy: matrix: - node-version: [14.x, 16.x, 18.x] + node-version: [14.x, 16.x, 18.x, 20.x] angular-version: [13.1.4, 14.0.2, 15.0.3, 16.2.1, 17.0.0] exclude: - node-version: 18.x + - node-version: 20.x - angular-version: 17.0.0 include: - angular-version: 13.1.4 @@ -35,6 +36,9 @@ jobs: - angular-version: 17.0.0 devkit-version: 0.1700.0 node-version: 18.x + - angular-version: 17.0.0 + devkit-version: 0.1700.0 + node-version: 20.x steps: - uses: actions/checkout@v2 From 0a0a410dd2a164d23171de7553514b902424596e Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 17 Jan 2024 15:30:49 +0100 Subject: [PATCH 03/23] ci: use angular 13.1.3 as 13.1.4 has no release for @angular/core --- .github/workflows/node.js.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 6b5e40c..8e84dd4 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,13 +16,13 @@ jobs: strategy: matrix: node-version: [14.x, 16.x, 18.x, 20.x] - angular-version: [13.1.4, 14.0.2, 15.0.3, 16.2.1, 17.0.0] + angular-version: [13.1.3, 14.0.2, 15.0.3, 16.2.1, 17.0.0] exclude: - node-version: 18.x - node-version: 20.x - angular-version: 17.0.0 include: - - angular-version: 13.1.4 + - angular-version: 13.1.3 devkit-version: 0.1301.4 - angular-version: 14.0.2 devkit-version: 0.1400.2 From 68daf2a929e3af8e7c0c09807fd9538614fba893 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 24 Jan 2024 16:01:37 +0100 Subject: [PATCH 04/23] ci: lock compiler-cli dependency to prevent version conflicts --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 8e84dd4..7e31e7e 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -47,7 +47,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: rm package-lock.json # otherwise we cannot overwrite the peerDependencies version of @angular-devkit/build-angular below - - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" + - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" "@angular/compiler-cli@{{ matrix.angular-version }}", - run: npm i - run: npm ls || true - run: npm run build From 4d3152578b5a786976476335306e8d2b72caed78 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 24 Jan 2024 16:03:05 +0100 Subject: [PATCH 05/23] fixup: remove superfluous comma --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 7e31e7e..a86578b 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -47,7 +47,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: rm package-lock.json # otherwise we cannot overwrite the peerDependencies version of @angular-devkit/build-angular below - - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" "@angular/compiler-cli@{{ matrix.angular-version }}", + - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" "@angular/compiler-cli@{{ matrix.angular-version }}" - run: npm i - run: npm ls || true - run: npm run build From 962f1b6d348b3c8da2f0295af88a1ff96e6517ed Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 24 Jan 2024 16:06:55 +0100 Subject: [PATCH 06/23] fixup: correct interpolation --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index a86578b..918a577 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -47,7 +47,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - run: rm package-lock.json # otherwise we cannot overwrite the peerDependencies version of @angular-devkit/build-angular below - - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" "@angular/compiler-cli@{{ matrix.angular-version }}" + - run: npm i --save-exact "@angular-devkit/architect@${{ matrix.devkit-version }}" "@angular-devkit/core@${{ matrix.angular-version }}" "@angular-devkit/schematics@${{ matrix.angular-version }}" "@schematics/angular@${{ matrix.angular-version }}" "@angular-devkit/build-angular@${{ matrix.angular-version }}" "@angular/core@${{ matrix.angular-version }}" "@angular/compiler-cli@${{ matrix.angular-version }}" - run: npm i - run: npm ls || true - run: npm run build From f5c54c517685644b1e868f5fbf6da879982b362c Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 24 Jan 2024 22:43:43 +0100 Subject: [PATCH 07/23] fix: correct ts-jest config for importing mjs --- jest.config.ts | 8 ++++---- package-lock.json | 9 ++++++--- src/builder.ts | 2 +- tsconfig.json | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index 5998d00..8fe5fac 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,14 +1,14 @@ -import type {Config} from '@jest/types'; +import {JestConfigWithTsJest} from 'ts-jest'; // Sync object -const config: Config.InitialOptions = { - preset: 'ts-jest', +const config: JestConfigWithTsJest = { + preset: 'ts-jest/presets/js-with-ts-esm', testEnvironment: 'node', verbose: false, testMatch: undefined, testRegex: '.*\.spec\.ts$', collectCoverageFrom: ['src/**/*.ts'], // exclude coverage from schematic as it only collects from js (instead of ts).. coveragePathIgnorePatterns: ['src/rmSafe.ts'], - + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], }; export default config; diff --git a/package-lock.json b/package-lock.json index 47cd03b..e2503e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3538,9 +3538,10 @@ } }, "node_modules/@types/jest": { - "version": "29.5.5", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, - "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -15371,7 +15372,9 @@ } }, "@types/jest": { - "version": "29.5.5", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, "requires": { "expect": "^29.0.0", diff --git a/src/builder.ts b/src/builder.ts index 96635f9..7d06ab7 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,7 +8,7 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; -import {VERSION} from "@angular/core"; +import {VERSION} from '@angular/core'; const STATE_INITIAL_XLF_2_0 = 'initial'; diff --git a/tsconfig.json b/tsconfig.json index 3f587b3..918db71 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ - // "allowJs": true, /* Allow javascript files to be compiled. */ + "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ "declaration": true, /* Generates corresponding '.d.ts' file. */ From 55e9a4a3d39e1afc14e942a7b15a23f9c2f29e1f Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 24 Jan 2024 23:00:56 +0100 Subject: [PATCH 08/23] fix: little newer angular 13 version --- .github/workflows/node.js.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 918a577..326fe5d 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,14 +16,14 @@ jobs: strategy: matrix: node-version: [14.x, 16.x, 18.x, 20.x] - angular-version: [13.1.3, 14.0.2, 15.0.3, 16.2.1, 17.0.0] + angular-version: [13.2.6, 14.0.2, 15.0.3, 16.2.1, 17.0.0] exclude: - node-version: 18.x - node-version: 20.x - angular-version: 17.0.0 include: - - angular-version: 13.1.3 - devkit-version: 0.1301.4 + - angular-version: 13.2.6 + devkit-version: 0.1302.6 - angular-version: 14.0.2 devkit-version: 0.1400.2 - angular-version: 15.0.3 From 080fc592b19cb3b6103d4fd7c33800a6d66df4f8 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Thu, 25 Jan 2024 21:51:58 +0100 Subject: [PATCH 09/23] feat: add new option 'buildTarget' and deprecate 'browserTarget' - see #89 --- README.md | 5 +++-- schematics/migrations/2_0_0/index.ts | 5 ++++- schematics/ng-add/index.spec.ts | 17 ++++++++++------- schematics/ng-add/index.ts | 7 +++++-- src/builder.ts | 4 ++-- src/options.ts | 4 +++- src/schema.json | 16 +++++++++++++--- 7 files changed, 40 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 803fff2..d3f13e4 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,8 @@ In your `angular.json` the target `extract-i18n` that can be configured with the | Name | Default | Description | |------------------------------|----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `browserTarget` | Inferred from current setup by `ng add` | A browser builder target to extract i18n messages in the format of `project:target[:configuration]`. See https://angular.io/cli/extract-i18n#options | +| ~~`browserTarget`~~ | Inferred from current setup by `ng add` | _Deprecated_: Use `buildTarget`. A browser builder target to extract i18n messages in the format of `project:target[:configuration]`. See https://angular.io/cli/extract-i18n#options | +| `buildTarget` | Inferred from current setup by `ng add` | A build builder target to extract i18n messages in the format of `project:target[:configuration]`. See https://angular.io/cli/extract-i18n#options | | `format` | Inferred from current setup by `ng add` | Any of `xlf`, `xlif`, `xliff`, `xlf2`, `xliff2` | | `outputPath` | Inferred from current setup by `ng add` | Path to folder containing all (source and target) translation files. | | `targetFiles` | Inferred from current setup by `ng add` | Filenames (relative to `outputPath` of all target translation files (e.g. `["messages.fr.xlf", "messages.de.xlf"]`). | @@ -57,7 +58,7 @@ In your `angular.json` the target `extract-i18n` that can be configured with the | `includeContext` | `false` | Whether to include the context information (like notes) in the translation files. This is useful for sending the target translation files to translation agencies/services. When `sourceFileOnly`, the context is retained only in the `sourceFile`. | | `newTranslationTargetsBlank` | `false` | When `false` (default) the "target" of new translation units is set to the "source" value. When `true`, an empty string is used. When `'omit'`, no target element is created. | | `sort` | `"stableAppendNew"` (will change to `stableAlphabetNew` with v3.0.0) | Sorting of all translation units in source and target translation files. Supported:
`"idAsc"` (sort by translation IDs),
`"stableAppendNew"` (keep existing sorting, append new translations at the end),
`"stableAlphabetNew"` (keep existing sorting, sort new translations next to alphabetical close IDs). | -| `builderI18n` | `"@angular-devkit/build-angular:extract-i18n"` | The builder to use for i18n extraction. Any custom builder should handle the same options as the default angular builder (browserTarget, outputPath, outFile, format, progress). | +| `builderI18n` | `"@angular-devkit/build-angular:extract-i18n"` | The builder to use for i18n extraction. Any custom builder should handle the same options as the default angular builder (buildTarget, outputPath, outFile, format, progress). | | `verbose` | `false` | Extended/debug output - it is recommended to use this only for manual debugging. | ## Contribute diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index 4c42127..abf4d52 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,5 +1,6 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; +import {VERSION} from '@angular/core'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -28,11 +29,13 @@ export default function (): Rule { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { context.logger.info(`updating extract-i18n(-merge) targets for project ${projectName}..`) + const angularMajorVersion = parseInt(VERSION.major); + const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const i18nTarget = {...(project.targets.get('extract-i18n') ?? {builder: 'ng-extract-i18n-merge:ng-extract-i18n-merge'})}; i18nTarget.builder = 'ng-extract-i18n-merge:ng-extract-i18n-merge'; i18nTarget.options = { ...i18nMergeTarget.options, - browserTarget: i18nTarget.options?.browserTarget ?? `${projectName}:build` + [buildTargetAttribute]: i18nTarget.options?.browserTarget ?? i18nTarget.options?.buildTarget ?? `${projectName}:build` } project.targets.delete('extract-i18n'); // 'project.targets.set' not working!? project.targets.add({name: 'extract-i18n', ...i18nTarget}); diff --git a/schematics/ng-add/index.spec.ts b/schematics/ng-add/index.spec.ts index bcc0428..0d1860e 100644 --- a/schematics/ng-add/index.spec.ts +++ b/schematics/ng-add/index.spec.ts @@ -4,8 +4,11 @@ import * as path from 'path'; import {Schema as WorkspaceOptions} from '@schematics/angular/workspace/schema'; import {Schema as ApplicationOptions, Style} from '@schematics/angular/application/schema'; import {Tree} from '@angular-devkit/schematics'; +import {VERSION} from '@angular/core'; const collectionPath = path.join(__dirname, '../collection.json'); +const angularMajorVersion = parseInt(VERSION.major); +const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const workspaceOptions: WorkspaceOptions = { name: 'workspace', @@ -50,7 +53,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf2",\n' + ' "outputPath": "src/locales",\n' + ' "targetFiles": []\n' + @@ -76,7 +79,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -109,7 +112,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/some-path",\n' + ' "targetFiles": [ "../other-path/messages.fr.xlf" ],\n' + @@ -135,7 +138,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -157,7 +160,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -185,7 +188,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + @@ -214,7 +217,7 @@ describe('ngAdd', () => { expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + - ' "browserTarget": "bar:build",\n' + + ' "' + buildTargetAttribute + '": "bar:build",\n' + ' "format": "xlf2",\n' + ' "outputPath": "src/other-path",\n' + ' "targetFiles": [ "messages.fr.xlf" ]\n' + diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 639d841..756b412 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -4,6 +4,7 @@ import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; import {Options} from '../../src/options'; +import {VERSION} from '@angular/core'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -81,7 +82,7 @@ export function ngAdd(_options: Schema): Rule { const outputPath = normalize(outputPathFromExtractI18nOptions ?? outputPathFromTargetFiles ?? 'src/locales'); context.logger.info(`inferred output path: ${outputPath}`); - const browserTarget = existingI18nTargetOptions?.browserTarget as string | undefined ?? `${projectName}:build`; + const buildTarget = existingI18nTargetOptions?.browserTarget as string | undefined ?? existingI18nTargetOptions?.buildTarget as string | undefined ?? `${projectName}:build`; // infer format: const formatFromExtractI18nOptions = existingI18nTargetOptions?.format as Options['format'] | undefined; @@ -93,8 +94,10 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); + const angularMajorVersion = parseInt(VERSION.major); + const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { - browserTarget, + [buildTargetAttribute]: buildTarget, format, outputPath, targetFiles: filesWithoutOutputPath ?? [] diff --git a/src/builder.ts b/src/builder.ts index 7d06ab7..2385974 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -108,9 +108,9 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); const angularMajorVersion = parseInt(VERSION.major); - const targetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; + const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { - [targetAttribute]: options.browserTarget, + [buildTargetAttribute]: options.browserTarget ?? options.buildTarget, outputPath: dirname(sourcePath), outFile: basename(sourcePath), format, diff --git a/src/options.ts b/src/options.ts index 819f32d..8e980f6 100644 --- a/src/options.ts +++ b/src/options.ts @@ -16,7 +16,9 @@ export interface Options extends JsonObject { includeContext: boolean | 'sourceFileOnly', newTranslationTargetsBlank: boolean | 'omit', sort: 'idAsc' | 'stableAppendNew' | 'stableAlphabetNew', - browserTarget: string, + /** @deprecated use `buildTarget` instead */ + browserTarget: string | null, + buildTarget: string | null, builderI18n: string, verbose: boolean } diff --git a/src/schema.json b/src/schema.json index 9e63516..abf77db 100644 --- a/src/schema.json +++ b/src/schema.json @@ -113,6 +113,12 @@ "browserTarget": { "type": "string", "description": "A browser builder target use for rendering the app shell in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.", + "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$", + "x-deprecated": "Use `buildTarget` instead." + }, + "buildTarget": { + "type": "string", + "description": "A build builder target use for rendering the app shell in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.", "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$" }, "builderI18n": { @@ -127,8 +133,12 @@ } }, "additionalProperties": false, - "required": [ - "targetFiles", - "browserTarget" + "anyOf": [ + { + "required": ["browserTarget", "targetFiles"] + }, + { + "required": ["buildTarget", "targetFiles"] + } ] } From ac0a07f2db44ea8feb0f7f62ebc1ce984b6297bb Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Fri, 26 Jan 2024 16:57:15 +0100 Subject: [PATCH 10/23] 2.10.0-0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e2503e7..46cd06f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ng-extract-i18n-merge", - "version": "2.9.1", + "version": "2.10.0-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ng-extract-i18n-merge", - "version": "2.9.1", + "version": "2.10.0-0", "license": "MIT", "dependencies": { "@angular-devkit/architect": "^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0", diff --git a/package.json b/package.json index 26ec32d..c2048fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng-extract-i18n-merge", - "version": "2.9.1", + "version": "2.10.0-0", "description": "Extract and merge i18n xliff translation files for angular projects.", "main": "index.js", "builders": "builders.json", From 2357c0ed5d2754fa4b564e77ece8f61fe0597633 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Fri, 26 Jan 2024 17:15:23 +0100 Subject: [PATCH 11/23] fix: use dynamic import to prevent error on ng add --- schematics/migrations/2_0_0/index.ts | 4 ++-- schematics/ng-add/index.ts | 4 ++-- src/builder.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index abf4d52..01b3851 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,6 +1,5 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; -import {VERSION} from '@angular/core'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -24,7 +23,8 @@ function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { export default function (): Rule { return (tree: Tree, context: SchematicContext) => { updateNpmScript(tree, context.logger); - return updateWorkspace((workspace) => { + return updateWorkspace(async (workspace) => { + const {VERSION} = await import('@angular/core'); workspace.projects.forEach((project, projectName) => { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 756b412..410ee99 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -4,7 +4,6 @@ import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; import {Options} from '../../src/options'; -import {VERSION} from '@angular/core'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -58,7 +57,7 @@ function getOutFileRelativeToOutputPath(outFile: string, outputPathFromExtractI1 // noinspection JSUnusedGlobalSymbols export function ngAdd(_options: Schema): Rule { return (tree: Tree, context: SchematicContext) => { - return updateWorkspace((workspace) => { + return updateWorkspace(async (workspace) => { const projectName = _options.project || Array.from(workspace.projects.keys())[0]; const projectWorkspace = workspace.projects.get(projectName)!; if (!projectWorkspace) { @@ -94,6 +93,7 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); + const {VERSION} = await import('@angular/core'); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { diff --git a/src/builder.ts b/src/builder.ts index 2385974..427ae55 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,7 +8,6 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; -import {VERSION} from '@angular/core'; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -107,6 +106,7 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); + const {VERSION} = await import('@angular/core'); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { From 880db444fa83920558c7887332967b9c33e7f1e4 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Fri, 26 Jan 2024 17:18:50 +0100 Subject: [PATCH 12/23] 2.10.0-1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 46cd06f..89f884b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ng-extract-i18n-merge", - "version": "2.10.0-0", + "version": "2.10.0-1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ng-extract-i18n-merge", - "version": "2.10.0-0", + "version": "2.10.0-1", "license": "MIT", "dependencies": { "@angular-devkit/architect": "^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0", diff --git a/package.json b/package.json index c2048fb..d6099b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng-extract-i18n-merge", - "version": "2.10.0-0", + "version": "2.10.0-1", "description": "Extract and merge i18n xliff translation files for angular projects.", "main": "index.js", "builders": "builders.json", From 99c03df47e29a6bf9d4cd874ddcde77bd164bccc Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Mon, 5 Feb 2024 22:42:14 +0100 Subject: [PATCH 13/23] refactor: switch from commonjs to esm --- package.json | 4 ++++ schematics/migrations/2_0_0/index.ts | 2 +- schematics/ng-add/index.ts | 3 +-- src/builder.ts | 2 +- tsconfig.json | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d6099b2..d32628d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,10 @@ "version": "2.10.0-1", "description": "Extract and merge i18n xliff translation files for angular projects.", "main": "index.js", + "type": "module", + "exports": { + ".": "./index.js" + }, "builders": "builders.json", "schematics": "./schematics/collection.json", "ng-add": { diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index 01b3851..c8ac526 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,5 +1,6 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; +import {VERSION} from '@angular/core'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -24,7 +25,6 @@ export default function (): Rule { return (tree: Tree, context: SchematicContext) => { updateNpmScript(tree, context.logger); return updateWorkspace(async (workspace) => { - const {VERSION} = await import('@angular/core'); workspace.projects.forEach((project, projectName) => { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 410ee99..1c07ab0 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -2,8 +2,8 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit import {updateWorkspace} from '@schematics/angular/utility/workspace'; import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; - import {Options} from '../../src/options'; +import {VERSION} from '@angular/core'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -93,7 +93,6 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); - const {VERSION} = await import('@angular/core'); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { diff --git a/src/builder.ts b/src/builder.ts index 427ae55..2385974 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,6 +8,7 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; +import {VERSION} from '@angular/core'; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -106,7 +107,6 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); - const {VERSION} = await import('@angular/core'); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { diff --git a/tsconfig.json b/tsconfig.json index 918db71..5055903 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "module": "ES2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ @@ -44,7 +44,7 @@ // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ From 6a6d3db5571782c2088b2dfcc9ee54737212c04c Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Mon, 5 Feb 2024 22:49:54 +0100 Subject: [PATCH 14/23] 2.10.0-2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89f884b..3dc8f00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ng-extract-i18n-merge", - "version": "2.10.0-1", + "version": "2.10.0-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ng-extract-i18n-merge", - "version": "2.10.0-1", + "version": "2.10.0-2", "license": "MIT", "dependencies": { "@angular-devkit/architect": "^0.1301.0 || ^0.1401.0 || ^0.1501.0 || ^0.1601.0 || ^0.1700.0", diff --git a/package.json b/package.json index d32628d..c57b813 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng-extract-i18n-merge", - "version": "2.10.0-1", + "version": "2.10.0-2", "description": "Extract and merge i18n xliff translation files for angular projects.", "main": "index.js", "type": "module", From 2f3de4bab22ede29675efd62af5f62f82676471a Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 7 Feb 2024 20:08:27 +0100 Subject: [PATCH 15/23] Revert "refactor: switch from commonjs to esm" This reverts commit 99c03df47e29a6bf9d4cd874ddcde77bd164bccc. --- package.json | 4 ---- schematics/migrations/2_0_0/index.ts | 2 +- schematics/ng-add/index.ts | 3 ++- src/builder.ts | 2 +- tsconfig.json | 4 ++-- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index c57b813..5230300 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,6 @@ "version": "2.10.0-2", "description": "Extract and merge i18n xliff translation files for angular projects.", "main": "index.js", - "type": "module", - "exports": { - ".": "./index.js" - }, "builders": "builders.json", "schematics": "./schematics/collection.json", "ng-add": { diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index c8ac526..01b3851 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,6 +1,5 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; -import {VERSION} from '@angular/core'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -25,6 +24,7 @@ export default function (): Rule { return (tree: Tree, context: SchematicContext) => { updateNpmScript(tree, context.logger); return updateWorkspace(async (workspace) => { + const {VERSION} = await import('@angular/core'); workspace.projects.forEach((project, projectName) => { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 1c07ab0..410ee99 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -2,8 +2,8 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit import {updateWorkspace} from '@schematics/angular/utility/workspace'; import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; + import {Options} from '../../src/options'; -import {VERSION} from '@angular/core'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -93,6 +93,7 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); + const {VERSION} = await import('@angular/core'); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { diff --git a/src/builder.ts b/src/builder.ts index 2385974..427ae55 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,7 +8,6 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; -import {VERSION} from '@angular/core'; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -107,6 +106,7 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); + const {VERSION} = await import('@angular/core'); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { diff --git a/tsconfig.json b/tsconfig.json index 5055903..918db71 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "ES2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ @@ -44,7 +44,7 @@ // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ /* Module Resolution Options */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ From c58cfd9c9e354e4b16a919120a0ca177508f0089 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 7 Feb 2024 21:25:28 +0100 Subject: [PATCH 16/23] fix: load angular version via dynamic import that is not removed by ts --- .github/workflows/node.js.yml | 2 +- jest.config.ts | 2 +- schematics/migrations/2_0_0/index.ts | 4 +++- schematics/ng-add/index.spec.ts | 24 +++++++++++++++--------- schematics/ng-add/index.ts | 4 +++- src/builder.ts | 4 +++- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 326fe5d..3b39527 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -51,7 +51,7 @@ jobs: - run: npm i - run: npm ls || true - run: npm run build - - run: npm run test-coverage + - run: NODE_OPTIONS=--experimental-vm-modules npm run test-coverage - name: Coveralls uses: coverallsapp/github-action@v1.1.2 with: diff --git a/jest.config.ts b/jest.config.ts index 8fe5fac..d6a8a1d 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -2,7 +2,7 @@ import {JestConfigWithTsJest} from 'ts-jest'; // Sync object const config: JestConfigWithTsJest = { - preset: 'ts-jest/presets/js-with-ts-esm', + preset: 'ts-jest', testEnvironment: 'node', verbose: false, testMatch: undefined, diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index 01b3851..4068427 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,5 +1,7 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; +import {loadEsmModule} from '@angular-devkit/architect/node'; +import {Version} from '@angular/core'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -24,7 +26,7 @@ export default function (): Rule { return (tree: Tree, context: SchematicContext) => { updateNpmScript(tree, context.logger); return updateWorkspace(async (workspace) => { - const {VERSION} = await import('@angular/core'); + const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); workspace.projects.forEach((project, projectName) => { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { diff --git a/schematics/ng-add/index.spec.ts b/schematics/ng-add/index.spec.ts index 0d1860e..24c2e46 100644 --- a/schematics/ng-add/index.spec.ts +++ b/schematics/ng-add/index.spec.ts @@ -4,11 +4,16 @@ import * as path from 'path'; import {Schema as WorkspaceOptions} from '@schematics/angular/workspace/schema'; import {Schema as ApplicationOptions, Style} from '@schematics/angular/application/schema'; import {Tree} from '@angular-devkit/schematics'; -import {VERSION} from '@angular/core'; +import {loadEsmModule} from "@angular-devkit/architect/node"; +import {Version} from '@angular/core'; const collectionPath = path.join(__dirname, '../collection.json'); -const angularMajorVersion = parseInt(VERSION.major); -const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; + +async function getBuildTargetAttribute() { + const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); + const angularMajorVersion = parseInt(VERSION.major); + return angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; +} const workspaceOptions: WorkspaceOptions = { name: 'workspace', @@ -49,6 +54,7 @@ describe('ngAdd', () => { }); it('works', async () => { + const buildTargetAttribute = await getBuildTargetAttribute(); const tree = await runSchematic(runner, 'ng-add', {}, appTree); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + @@ -75,7 +81,7 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + @@ -108,7 +114,7 @@ describe('ngAdd', () => { appTree.create('/src/some-path/my-messages.xlf', '<>'); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + @@ -134,7 +140,7 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + @@ -156,7 +162,7 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + @@ -184,7 +190,7 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + @@ -213,7 +219,7 @@ describe('ngAdd', () => { appTree.overwrite('/angular.json', JSON.stringify(angularJson)); const tree = await runSchematic(runner, 'ng-add', {}, appTree); - + const buildTargetAttribute = await getBuildTargetAttribute(); expect(norm(tree.readContent('/angular.json'))).toContain(norm('"extract-i18n": {\n' + ' "builder": "ng-extract-i18n-merge:ng-extract-i18n-merge",\n' + ' "options": {\n' + diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 410ee99..19636ef 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -4,6 +4,8 @@ import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; import {Options} from '../../src/options'; +import {loadEsmModule} from '@angular-devkit/architect/node'; +import {Version} from '@angular/core'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -93,7 +95,7 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); - const {VERSION} = await import('@angular/core'); + const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { diff --git a/src/builder.ts b/src/builder.ts index 427ae55..90e400c 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,6 +8,8 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; +import {loadEsmModule} from '@angular-devkit/architect/node'; +import {Version} from '@angular/core'; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -106,7 +108,7 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); - const {VERSION} = await import('@angular/core'); + const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); const angularMajorVersion = parseInt(VERSION.major); const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { From 4f56bbdbd26c8c358aed26842421378205a4e087 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 7 Feb 2024 21:39:06 +0100 Subject: [PATCH 17/23] fix: copy loadEsmModule as not present in older angular versions (and internal anyway) --- schematics/migrations/2_0_0/index.ts | 2 +- schematics/ng-add/index.ts | 2 +- src/builder.ts | 2 +- src/loadEsmModule.ts | 26 ++++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/loadEsmModule.ts diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index 4068427..c880cf8 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,7 +1,7 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; -import {loadEsmModule} from '@angular-devkit/architect/node'; import {Version} from '@angular/core'; +import {loadEsmModule} from '../../../src/loadEsmModule'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index 19636ef..f2db6c1 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -4,7 +4,7 @@ import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; import {Options} from '../../src/options'; -import {loadEsmModule} from '@angular-devkit/architect/node'; +import {loadEsmModule} from '../../src/loadEsmModule'; import {Version} from '@angular/core'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { diff --git a/src/builder.ts b/src/builder.ts index 90e400c..ce1cd50 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,8 +8,8 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; -import {loadEsmModule} from '@angular-devkit/architect/node'; import {Version} from '@angular/core'; +import {loadEsmModule} from './loadEsmModule'; const STATE_INITIAL_XLF_2_0 = 'initial'; diff --git a/src/loadEsmModule.ts b/src/loadEsmModule.ts new file mode 100644 index 0000000..e2b3f8f --- /dev/null +++ b/src/loadEsmModule.ts @@ -0,0 +1,26 @@ +/** + * This uses a dynamic import to load a module which may be ESM. + * CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript + * will currently, unconditionally downlevel dynamic import into a require call. + * require calls cannot load ESM code and will result in a runtime error. To workaround + * this, a Function constructor is used to prevent TypeScript from changing the dynamic import. + * Once TypeScript provides support for keeping the dynamic import this workaround can + * be dropped. + * This is only intended to be used with Angular framework packages. + * + * Copied from https://github.com/angular/angular/blob/e0015d3c456d584242269b0765878d598a550888/packages/core/schematics/utils/load_esm.ts#L11-L35 + * + * @param modulePath The path of the module to load. + * @returns A Promise that resolves to the dynamically imported module. + */ +export async function loadEsmModule(modulePath: string|URL): Promise { + const namespaceObject = + (await new Function('modulePath', `return import(modulePath);`)(modulePath)); + + // If it is not ESM then the values needed will be stored in the `default` property. + if (namespaceObject.default) { + return namespaceObject.default; + } else { + return namespaceObject; + } +} \ No newline at end of file From 56b0694f5059fe1213400e3ab2e238da0d11faca Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 7 Feb 2024 21:41:46 +0100 Subject: [PATCH 18/23] fixup: use new loadEsmModule in test as well --- schematics/ng-add/index.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematics/ng-add/index.spec.ts b/schematics/ng-add/index.spec.ts index 24c2e46..df4380a 100644 --- a/schematics/ng-add/index.spec.ts +++ b/schematics/ng-add/index.spec.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import {Schema as WorkspaceOptions} from '@schematics/angular/workspace/schema'; import {Schema as ApplicationOptions, Style} from '@schematics/angular/application/schema'; import {Tree} from '@angular-devkit/schematics'; -import {loadEsmModule} from "@angular-devkit/architect/node"; +import {loadEsmModule} from '../../src/loadEsmModule'; import {Version} from '@angular/core'; const collectionPath = path.join(__dirname, '../collection.json'); From b29d6541fab1b3aaf151d2421a50d69be56b6496 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 7 Feb 2024 22:02:55 +0100 Subject: [PATCH 19/23] fix: build error: A jest worker process was terminated by another process: signal=SIGSEGV, --- jest.config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jest.config.ts b/jest.config.ts index d6a8a1d..dd0042b 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -5,6 +5,8 @@ const config: JestConfigWithTsJest = { preset: 'ts-jest', testEnvironment: 'node', verbose: false, + maxWorkers: 10, + maxConcurrency: 10, testMatch: undefined, testRegex: '.*\.spec\.ts$', collectCoverageFrom: ['src/**/*.ts'], // exclude coverage from schematic as it only collects from js (instead of ts).. From 4ecf3cda341a1bb425be4eb7dea3e46f6ef04c07 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Thu, 8 Feb 2024 15:23:08 +0100 Subject: [PATCH 20/23] fix: another try for successfully running CI pipeline.. --- jest.config.ts | 6 +++--- tsconfig.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index dd0042b..aea1443 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -5,12 +5,12 @@ const config: JestConfigWithTsJest = { preset: 'ts-jest', testEnvironment: 'node', verbose: false, - maxWorkers: 10, - maxConcurrency: 10, + maxWorkers: 100, + maxConcurrency: 100, + testTimeout: 30_000, testMatch: undefined, testRegex: '.*\.spec\.ts$', collectCoverageFrom: ['src/**/*.ts'], // exclude coverage from schematic as it only collects from js (instead of ts).. coveragePathIgnorePatterns: ['src/rmSafe.ts'], - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], }; export default config; diff --git a/tsconfig.json b/tsconfig.json index 918db71..3c0782f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */ From 538ed976e49d93066fc7f5a993c61c8e481af4cd Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Thu, 8 Feb 2024 16:26:06 +0100 Subject: [PATCH 21/23] another try.. --- jest.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.ts b/jest.config.ts index aea1443..4b56be3 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -6,7 +6,7 @@ const config: JestConfigWithTsJest = { testEnvironment: 'node', verbose: false, maxWorkers: 100, - maxConcurrency: 100, + maxConcurrency: 1, testTimeout: 30_000, testMatch: undefined, testRegex: '.*\.spec\.ts$', From cd9b659c2256e4ffbf63bb3600b11ead303010a6 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 21 Feb 2024 22:03:08 +0100 Subject: [PATCH 22/23] check existence of config attribute instead of reading angular version --- schematics/migrations/2_0_0/index.ts | 7 ++----- schematics/ng-add/index.spec.ts | 7 ++----- schematics/ng-add/index.ts | 7 ++----- src/builder.ts | 7 ++----- src/loadEsmModule.ts | 26 -------------------------- tsconfig.json | 1 + 6 files changed, 9 insertions(+), 46 deletions(-) delete mode 100644 src/loadEsmModule.ts diff --git a/schematics/migrations/2_0_0/index.ts b/schematics/migrations/2_0_0/index.ts index c880cf8..6cbd5b8 100644 --- a/schematics/migrations/2_0_0/index.ts +++ b/schematics/migrations/2_0_0/index.ts @@ -1,7 +1,6 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {updateWorkspace} from '@schematics/angular/utility/workspace'; -import {Version} from '@angular/core'; -import {loadEsmModule} from '../../../src/loadEsmModule'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; function updateNpmScript(tree: Tree, logger: SchematicContext['logger']) { const pkgPath = '/package.json'; @@ -26,13 +25,11 @@ export default function (): Rule { return (tree: Tree, context: SchematicContext) => { updateNpmScript(tree, context.logger); return updateWorkspace(async (workspace) => { - const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); workspace.projects.forEach((project, projectName) => { const i18nMergeTarget = project.targets.get('extract-i18n-merge'); if (i18nMergeTarget) { context.logger.info(`updating extract-i18n(-merge) targets for project ${projectName}..`) - const angularMajorVersion = parseInt(VERSION.major); - const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; + const buildTargetAttribute = extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; const i18nTarget = {...(project.targets.get('extract-i18n') ?? {builder: 'ng-extract-i18n-merge:ng-extract-i18n-merge'})}; i18nTarget.builder = 'ng-extract-i18n-merge:ng-extract-i18n-merge'; i18nTarget.options = { diff --git a/schematics/ng-add/index.spec.ts b/schematics/ng-add/index.spec.ts index df4380a..0a37d08 100644 --- a/schematics/ng-add/index.spec.ts +++ b/schematics/ng-add/index.spec.ts @@ -4,15 +4,12 @@ import * as path from 'path'; import {Schema as WorkspaceOptions} from '@schematics/angular/workspace/schema'; import {Schema as ApplicationOptions, Style} from '@schematics/angular/application/schema'; import {Tree} from '@angular-devkit/schematics'; -import {loadEsmModule} from '../../src/loadEsmModule'; -import {Version} from '@angular/core'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; const collectionPath = path.join(__dirname, '../collection.json'); async function getBuildTargetAttribute() { - const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); - const angularMajorVersion = parseInt(VERSION.major); - return angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; + return extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; } const workspaceOptions: WorkspaceOptions = { diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index f2db6c1..6bdca6f 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -4,8 +4,7 @@ import {Schema} from './schema'; import {JsonArray, JsonObject, normalize, Path, relative} from '@angular-devkit/core'; import {Options} from '../../src/options'; -import {loadEsmModule} from '../../src/loadEsmModule'; -import {Version} from '@angular/core'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; function getTargetFiles(i18nExtension: JsonObject | undefined): string[] { const locales = i18nExtension?.locales ? (Object.values(i18nExtension?.locales) as JsonArray | string[] | undefined) : undefined; @@ -95,9 +94,7 @@ export function ngAdd(_options: Schema): Rule { const filesWithoutOutputPath = files?.map(f => relative(`/${outputPath}` as Path, `/${f}` as Path)); const target = projectWorkspace.targets.get('extract-i18n'); - const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); - const angularMajorVersion = parseInt(VERSION.major); - const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; + const buildTargetAttribute = extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; const builderOptions: Partial = { [buildTargetAttribute]: buildTarget, format, diff --git a/src/builder.ts b/src/builder.ts index ce1cd50..c465f99 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -8,8 +8,7 @@ import {TranslationFile, TranslationUnit} from './model/translationFileModels'; import {Merger} from './merger'; import {Options} from './options'; import {doCollapseWhitespace} from './stringUtils'; -import {Version} from '@angular/core'; -import {loadEsmModule} from './loadEsmModule'; +import * as extractI18nSchema from '@angular-devkit/build-angular/src/builders/extract-i18n/schema.json'; const STATE_INITIAL_XLF_2_0 = 'initial'; @@ -108,9 +107,7 @@ async function extractI18nMergeBuilder(options: Options, context: BuilderContext const sourcePath = join(normalize(outputPath), options.sourceFile ?? 'messages.xlf'); const translationSourceFileOriginal = fromXlf(await readFileIfExists(sourcePath)); - const {VERSION} = (await loadEsmModule<{VERSION: Version}>('@angular/core')); - const angularMajorVersion = parseInt(VERSION.major); - const buildTargetAttribute = angularMajorVersion >= 17 ? 'buildTarget' : 'browserTarget'; + const buildTargetAttribute = extractI18nSchema.properties.buildTarget ? 'buildTarget' : 'browserTarget'; const extractI18nRun = await context.scheduleBuilder(options.builderI18n ?? '@angular-devkit/build-angular:extract-i18n', { [buildTargetAttribute]: options.browserTarget ?? options.buildTarget, outputPath: dirname(sourcePath), diff --git a/src/loadEsmModule.ts b/src/loadEsmModule.ts deleted file mode 100644 index e2b3f8f..0000000 --- a/src/loadEsmModule.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * This uses a dynamic import to load a module which may be ESM. - * CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript - * will currently, unconditionally downlevel dynamic import into a require call. - * require calls cannot load ESM code and will result in a runtime error. To workaround - * this, a Function constructor is used to prevent TypeScript from changing the dynamic import. - * Once TypeScript provides support for keeping the dynamic import this workaround can - * be dropped. - * This is only intended to be used with Angular framework packages. - * - * Copied from https://github.com/angular/angular/blob/e0015d3c456d584242269b0765878d598a550888/packages/core/schematics/utils/load_esm.ts#L11-L35 - * - * @param modulePath The path of the module to load. - * @returns A Promise that resolves to the dynamically imported module. - */ -export async function loadEsmModule(modulePath: string|URL): Promise { - const namespaceObject = - (await new Function('modulePath', `return import(modulePath);`)(modulePath)); - - // If it is not ESM then the values needed will be stored in the `default` property. - if (namespaceObject.default) { - return namespaceObject.default; - } else { - return namespaceObject; - } -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 3c0782f..e84f04f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -52,6 +52,7 @@ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "resolveJsonModule": true, // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ From 9f3634a8ec1f42dbcba2f41cf6d19fc8098bc1e7 Mon Sep 17 00:00:00 2001 From: Daniel Schreiber Date: Wed, 21 Feb 2024 22:11:08 +0100 Subject: [PATCH 23/23] revert allowJs option --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index e84f04f..b82a18b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ - "allowJs": true, /* Allow javascript files to be compiled. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ "declaration": true, /* Generates corresponding '.d.ts' file. */