From 65386c1e23e82fbb6f8433ff202dd51e7da0d4fb Mon Sep 17 00:00:00 2001 From: Olivier Combe Date: Wed, 11 Oct 2023 17:40:57 +0200 Subject: [PATCH] feat: add support for Angular v17 --- .bitmap | 32 ++- .github/workflows/main.yml | 127 +++++++++ .../angular-app-type/angular.application.ts | 6 +- .../index-html-webpack-plugin.ts | 2 +- .../build-angular/webpack/configs.ts | 2 +- .../ng-compat/build-angular/webpack/stats.ts | 2 +- .../src/environments/environment.prod.ts | 3 - .../src/environments/environment.ts | 16 -- .../preview/preview-app/src/polyfills.ts | 2 +- .../preview/preview/preview-app/src/test.ts | 2 +- angular/devkit/preview/runtime/loader.ts | 2 +- angular/devkit/preview/runtime/main.ts | 2 +- angular/envs/angular-env/component.json | 3 +- angular/envs/angular-env/env.jsonc | 4 +- angular/envs/angular-v12-env/component.json | 2 +- angular/envs/angular-v12-env/env.jsonc | 4 +- angular/envs/angular-v13-env/component.json | 2 +- angular/envs/angular-v13-env/env.jsonc | 4 +- angular/envs/angular-v14-env/component.json | 2 +- angular/envs/angular-v14-env/env.jsonc | 4 +- angular/envs/angular-v15-env/component.json | 2 +- angular/envs/angular-v15-env/env.jsonc | 4 +- .../angular-v16-env.bit-env.ts | 2 +- angular/envs/angular-v16-env/component.json | 3 +- angular/envs/angular-v16-env/env.jsonc | 4 +- .../angular-v17-env.bit-env.ts | 68 +++++ .../angular-v17-env/angular-v17-env.docs.mdx | 85 ++++++ angular/envs/angular-v17-env/component.json | 69 +++++ angular/envs/angular-v17-env/env.jsonc | 111 ++++++++ angular/envs/angular-v17-env/index.ts | 2 + .../angular-v17-env/jest/jest-global-mocks.ts | 31 ++ .../envs/angular-v17-env/jest/jest.config.ts | 35 +++ .../angular-v17-env/jest/jest.resolver.ts | 35 +++ .../angular-v17-env/jest/tsconfig.spec.json | 36 +++ .../angular-v17-env/webpack-config.factory.ts | 267 ++++++++++++++++++ .../webpack/module-rules.config.ts | 115 ++++++++ .../webpack/webpack5.build.config.ts | 59 ++++ .../webpack/webpack5.serve.config.ts | 176 ++++++++++++ .../examples/my-angular-env/component.json | 1 + angular/examples/my-angular-env/env.jsonc | 4 +- angular/examples/my-angular-v12-env/env.jsonc | 4 +- angular/examples/my-angular-v13-env/env.jsonc | 4 +- angular/examples/my-angular-v14-env/env.jsonc | 4 +- angular/examples/my-angular-v15-env/env.jsonc | 4 +- .../my-angular-v16-env/component.json | 1 + angular/examples/my-angular-v16-env/env.jsonc | 4 +- .../my-angular-v17-env/component.json | 20 ++ .../my-angular-v17-env/config/eslintrc.js | 7 + .../my-angular-v17-env/config/jest.config.ts | 8 + .../config/prettier.config.ts | 8 + .../my-angular-v17-env/config/tsconfig.json | 7 + angular/examples/my-angular-v17-env/env.jsonc | 111 ++++++++ angular/examples/my-angular-v17-env/index.ts | 1 + .../my-angular-v17-env.bit-env.ts | 131 +++++++++ .../my-angular-v17-env.docs.mdx | 86 ++++++ .../preview/host-dependencies.ts | 11 + .../my-angular-v17-env/preview/mounter.ts | 27 ++ angular/templates/generators/ng-app/index.ts | 50 +++- .../ng-app/template-files/ng-app.ts | 7 +- .../src/app/app.component-html.ts | 77 ++--- .../src/app/app.component-spec.ts | 6 +- .../template-files/src/app/app.component.ts | 18 +- .../template-files/src/app/app.config.ts | 16 ++ .../template-files/src/app/app.routes.ts | 11 + .../src/environments/environment.prod.ts | 11 - .../src/environments/environment.ts | 24 -- .../ng-app/template-files/src/main.ts | 15 +- .../ng-app/template-files/src/polyfills.ts | 2 +- .../ng-app/template-files/tsconfig.app.ts | 15 +- .../demo-app/src/app/app.component.html | 77 ++--- integration/demo-lib-v17/public-api.ts | 6 + .../demo-lib-v17/src/bit-test.component.ts | 13 + integration/demo-lib-v17/src/bit-test.docs.md | 27 ++ .../demo-lib-v17/src/bit-test.module.ts | 15 + .../demo-lib-v17/src/bit-test.service.ts | 8 + integration/demo-lib-v17/src/bit-test.spec.ts | 30 ++ .../demo-lib-v17/src/bit-test2.component.ts | 11 + .../src/compositions/bit-test.composition.ts | 16 ++ .../src/compositions/cmp1.composition.ts | 18 ++ workspace.jsonc | 17 +- 80 files changed, 2015 insertions(+), 245 deletions(-) delete mode 100644 angular/devkit/preview/preview/preview-app/src/environments/environment.prod.ts delete mode 100644 angular/devkit/preview/preview/preview-app/src/environments/environment.ts create mode 100644 angular/envs/angular-v17-env/angular-v17-env.bit-env.ts create mode 100644 angular/envs/angular-v17-env/angular-v17-env.docs.mdx create mode 100644 angular/envs/angular-v17-env/component.json create mode 100644 angular/envs/angular-v17-env/env.jsonc create mode 100644 angular/envs/angular-v17-env/index.ts create mode 100644 angular/envs/angular-v17-env/jest/jest-global-mocks.ts create mode 100644 angular/envs/angular-v17-env/jest/jest.config.ts create mode 100644 angular/envs/angular-v17-env/jest/jest.resolver.ts create mode 100644 angular/envs/angular-v17-env/jest/tsconfig.spec.json create mode 100644 angular/envs/angular-v17-env/webpack-config.factory.ts create mode 100644 angular/envs/angular-v17-env/webpack/module-rules.config.ts create mode 100644 angular/envs/angular-v17-env/webpack/webpack5.build.config.ts create mode 100644 angular/envs/angular-v17-env/webpack/webpack5.serve.config.ts create mode 100644 angular/examples/my-angular-v17-env/component.json create mode 100644 angular/examples/my-angular-v17-env/config/eslintrc.js create mode 100644 angular/examples/my-angular-v17-env/config/jest.config.ts create mode 100644 angular/examples/my-angular-v17-env/config/prettier.config.ts create mode 100644 angular/examples/my-angular-v17-env/config/tsconfig.json create mode 100644 angular/examples/my-angular-v17-env/env.jsonc create mode 100644 angular/examples/my-angular-v17-env/index.ts create mode 100644 angular/examples/my-angular-v17-env/my-angular-v17-env.bit-env.ts create mode 100644 angular/examples/my-angular-v17-env/my-angular-v17-env.docs.mdx create mode 100644 angular/examples/my-angular-v17-env/preview/host-dependencies.ts create mode 100644 angular/examples/my-angular-v17-env/preview/mounter.ts create mode 100644 angular/templates/generators/ng-app/template-files/src/app/app.config.ts create mode 100644 angular/templates/generators/ng-app/template-files/src/app/app.routes.ts delete mode 100644 angular/templates/generators/ng-app/template-files/src/environments/environment.prod.ts delete mode 100644 angular/templates/generators/ng-app/template-files/src/environments/environment.ts create mode 100644 integration/demo-lib-v17/public-api.ts create mode 100644 integration/demo-lib-v17/src/bit-test.component.ts create mode 100644 integration/demo-lib-v17/src/bit-test.docs.md create mode 100644 integration/demo-lib-v17/src/bit-test.module.ts create mode 100644 integration/demo-lib-v17/src/bit-test.service.ts create mode 100644 integration/demo-lib-v17/src/bit-test.spec.ts create mode 100644 integration/demo-lib-v17/src/bit-test2.component.ts create mode 100644 integration/demo-lib-v17/src/compositions/bit-test.composition.ts create mode 100644 integration/demo-lib-v17/src/compositions/cmp1.composition.ts diff --git a/.bitmap b/.bitmap index 3ba19abd..834444b1 100644 --- a/.bitmap +++ b/.bitmap @@ -30,13 +30,6 @@ "mainFile": "index.ts", "rootDir": "angular/devkit/common" }, - "dev-services/ng-compat": { - "name": "dev-services/ng-compat", - "scope": "", - "version": "", - "mainFile": "index.ts", - "rootDir": "angular/devkit/ng-compat" - }, "dev-services/compiler/elements": { "name": "dev-services/compiler/elements", "scope": "bitdev.angular", @@ -65,6 +58,14 @@ "mainFile": "index.js", "rootDir": "angular/devkit/linter/eslint" }, + "dev-services/ng-compat": { + "name": "dev-services/ng-compat", + "scope": "", + "version": "", + "defaultScope": "bitdev.angular", + "mainFile": "index.ts", + "rootDir": "angular/devkit/ng-compat" + }, "dev-services/ngcc": { "name": "dev-services/ngcc", "scope": "bitdev.angular", @@ -97,6 +98,7 @@ "name": "dev-services/vite", "scope": "", "version": "", + "defaultScope": "bitdev.angular", "mainFile": "index.ts", "rootDir": "angular/devkit/vite" }, @@ -142,6 +144,14 @@ "mainFile": "index.ts", "rootDir": "angular/envs/angular-v16-env" }, + "envs/angular-v17-env": { + "name": "envs/angular-v17-env", + "scope": "", + "version": "", + "defaultScope": "bitdev.angular", + "mainFile": "index.ts", + "rootDir": "angular/envs/angular-v17-env" + }, "envs/base-env": { "name": "envs/base-env", "scope": "bitdev.angular", @@ -191,6 +201,14 @@ "mainFile": "index.ts", "rootDir": "angular/examples/my-angular-v16-env" }, + "examples/my-angular-v17-env": { + "name": "examples/my-angular-v17-env", + "scope": "", + "version": "", + "defaultScope": "bitdev.angular", + "mainFile": "index.ts", + "rootDir": "angular/examples/my-angular-v17-env" + }, /*"readme": { "scope": "bitdev.angular", "version": "1.0.1", diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1004c45b..3f0d3d5e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,6 +35,12 @@ jobs: - name: Install dependencies run: bit install --log + - name: Remove v17 + run: bit remove envs/angular-v17-env -s -f --log + + - name: Remove v17 fork + run: bit remove examples/my-angular-v17-env -s -f --log + - name: Remove v15 run: bit remove envs/angular-v15-env -s -f --log @@ -98,6 +104,97 @@ jobs: name: debug-log path: $HOME/Library/Caches/Bit/logs + # Test angular-v17 + v17: + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, 'skip-ci')" + container: + image: docker://bitcli/bit:latest + steps: + - uses: teambit/setup-action@v2.02 + with: + name: angular-github-actions + BIT_TOKEN: ${{ env.BIT_TOKEN }} + + - uses: actions/checkout@v3 + + - name: Keep v17 + run: npm i replace-in-file@6.3.5 && node scripts/keep-env.js --version=17 + + - name: Cleanup node modules + run: rm -rf node_modules + + - name: Install dependencies + run: bit install --log + + - name: Remove default + run: bit remove angular-env -s -f --log + + - name: Remove default fork + run: bit remove examples/my-angular-env -s -f --log + + - name: Remove v16 + run: bit remove envs/angular-v16-env -s -f --log + + - name: Remove v16 fork + run: bit remove examples/my-angular-v16-env -s -f --log + + - name: Remove v15 + run: bit remove envs/angular-v15-env -s -f --log + + - name: Remove v15 fork + run: bit remove examples/my-angular-v15-env -s -f --log + + - name: Remove v14 + run: bit remove envs/angular-v14-env -s -f --log + + - name: Remove v14 fork + run: bit remove examples/my-angular-v14-env -s -f --log + + - name: Remove v13 + run: bit remove envs/angular-v13-env -s -f --log + + - name: Remove v13 fork + run: bit remove examples/my-angular-v13-env -s -f --log + + - name: Remove v12 + run: bit remove envs/angular-v12-env -s -f --log + + - name: Remove v12 fork + run: bit remove examples/my-angular-v12-env -s -f --log + + - name: Add example component + run: bit add integration/demo-lib-v17 --log + + - name: Bit cc + run: bit cc + + - name: Cleanup capsules + run: bit capsule delete --all + + - name: Cleanup node modules + run: rm -rf node_modules + + - name: Cleanup package-lock.json + run: rm -rf package-lock.json + + - name: Cleanup .git/bit + run: rm -rf .git/bit + + - name: Install dependencies + run: bit install --log + + - name: Bit test + run: bit test --log + + - name: Bit build + run: bit build --log + + - uses: actions/upload-artifact@v3 + with: + name: debug-log + path: $HOME/Library/Caches/Bit/logs + # Test angular-v16 v16: runs-on: ubuntu-latest @@ -127,6 +224,12 @@ jobs: - name: Remove default fork run: bit remove examples/my-angular-env -s -f --log + - name: Remove v17 + run: bit remove envs/angular-v17-env -s -f --log + + - name: Remove v17 fork + run: bit remove examples/my-angular-v17-env -s -f --log + - name: Remove v15 run: bit remove envs/angular-v15-env -s -f --log @@ -213,6 +316,12 @@ jobs: - name: Remove default fork run: bit remove examples/my-angular-env -s -f --log + - name: Remove v17 + run: bit remove envs/angular-v17-env -s -f --log + + - name: Remove v17 fork + run: bit remove examples/my-angular-v17-env -s -f --log + - name: Remove v16 run: bit remove envs/angular-v16-env -s -f --log @@ -298,6 +407,12 @@ jobs: - name: Remove default fork run: bit remove examples/my-angular-env -s -f --log + - name: Remove v17 + run: bit remove envs/angular-v17-env -s -f --log + + - name: Remove v17 fork + run: bit remove examples/my-angular-v17-env -s -f --log + - name: Remove v16 run: bit remove envs/angular-v16-env -s -f --log @@ -383,6 +498,12 @@ jobs: - name: Remove default fork run: bit remove examples/my-angular-env -s -f --log + - name: Remove v17 + run: bit remove envs/angular-v17-env -s -f --log + + - name: Remove v17 fork + run: bit remove examples/my-angular-v17-env -s -f --log + - name: Remove v16 run: bit remove envs/angular-v16-env -s -f --log @@ -469,6 +590,12 @@ jobs: - name: Remove default fork run: bit remove examples/my-angular-env -s -f --log + - name: Remove v17 + run: bit remove envs/angular-v17-env -s -f --log + + - name: Remove v17 fork + run: bit remove examples/my-angular-v17-env -s -f --log + - name: Remove v16 run: bit remove envs/angular-v16-env -s -f --log diff --git a/angular/app-types/angular-app-type/angular.application.ts b/angular/app-types/angular-app-type/angular.application.ts index f2413699..704db128 100644 --- a/angular/app-types/angular-app-type/angular.application.ts +++ b/angular/app-types/angular-app-type/angular.application.ts @@ -55,10 +55,10 @@ export class AngularApp implements Application { return join(artifactsDir, this.name); } - private getDevServerContext(context: AppContext, appRootPath: string): DevServerContext { + private getDevServerContext(context: AppContext): DevServerContext { return Object.assign(cloneDeep(context), { entry: [], - rootPath: appRootPath, + rootPath: '', publicPath: `${this.publicDir}/${this.options.name}`, title: this.options.name }); @@ -121,7 +121,7 @@ export class AngularApp implements Application { const workspaceCmpsIDs = await this.workspace.listIds(); const bitCmps = await this.workspace.getMany(workspaceCmpsIDs); this.generateTsConfig(bitCmps, appRootPath, tsconfigPath); - const devServerContext = this.getDevServerContext(context, this.options.bundler === 'vite' ? '' : appRootPath); + const devServerContext = this.getDevServerContext(context); const preview = this.preview(this.envContext); return preview.getDevServer(devServerContext)(this.envContext); diff --git a/angular/devkit/ng-compat/build-angular/index-html-webpack-plugin.ts b/angular/devkit/ng-compat/build-angular/index-html-webpack-plugin.ts index e9cb4a17..f5fe0fbf 100644 --- a/angular/devkit/ng-compat/build-angular/index-html-webpack-plugin.ts +++ b/angular/devkit/ng-compat/build-angular/index-html-webpack-plugin.ts @@ -1,7 +1,7 @@ import { VERSION } from '@angular/cli'; export let IndexHtmlWebpackPlugin: any; -if (VERSION.major === '16' && Number(VERSION.minor) >= 2) { +if ((VERSION.major === '16' && Number(VERSION.minor) >= 2) || Number(VERSION.major) > 16) { // 16.2+ IndexHtmlWebpackPlugin = require('@angular-devkit/build-angular/src/tools/webpack/plugins/index-html-webpack-plugin').IndexHtmlWebpackPlugin; } else { diff --git a/angular/devkit/ng-compat/build-angular/webpack/configs.ts b/angular/devkit/ng-compat/build-angular/webpack/configs.ts index 939cdf81..383b0fe4 100644 --- a/angular/devkit/ng-compat/build-angular/webpack/configs.ts +++ b/angular/devkit/ng-compat/build-angular/webpack/configs.ts @@ -3,7 +3,7 @@ import { VERSION } from '@angular/cli'; type configFn = (wco: any) => Promise | Configuration; let configs: any; -if (VERSION.major === '16' && Number(VERSION.minor) >= 2) { +if ((VERSION.major === '16' && Number(VERSION.minor) >= 2) || Number(VERSION.major) > 16) { // 16.2+ configs = require('@angular-devkit/build-angular/src/tools/webpack/configs'); } else { diff --git a/angular/devkit/ng-compat/build-angular/webpack/stats.ts b/angular/devkit/ng-compat/build-angular/webpack/stats.ts index 9684d1a9..eff2ae74 100644 --- a/angular/devkit/ng-compat/build-angular/webpack/stats.ts +++ b/angular/devkit/ng-compat/build-angular/webpack/stats.ts @@ -5,7 +5,7 @@ import { BrowserBuilderSchema } from '../browser-schema'; export let createWebpackLoggingCallback: (options: typeof BrowserBuilderSchema, logger: logging.LoggerApi) => WebpackLoggingCallback; -if (VERSION.major === '16' && Number(VERSION.minor) >= 2) { +if ((VERSION.major === '16' && Number(VERSION.minor) >= 2) || Number(VERSION.major) > 16) { createWebpackLoggingCallback = require('@angular-devkit/build-angular/src/tools/webpack/utils/stats').createWebpackLoggingCallback; } else { createWebpackLoggingCallback = require('@angular-devkit/build-angular/src/webpack/utils/stats').createWebpackLoggingCallback; diff --git a/angular/devkit/preview/preview/preview-app/src/environments/environment.prod.ts b/angular/devkit/preview/preview/preview-app/src/environments/environment.prod.ts deleted file mode 100644 index c9669790..00000000 --- a/angular/devkit/preview/preview/preview-app/src/environments/environment.prod.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const environment = { - production: true, -}; diff --git a/angular/devkit/preview/preview/preview-app/src/environments/environment.ts b/angular/devkit/preview/preview/preview-app/src/environments/environment.ts deleted file mode 100644 index 99c3763c..00000000 --- a/angular/devkit/preview/preview/preview-app/src/environments/environment.ts +++ /dev/null @@ -1,16 +0,0 @@ -// This file can be replaced during build by using the `fileReplacements` array. -// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. -// The list of file replacements can be found in `angular.json`. - -export const environment = { - production: false, -}; - -/* - * For easier debugging in development mode, you can import the following file - * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. - * - * This import should be commented out in production mode because it will have a negative impact - * on performance if an error is thrown. - */ -// import 'zone.js/dist/zone-error'; // Included with Angular CLI. diff --git a/angular/devkit/preview/preview/preview-app/src/polyfills.ts b/angular/devkit/preview/preview/preview-app/src/polyfills.ts index 8494ac9c..8827b010 100644 --- a/angular/devkit/preview/preview/preview-app/src/polyfills.ts +++ b/angular/devkit/preview/preview/preview-app/src/polyfills.ts @@ -57,7 +57,7 @@ /** ************************************************************************************************* * Zone JS is required by default for Angular itself. */ -import 'zone.js/dist/zone'; // Included with Angular CLI. +import 'zone.js'; // Included with Angular CLI. /** ************************************************************************************************* * APPLICATION IMPORTS diff --git a/angular/devkit/preview/preview/preview-app/src/test.ts b/angular/devkit/preview/preview/preview-app/src/test.ts index 4f56cf52..0fc6e7bd 100644 --- a/angular/devkit/preview/preview/preview-app/src/test.ts +++ b/angular/devkit/preview/preview/preview-app/src/test.ts @@ -1,6 +1,6 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files -import 'zone.js/dist/zone-testing'; +import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; diff --git a/angular/devkit/preview/runtime/loader.ts b/angular/devkit/preview/runtime/loader.ts index 30d01aec..48e638ef 100644 --- a/angular/devkit/preview/runtime/loader.ts +++ b/angular/devkit/preview/runtime/loader.ts @@ -2,7 +2,7 @@ // Only load those if we are in the browser if (typeof window !== 'undefined') { require('./native-shim.js'); - require('zone.js/dist/zone'); + require('zone.js'); } import { Injector, NgModuleRef, Type } from '@angular/core'; import { createCustomElement } from '@angular/elements'; diff --git a/angular/devkit/preview/runtime/main.ts b/angular/devkit/preview/runtime/main.ts index 21d4af82..a75c2f56 100644 --- a/angular/devkit/preview/runtime/main.ts +++ b/angular/devkit/preview/runtime/main.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -require('zone.js/dist/zone'); +require('zone.js'); const i0 = require('@angular/core') as any; import { BrowserModule } from '@angular/platform-browser'; diff --git a/angular/envs/angular-env/component.json b/angular/envs/angular-env/component.json index 750c88f4..29385b37 100644 --- a/angular/envs/angular-env/component.json +++ b/angular/envs/angular-env/component.json @@ -24,6 +24,7 @@ "@angular/elements": "~16.2.0", "@angular/platform-browser": "~16.2.0", "@angular/platform-browser-dynamic": "~16.2.0", + "@jest/globals": "^29.3.1", "@ngtools/webpack": "~16.2.0", "@types/eslint": "^8.40.0", "@types/jest": "^29.5.0", @@ -56,7 +57,7 @@ "webpack": "5.81.0", "webpack-dev-middleware": "6.0.2", "webpack-dev-server": "4.13.3", - "zone.js": "~0.13.0" + "zone.js": "~0.14.0" }, "peerDependencies": { "rxjs": "^6.5.5 || ^7.4.0" diff --git a/angular/envs/angular-env/env.jsonc b/angular/envs/angular-env/env.jsonc index c357a9ed..b53502c9 100644 --- a/angular/envs/angular-env/env.jsonc +++ b/angular/envs/angular-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "0.13.1", - "supportedRange": "0.13.1" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/envs/angular-v12-env/component.json b/angular/envs/angular-v12-env/component.json index bcd410d5..ffc9949b 100644 --- a/angular/envs/angular-v12-env/component.json +++ b/angular/envs/angular-v12-env/component.json @@ -50,7 +50,7 @@ "webpack": "^5.37.0", "webpack-dev-middleware": "5.1.0", "webpack-dev-server": "4.3.1", - "zone.js": "~0.11.4" + "zone.js": "~0.14.0" } } } diff --git a/angular/envs/angular-v12-env/env.jsonc b/angular/envs/angular-v12-env/env.jsonc index a1c85389..4b294c97 100644 --- a/angular/envs/angular-v12-env/env.jsonc +++ b/angular/envs/angular-v12-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.11.4", - "supportedRange": "~0.11.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/envs/angular-v13-env/component.json b/angular/envs/angular-v13-env/component.json index 793da6ff..1fb5cadb 100644 --- a/angular/envs/angular-v13-env/component.json +++ b/angular/envs/angular-v13-env/component.json @@ -50,7 +50,7 @@ "webpack": "5.60.0", "webpack-dev-middleware": "5.2.1", "webpack-dev-server": "4.4.0", - "zone.js": "~0.11.4" + "zone.js": "~0.14.0" } } } diff --git a/angular/envs/angular-v13-env/env.jsonc b/angular/envs/angular-v13-env/env.jsonc index d05d8309..b32e0f4f 100644 --- a/angular/envs/angular-v13-env/env.jsonc +++ b/angular/envs/angular-v13-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.11.4", - "supportedRange": "~0.11.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/envs/angular-v14-env/component.json b/angular/envs/angular-v14-env/component.json index 010805f7..6ba4c330 100644 --- a/angular/envs/angular-v14-env/component.json +++ b/angular/envs/angular-v14-env/component.json @@ -58,7 +58,7 @@ "webpack": "5.72.1", "webpack-dev-middleware": "5.2.1", "webpack-dev-server": "4.4.0", - "zone.js": "~0.11.6" + "zone.js": "~0.14.0" } } } diff --git a/angular/envs/angular-v14-env/env.jsonc b/angular/envs/angular-v14-env/env.jsonc index db56efa5..e72572ec 100644 --- a/angular/envs/angular-v14-env/env.jsonc +++ b/angular/envs/angular-v14-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.11.6", - "supportedRange": "~0.11.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/envs/angular-v15-env/component.json b/angular/envs/angular-v15-env/component.json index d216a383..4ce60e4f 100644 --- a/angular/envs/angular-v15-env/component.json +++ b/angular/envs/angular-v15-env/component.json @@ -58,7 +58,7 @@ "webpack": "5.75.0", "webpack-dev-middleware": "6.0.1", "webpack-dev-server": "4.11.1", - "zone.js": "~0.12.0" + "zone.js": "~0.14.0" } } } diff --git a/angular/envs/angular-v15-env/env.jsonc b/angular/envs/angular-v15-env/env.jsonc index 337ca901..d3cf253f 100644 --- a/angular/envs/angular-v15-env/env.jsonc +++ b/angular/envs/angular-v15-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.12.0", - "supportedRange": "~0.12.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/envs/angular-v16-env/angular-v16-env.bit-env.ts b/angular/envs/angular-v16-env/angular-v16-env.bit-env.ts index 310a18a1..871d0973 100644 --- a/angular/envs/angular-v16-env/angular-v16-env.bit-env.ts +++ b/angular/envs/angular-v16-env/angular-v16-env.bit-env.ts @@ -61,7 +61,7 @@ export class AngularV16Env extends AngularBaseEnv { webpackOptions: webpackOptions as any }); } - return this.super(); + return super.getDevServer(devServerContext, ngEnvOptions, transformers as WebpackConfigTransformer[], angularOptions, webpackOptions, sourceRoot); } } diff --git a/angular/envs/angular-v16-env/component.json b/angular/envs/angular-v16-env/component.json index 7edac032..59afd1f9 100644 --- a/angular/envs/angular-v16-env/component.json +++ b/angular/envs/angular-v16-env/component.json @@ -25,6 +25,7 @@ "@angular/elements": "~16.2.0", "@angular/platform-browser": "~16.2.0", "@angular/platform-browser-dynamic": "~16.2.0", + "@jest/globals": "^29.3.1", "@ngtools/webpack": "~16.2.0", "@types/eslint": "^8.40.0", "@types/jest": "^29.5.0", @@ -57,7 +58,7 @@ "webpack": "5.81.0", "webpack-dev-middleware": "6.0.2", "webpack-dev-server": "4.13.3", - "zone.js": "~0.13.0" + "zone.js": "~0.14.0" }, "peerDependencies": { "rxjs": "^6.5.5 || ^7.4.0" diff --git a/angular/envs/angular-v16-env/env.jsonc b/angular/envs/angular-v16-env/env.jsonc index c357a9ed..b53502c9 100644 --- a/angular/envs/angular-v16-env/env.jsonc +++ b/angular/envs/angular-v16-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "0.13.1", - "supportedRange": "0.13.1" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/envs/angular-v17-env/angular-v17-env.bit-env.ts b/angular/envs/angular-v17-env/angular-v17-env.bit-env.ts new file mode 100644 index 00000000..72cb2e0c --- /dev/null +++ b/angular/envs/angular-v17-env/angular-v17-env.bit-env.ts @@ -0,0 +1,68 @@ +import { + AngularEnvOptions, + BrowserOptions, + DevServerOptions, + isAppDevContext +} from '@bitdev/angular.dev-services.common'; +import { NgViteDevServer, ViteConfigTransformer } from '@bitdev/angular.dev-services.vite'; +import { AngularBaseEnv } from '@bitdev/angular.envs.base-env'; +import { DevServer, DevServerContext } from '@teambit/bundler'; +import { AsyncEnvHandler } from '@teambit/envs'; +import { NativeCompileCache } from '@teambit/toolbox.performance.v8-cache'; +import { + Configuration, + WebpackConfigTransformer, + WebpackConfigWithDevServer +} from '@teambit/webpack'; +import { webpackConfigFactory } from './webpack-config.factory'; + +// Disable v8-caching because it breaks ESM loaders +NativeCompileCache.uninstall(); + +export class AngularV17Env extends AngularBaseEnv { + /** + * name of the environment. used for friendly mentions across bit. + */ + name = 'angular-v17-env'; + + angularVersion = 17; + + ngEnvOptions: AngularEnvOptions = { + useNgcc: false, + useAngularElementsPreview: false, + // angularElementsModulePath: require.resolve('@angular/elements'), + jestConfigPath: require.resolve('./jest/jest.config'), + jestModulePath: require.resolve('jest'), + ngPackagrModulePath: require.resolve('ng-packagr'), + readDefaultTsConfig: require.resolve('ng-packagr/lib/ts/tsconfig'), + webpackConfigFactory, + webpackDevServerModulePath: require.resolve('webpack-dev-server'), + // resolving to the webpack used by angular devkit to avoid multiple instances of webpack + // otherwise, if we use a different version, it would break + webpackModulePath: require.resolve('webpack', { paths: [require.resolve('@angular-devkit/build-angular')] }), + devServer: 'webpack', + }; + + override getDevServer( + devServerContext: DevServerContext, + ngEnvOptions: AngularEnvOptions, + transformers: (WebpackConfigTransformer | ViteConfigTransformer)[] = [], + angularOptions: Partial = {}, + webpackOptions: Partial = {}, + sourceRoot?: string + ): AsyncEnvHandler { + if (this.ngEnvOptions.devServer === 'vite' && isAppDevContext(devServerContext)) { + return NgViteDevServer.from({ + angularOptions, + devServerContext, + ngEnvOptions, + sourceRoot, + transformers, + webpackOptions: webpackOptions as any + }); + } + return super.getDevServer(devServerContext, ngEnvOptions, transformers as WebpackConfigTransformer[], angularOptions, webpackOptions, sourceRoot); + } +} + +export default new AngularV17Env(); diff --git a/angular/envs/angular-v17-env/angular-v17-env.docs.mdx b/angular/envs/angular-v17-env/angular-v17-env.docs.mdx new file mode 100644 index 00000000..b7c9cba0 --- /dev/null +++ b/angular/envs/angular-v17-env/angular-v17-env.docs.mdx @@ -0,0 +1,85 @@ +--- +description: A Bit development environment for Angular Components +labels: ['angular', 'environment', 'env', 'aspect', 'extension'] +--- + +import { EnvOverview } from '@teambit/envs.docs.env-overview-template'; + + diff --git a/angular/envs/angular-v17-env/component.json b/angular/envs/angular-v17-env/component.json new file mode 100644 index 00000000..0aef50fa --- /dev/null +++ b/angular/envs/angular-v17-env/component.json @@ -0,0 +1,69 @@ +{ + "componentId": { + "name": "envs/angular-v17-env", + "scope": "bitdev.angular" + }, + "propagate": true, + "extensions": { + "teambit.dependencies/dependency-resolver": { + "policy": { + "dependencies": { + "@angular-devkit/architect": "0.1700.0-next.7", + "@angular-devkit/build-angular": "^17.0.0-next.0", + "@angular-devkit/build-webpack": "0.1700.0-next.7", + "@angular-devkit/core": "^17.0.0-next.0", + "@angular-devkit/schematics": "^17.0.0-next.0", + "@angular-eslint/eslint-plugin": "~16.1.1", + "@angular-eslint/eslint-plugin-template": "~16.1.1", + "@angular-eslint/template-parser": "~16.1.1", + "@angular/animations": "^17.0.0-next.0", + "@angular/common": "^17.0.0-next.0", + "@angular/compiler": "^17.0.0-next.0", + "@angular/compiler-cli": "^17.0.0-next.0", + "@angular/cli": "^17.0.0-next.0", + "@angular/core": "^17.0.0-next.0", + "@angular/elements": "^17.0.0-next.0", + "@angular/platform-browser": "^17.0.0-next.0", + "@angular/platform-browser-dynamic": "^17.0.0-next.0", + "@jest/globals": "^29.3.1", + "@ngtools/webpack": "^17.0.0-next.0", + "@types/eslint": "^8.40.0", + "@types/jest": "^29.5.0", + "@types/react-dev-utils": "~9.0.8", + "@types/remark-prism": "~1.3.0", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "css-loader": "6.7.3", + "eslint": "^8.40.0", + "events": "^3.2.0", + "html-loader": "~2.1.2", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.0.3", + "jest-environment-node": "^29.0.3", + "jest-preset-angular": "~13.1.0", + "ng-packagr": "^17.0.0-next.0", + "postcss": "8.4.23", + "postcss-flexbugs-fixes": "5.0.2", + "postcss-loader": "7.2.4", + "postcss-preset-env": "7.8.2", + "remark": "~13.0.0", + "remark-loader": "~4.0.0", + "resolve-url-loader": "5.0.0", + "sass": "1.65.1", + "sass-loader": "13.3.2", + "style-loader": "^2.0.0", + "ts-node": "^10.9.1", + "tslib": "^2.6.1", + "typescript": "~5.2.2", + "webpack": "5.81.0", + "webpack-dev-middleware": "6.0.2", + "webpack-dev-server": "4.13.3", + "zone.js": "~0.14.0" + }, + "peerDependencies": { + "rxjs": "~7.8.0" + } + } + } + } +} diff --git a/angular/envs/angular-v17-env/env.jsonc b/angular/envs/angular-v17-env/env.jsonc new file mode 100644 index 00000000..4d347e5e --- /dev/null +++ b/angular/envs/angular-v17-env/env.jsonc @@ -0,0 +1,111 @@ +/** + * define the peer dependencies for your environment. + * these components would be resolved once for all components in + * in the dependency graph of your component. + **/ +{ + "policy": { + "runtime": [ + { + "name": "tslib", + "version": "^2.6.1", + "supportedRange": "^2.3.0" + } + ], + /** + * dev dependencies resolved in the workspace + * for components using this env. these dependencies would not be defined + * as a direct component dependencies. they are used for component development only. + **/ + "dev": [ + { + "name": "@types/jest", + "version": "^29.5.0", + "supportedRange": "^29.0.0", + "hidden": true, + "force": true + }, + { + "name": "@types/node", + "version": "^16.11.7", + "hidden": true, + "force": true + }, + { + "name": "jest-preset-angular", + "version": "~13.1.0", + "supportedRange": "~13.1.0", + "hidden": true, + "force": true + } + ], + "peers": [ + { + "name": "@angular/common", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "@angular/compiler", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0", + }, + { + "name": "@angular/compiler-cli", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0", + }, + { + "name": "@angular/core", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "@angular/platform-browser", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "@angular/platform-browser-dynamic", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "jest", + "version": "^29.5.0", + "supportedRange": "^29.5.0", + }, + { + "name": "rxjs", + "version": "^7.8.1", + "supportedRange": "^7.8.0" + }, + { + "name": "tslib", + "version": "^2.6.1", + "supportedRange": "^2.3.0" + }, + { + "name": "typescript", + "version": "~5.2.2", + "supportedRange": ">=5.2 <5.3" + }, + { + "name": "zone.js", + "version": "~0.14.0", + "supportedRange": "~0.14.0" + } + ] + }, + + /** + * used to define patterns to different + * files in your component and associate them with + * bit aspects. + **/ + "patterns": { + "compositions": ["**/*.composition.*", "**/*.preview.*"], + "docs": ["**/*.docs.*"], + "tests": ["**/*.spec.*", "**/*.test.*", "**/*.cy.*"], + } +} diff --git a/angular/envs/angular-v17-env/index.ts b/angular/envs/angular-v17-env/index.ts new file mode 100644 index 00000000..ce036ab5 --- /dev/null +++ b/angular/envs/angular-v17-env/index.ts @@ -0,0 +1,2 @@ +export { AngularV17Env } from './angular-v17-env.bit-env'; +export { default as jestConfig } from './jest/jest.config'; diff --git a/angular/envs/angular-v17-env/jest/jest-global-mocks.ts b/angular/envs/angular-v17-env/jest/jest-global-mocks.ts new file mode 100644 index 00000000..3199357e --- /dev/null +++ b/angular/envs/angular-v17-env/jest/jest-global-mocks.ts @@ -0,0 +1,31 @@ +import { jest } from '@jest/globals'; + +Object.defineProperty(window, 'CSS', { value: null }); + +Object.defineProperty(document, 'doctype', { + value: '', +}); + +Object.defineProperty(window, 'getComputedStyle', { + value: () => { + return { + display: 'none', + appearance: ['-webkit-appearance'], + }; + }, +}); + +/** + * ISSUE: https://github.com/angular/material2/issues/7101 + * Workaround for JSDOM missing transform property + */ +Object.defineProperty(document.body.style, 'transform', { + value: () => { + return { + enumerable: true, + configurable: true, + }; + }, +}); + +HTMLCanvasElement.prototype.getContext = jest.fn(); diff --git a/angular/envs/angular-v17-env/jest/jest.config.ts b/angular/envs/angular-v17-env/jest/jest.config.ts new file mode 100644 index 00000000..d0214580 --- /dev/null +++ b/angular/envs/angular-v17-env/jest/jest.config.ts @@ -0,0 +1,35 @@ +import { generateNodeModulesPattern } from '@teambit/dependencies.modules.packages-excluder'; + +const { defaultTransformerOptions } = require('jest-preset-angular/presets'); + +const packagesToExclude: string[] = ['@angular', '@ngrx']; + +export default { + preset: 'jest-preset-angular', + reporters: ['default'], + setupFilesAfterEnv: [require.resolve('jest-preset-angular/setup-jest')], + testPathIgnorePatterns: ['/.*/e2e/'], + globals: { + ngJest: { + skipNgcc: true + } + }, + resolver: require.resolve('./jest.resolver.js'), + moduleDirectories: ['/node_modules', 'node_modules'], + transform: { + '^.+\\.(ts|js|mjs|html|svg)$': [ + 'jest-preset-angular', + { + ...defaultTransformerOptions, + tsconfig: require.resolve('./tsconfig.spec.json') + } + ] + }, + transformIgnorePatterns: [ + '^.+.module.(css|sass|scss)$', + generateNodeModulesPattern({ + packages: packagesToExclude, + excludeComponents: true + }) + ] +}; diff --git a/angular/envs/angular-v17-env/jest/jest.resolver.ts b/angular/envs/angular-v17-env/jest/jest.resolver.ts new file mode 100644 index 00000000..7b076012 --- /dev/null +++ b/angular/envs/angular-v17-env/jest/jest.resolver.ts @@ -0,0 +1,35 @@ +import { PackageJsonProps } from "@teambit/pkg"; + +module.exports = (path: string, options: any) => { + // Call the defaultResolver, so we leverage its cache, error handling, etc. + return options.defaultResolver(path, { + ...options, + // Use packageFilter to process parsed `package.json` before the resolution (see https://www.npmjs.com/package/resolve#resolveid-opts-cb) + packageFilter: (pkg: PackageJsonProps) => { + const pkgNamesToTarget = new Set([ + 'rxjs', + '@firebase/auth', + '@firebase/storage', + '@firebase/functions', + '@firebase/database', + '@firebase/auth-compat', + '@firebase/database-compat', + '@firebase/app-compat', + '@firebase/firestore', + '@firebase/firestore-compat', + '@firebase/messaging', + '@firebase/util', + 'firebase', + ]); + + if (pkgNamesToTarget.has(pkg.name)) { + // eslint-disable-next-line no-param-reassign + delete pkg.exports; + // eslint-disable-next-line no-param-reassign + delete pkg.module; + } + + return pkg; + }, + }); +}; diff --git a/angular/envs/angular-v17-env/jest/tsconfig.spec.json b/angular/envs/angular-v17-env/jest/tsconfig.spec.json new file mode 100644 index 00000000..351c2d4d --- /dev/null +++ b/angular/envs/angular-v17-env/jest/tsconfig.spec.json @@ -0,0 +1,36 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc/spec", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "importHelpers": true, + "allowJs": true, + "target": "es2020", + "module": "esnext", + "lib": [ + "es2018", + "dom" + ], + "types": ["jest", "node"] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true, + "enableIvy": true + }, + "include": ["**/*.spec.+(js|ts)", "**/*.test.+(js|ts)", "**/*.d.ts"] +} diff --git a/angular/envs/angular-v17-env/webpack-config.factory.ts b/angular/envs/angular-v17-env/webpack-config.factory.ts new file mode 100644 index 00000000..2e3c50be --- /dev/null +++ b/angular/envs/angular-v17-env/webpack-config.factory.ts @@ -0,0 +1,267 @@ +/* eslint-disable no-param-reassign */ +import type { BrowserBuilderOptions, DevServerBuilderOptions } from '@angular-devkit/build-angular'; +import { OutputHashing } from '@angular-devkit/build-angular'; +import { + getCommonConfig, + getDevServerConfig, + getStylesConfig, + IndexHtmlWebpackPlugin, + normalizeCacheOptions, + generateEntryPoints, + generateWebpackConfig, + getIndexOutputFile, + normalizeBrowserSchema, + normalizeOptimization +} from '@bitdev/angular.dev-services.ng-compat'; +import { getSystemPath, logging, normalize, tags } from '@angular-devkit/core'; +import { BundlerSetup } from '@bitdev/angular.dev-services.common'; +import { + WebpackBuildConfigFactoryOpts, + WebpackConfig, + WebpackConfigFactoryOpts, + WebpackServeConfigFactoryOpts +} from '@bitdev/angular.dev-services.webpack'; +import { BundlerContext, DevServerContext } from '@teambit/bundler'; +import { Logger } from '@teambit/logger'; +import { + runTransformersWithContext, + WebpackConfigMutator, + WebpackConfigTransformer, + WebpackConfigWithDevServer +} from '@teambit/webpack'; +import path, { join } from 'path'; +import type { Configuration } from 'webpack'; +import { webpack5BuildConfigFactory } from './webpack/webpack5.build.config'; +import { webpack5ServeConfigFactory } from './webpack/webpack5.serve.config'; + +/** + * Migrate options from webpack-dev-server 3 to 4 + */ +function migrateConfiguration(webpackConfig: any): WebpackConfigWithDevServer | Configuration { + /** + * Removed logLevel in favor of built-in logger + * see https://webpack.js.org/configuration/other-options/#infrastructurelogginglevel + */ + delete webpackConfig.devServer.logLevel; + + // Removed contentBase in favor of the static option + delete webpackConfig.devServer.contentBase; + + // Removed publicPath in favor of the dev option + delete webpackConfig.devServer.publicPath; + + // Moved overlay to client option + webpackConfig.devServer.client = webpackConfig.devServer.client || {}; + webpackConfig.devServer.client.overlay = webpackConfig.devServer.overlay; + delete webpackConfig.devServer.overlay; + + // Removed in favor of the static option + delete webpackConfig.devServer.watchOptions; + + // Moved sockPath to client.webSocketURL.pathname option + // We let webpack handle that now + delete webpackConfig.devServer.sockPath; + + // Removed stats in favor of the stats options from webpack + delete webpackConfig.devServer.stats; + + // Removed in favor client.webSocketURL options + delete webpackConfig.devServer.public; + + // Removed watch to avoid "DEP_WEBPACK_WATCH_WITHOUT_CALLBACK" warning + delete webpackConfig.watch; + + // Removed in favor of manual setup entries. + delete webpackConfig.devServer.injectClient; + + // Cleaning up undefined values + Object.keys(webpackConfig.devServer).forEach((option) => { + if (typeof webpackConfig.devServer[option] === 'undefined') { + delete webpackConfig.devServer[option]; + } + }); + + delete webpackConfig.devServer.devMiddleware.publicPath; + delete webpackConfig.devServer.webSocketServer; + delete webpackConfig.devServer.client; + + return webpackConfig; +} + +async function getWebpackConfig( + _context: DevServerContext | BundlerContext, + entryFiles: string[], + tsconfigPath: string, + workspaceRoot: string, + logger: Logger, + setup: BundlerSetup, + webpackOptions: Partial = {}, + angularOptions: Partial = {}, + sourceRoot = 'src' +): Promise { + // Options from angular.json + const browserOptions: BrowserBuilderOptions = { + ...angularOptions, + baseHref: angularOptions.baseHref ?? './', + preserveSymlinks: false, + outputPath: 'public', // doesn't matter because it will be deleted from the config + index: angularOptions.index ?? `./${join(sourceRoot, `index.html`)}`, + main: angularOptions.main ?? `./${join(sourceRoot, `main.ts`)}`, + polyfills: angularOptions.polyfills ?? `./${join(sourceRoot, `polyfills.ts`)}`, + tsConfig: angularOptions.tsConfig ?? tsconfigPath, + assets: [...new Set([path.posix.join(sourceRoot, `assets/**/*`), ...(angularOptions.assets ?? [])])], // using set to remove duplicates + styles: [...new Set([path.posix.join(sourceRoot, `styles.scss`), ...(angularOptions.styles ?? [])])], // using set to remove duplicates + scripts: angularOptions.scripts, + vendorChunk: angularOptions.vendorChunk ?? true, + namedChunks: angularOptions.namedChunks ?? true, + optimization: angularOptions.optimization ?? setup === BundlerSetup.Build, + buildOptimizer: angularOptions.buildOptimizer ?? setup === BundlerSetup.Build, + aot: angularOptions.aot ?? true, + deleteOutputPath: angularOptions.deleteOutputPath ?? true, + sourceMap: angularOptions.sourceMap ?? true, + outputHashing: angularOptions.outputHashing ?? (setup === BundlerSetup.Build ? OutputHashing.All : OutputHashing.None), + watch: setup === BundlerSetup.Serve, + allowedCommonJsDependencies: ['dompurify', '@teambit/harmony', 'graphql', '@teambit/documenter.ng.content.copy-box', ...(angularOptions.allowedCommonJsDependencies || [])] + }; + const normalizedWorkspaceRoot = normalize(workspaceRoot); + // used to load component config files, such as tailwind config, ... + const projectRoot = normalize(workspaceRoot); + const normalizedSourceRoot = normalize(sourceRoot); + const loggerApi = { + createChild: () => logger as any, + ...logger, + log: logger.console + } as any as logging.LoggerApi; + console.log(browserOptions); + const normalizedOptions = normalizeBrowserSchema( + normalizedWorkspaceRoot, + projectRoot, + normalizedSourceRoot, + { + ...browserOptions, + ...(webpackOptions as Partial) + }, + { + cli: { + cache: { + // disable webpack cache for now because it seems to cause an infinite loop + // TODO(ocombe): investigate this, maybe change the path? + enabled: false + } + } + }, + loggerApi + ); + + let webpackConfig: any = await generateWebpackConfig( + getSystemPath(normalizedWorkspaceRoot), + getSystemPath(projectRoot), + getSystemPath(normalizedSourceRoot), + 'bit-angular-v16-env', // projectName + normalizedOptions, + (wco: any) => [ + setup === BundlerSetup.Serve ? getDevServerConfig(wco) : {}, + getCommonConfig(wco), + getStylesConfig(wco) + ], + loggerApi, + {} + ); + + // @ts-ignore + if (webpackOptions.hmr) { + logger.warn(tags.stripIndents`NOTICE: Hot Module Replacement (HMR) is enabled for the dev server. + See https://webpack.js.org/guides/hot-module-replacement for information on working with HMR for Webpack.`); + } + + // Add bit generated files to the list of entries + webpackConfig.entry.main.unshift(...entryFiles); + // webpackConfig.entry.main = entryFiles; + + const { scripts = [], styles = [] } = browserOptions; + const entrypoints = generateEntryPoints({ scripts, styles }); + const normalizedIndex = normalize(browserOptions.index as string); + const normalizedOptimization = normalizeOptimization(browserOptions.optimization); + if (!webpackConfig.plugins) { + webpackConfig.plugins = []; + } + const cacheOptions = normalizeCacheOptions({}, workspaceRoot); + webpackConfig.plugins.push( + new IndexHtmlWebpackPlugin({ + indexPath: path.resolve(workspaceRoot, browserOptions.index as string), + outputPath: getIndexOutputFile(normalizedIndex), + baseHref: browserOptions.baseHref || '/', + entrypoints, + deployUrl: browserOptions.deployUrl, + sri: browserOptions.subresourceIntegrity, + cache: cacheOptions, + postTransform: undefined, // IndexHtmlTransform + optimization: normalizedOptimization, + crossOrigin: browserOptions.crossOrigin, + lang: 'en-US' // TODO(ocombe) support locale + }) + ); + + // don't use the output path from angular + delete webpackConfig?.output?.path; + delete webpackConfig?.resolve?.modules; + webpackConfig.stats = 'errors-only'; + // uniqueName should not be an empty string + webpackConfig.output.uniqueName = 'angular-v17-env'; + + if (setup === BundlerSetup.Serve) { + webpackConfig = migrateConfiguration(webpackConfig); + } + + return webpackConfig; +} + +export async function webpackConfigFactory(opts: WebpackConfigFactoryOpts & WebpackServeConfigFactoryOpts & WebpackBuildConfigFactoryOpts): Promise { + const baseConfig = await getWebpackConfig( + opts.context, + opts.entryFiles, + opts.tsConfigPath, + opts.rootPath, + opts.logger, + opts.setup, + opts.webpackOptions, + opts.angularOptions, + opts.sourceRoot + ) as WebpackConfigWithDevServer; + + let overwriteConfig: WebpackConfigWithDevServer; + if (opts.setup === BundlerSetup.Serve) { + overwriteConfig = webpack5ServeConfigFactory( + opts.devServerID, + opts.workspaceDir, + opts.entryFiles, + opts.publicRoot, + opts.publicPath, + opts.pubsub, + opts.nodeModulesPaths, + opts.tempFolder, + opts.plugins, + opts.isApp, + opts.useNgcc + ); + } else { + overwriteConfig = webpack5BuildConfigFactory( + opts.entryFiles, + opts.outputPath, + opts.nodeModulesPaths, + opts.workspaceDir, + opts.tempFolder, + opts.plugins, + opts.useNgcc + ) as WebpackConfigWithDevServer; + } + + const transformer: WebpackConfigTransformer = configMutator => configMutator.merge([baseConfig]); + const configMutator = new WebpackConfigMutator(overwriteConfig); + const afterMutation = runTransformersWithContext( + configMutator.clone(), + [transformer], + { mode: 'dev' } + ); + return afterMutation.raw as WebpackConfigWithDevServer; +} diff --git a/angular/envs/angular-v17-env/webpack/module-rules.config.ts b/angular/envs/angular-v17-env/webpack/module-rules.config.ts new file mode 100644 index 00000000..b154bb3a --- /dev/null +++ b/angular/envs/angular-v17-env/webpack/module-rules.config.ts @@ -0,0 +1,115 @@ +import { generateStyleLoaders } from '@teambit/webpack.modules.generate-style-loaders'; +import * as stylesRegexps from '@teambit/webpack.modules.style-regexps'; +import { merge } from 'lodash'; +import getCSSModuleLocalIdent from 'react-dev-utils/getCSSModuleLocalIdent'; +import RemarkFrontmatter from 'remark-frontmatter'; +import RemarkHTML from 'remark-html'; +import RemarkPrism from 'remark-prism'; +import { RuleSetRule } from 'webpack'; + +const postCssConfig = { + // Necessary for external CSS imports to work + // https://github.com/facebook/create-react-app/issues/2677 + ident: 'postcss', + plugins: [ + // eslint-disable-next-line global-require + require.resolve('postcss-flexbugs-fixes'), + // eslint-disable-next-line global-require + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + // Adds PostCSS Normalize as the reset css with default options, + // so that it honors browserslist config in package.json + // which in turn lets users customize the target behavior as per their needs. + // require.resolve('postcss-normalize'), + ], +}; + +const styleLoaderPath = require.resolve('style-loader'); + +// Source maps are resource heavy and can cause out of memory issue for large source files. +const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; + +export function getModuleRulesConfig(isEnvProduction: boolean): RuleSetRule[] { + const baseStyleLoadersOptions = { + injectingLoader: styleLoaderPath, + cssLoaderPath: require.resolve('css-loader'), + postCssLoaderPath: require.resolve('postcss-loader'), + postCssConfig + }; + + return [ + { + test: /\.m?js/, + resolve: { + fullySpecified: false + } + }, + { + // "oneOf" will traverse all following loaders until one will + // match the requirements. When no loader matches it will fall + // back to the "file" loader at the end of the loader list. + oneOf: [ + // MDX support + { + test: /\.md$/, + use: [ + { + loader: 'html-loader' + }, + { + loader: 'remark-loader', + options: { + removeFrontMatter: false, + remarkOptions: { + plugins: [RemarkPrism, RemarkHTML, RemarkFrontmatter] + } + } + } + ] + }, + // Adds support for CSS Modules (https://github.com/css-modules/css-modules) + // using the extension .module.css + { + test: stylesRegexps.cssModuleRegex, + use: generateStyleLoaders( + merge({}, baseStyleLoadersOptions, { + cssLoaderOpts: { + importLoaders: 1, + sourceMap: isEnvProduction || shouldUseSourceMap, + modules: { + getLocalIdent: getCSSModuleLocalIdent + } + }, + shouldUseSourceMap: isEnvProduction || shouldUseSourceMap + }) + ) + }, + // Adds support for CSS Modules, but using SASS + // using the extension .module.scss or .module.sass + { + test: stylesRegexps.sassModuleRegex, + use: generateStyleLoaders( + merge({}, baseStyleLoadersOptions, { + cssLoaderOpts: { + importLoaders: 3, + sourceMap: isEnvProduction || shouldUseSourceMap, + modules: { + getLocalIdent: getCSSModuleLocalIdent + } + }, + shouldUseSourceMap: isEnvProduction || shouldUseSourceMap, + preProcessOptions: { + resolveUrlLoaderPath: require.resolve('resolve-url-loader'), + preProcessorPath: require.resolve('sass-loader') + } + }) + ) + } + ] + } + ]; +} diff --git a/angular/envs/angular-v17-env/webpack/webpack5.build.config.ts b/angular/envs/angular-v17-env/webpack/webpack5.build.config.ts new file mode 100644 index 00000000..d263fc6e --- /dev/null +++ b/angular/envs/angular-v17-env/webpack/webpack5.build.config.ts @@ -0,0 +1,59 @@ +import { BitDedupeModuleResolvePlugin, WebpackConfig } from '@bitdev/angular.dev-services.webpack'; +import { fallbacks, fallbacksAliases, fallbacksProvidePluginConfig } from '@teambit/webpack'; +import { sep } from 'path'; +import webpack from 'webpack'; +import { getModuleRulesConfig } from './module-rules.config'; + +export function webpack5BuildConfigFactory( + entryFiles: string[], + outputPath: string, + nodeModulesPaths: string[], + workspaceDir: string, + tempFolder: string, + plugins: any[] = [], + useNgcc: boolean, +): WebpackConfig { + const config = { + mode: 'production', + // Stop compilation early in production + bail: true, + // These are the "entry points" to our application. + // This means they will be the "root" imports that are included in JS bundle. + entry: entryFiles, + + output: { + // The build folder. + path: `${outputPath}${sep}public`, + + filename: 'static/js/[name].[contenthash:8].js', + // There are also additional JS chunk files if you use code splitting. + chunkFilename: 'static/js/[name].[contenthash:8].chunk.js', + // webpack uses `publicPath` to determine where the app is being served from. + // It requires a trailing slash, or the file assets will get an incorrect path. + // We inferred the "public path" (such as / or /my-project) from homepage. + publicPath: ``, + // this defaults to 'window', but by setting it to 'this' then + // module chunks which are built will work in web workers as well. + // Commented out to use the default (self) as according to tobias with webpack5 self is working with workers as well + // globalObject: 'this', + }, + + resolve: { + alias: fallbacksAliases, + fallback: fallbacks, + modules: nodeModulesPaths + }, + + module: { + rules: getModuleRulesConfig(true) + }, + + plugins: [ + new BitDedupeModuleResolvePlugin(nodeModulesPaths, workspaceDir, tempFolder, useNgcc), + new webpack.ProvidePlugin(fallbacksProvidePluginConfig), + ...plugins + ], + }; + + return config as WebpackConfig; +} diff --git a/angular/envs/angular-v17-env/webpack/webpack5.serve.config.ts b/angular/envs/angular-v17-env/webpack/webpack5.serve.config.ts new file mode 100644 index 00000000..45d16db6 --- /dev/null +++ b/angular/envs/angular-v17-env/webpack/webpack5.serve.config.ts @@ -0,0 +1,176 @@ +import { BitDedupeModuleResolvePlugin, StatsLoggerPlugin } from '@bitdev/angular.dev-services.webpack'; +import { pathNormalizeToLinux } from '@teambit/legacy/dist/utils'; +import { PubsubMain } from '@teambit/pubsub'; +import { + fallbacks, + fallbacksAliases, + fallbacksProvidePluginConfig, + WebpackBitReporterPlugin, + WebpackConfigWithDevServer +} from '@teambit/webpack'; +import { join, posix, resolve } from 'path'; +import errorOverlayMiddleware from 'react-dev-utils/errorOverlayMiddleware'; +import evalSourceMapMiddleware from 'react-dev-utils/evalSourceMapMiddleware'; +import getPublicUrlOrPath from 'react-dev-utils/getPublicUrlOrPath'; +import noopServiceWorkerMiddleware from 'react-dev-utils/noopServiceWorkerMiddleware'; +import redirectServedPath from 'react-dev-utils/redirectServedPathMiddleware'; +import { ProvidePlugin } from 'webpack'; +import { getModuleRulesConfig } from './module-rules.config'; + +const publicUrlOrPath = getPublicUrlOrPath(process.env.NODE_ENV === 'development', '/', '/public'); + +export function webpack5ServeConfigFactory( + devServerID: string, + workspaceDir: string, + entryFiles: string[], + publicRoot: string, + publicPath: string, + pubsub: PubsubMain, + nodeModulesPaths: string[], + tempFolder: string, + plugins: any[] = [], + isApp = false, + useNgcc: boolean +): WebpackConfigWithDevServer { + const resolveWorkspacePath = (relativePath: string) => resolve(workspaceDir, relativePath); + + // Host + const host = process.env.HOST || 'localhost'; + + // Required for babel-preset-react-app + process.env.NODE_ENV = 'development'; + + const publicDirectory = posix.join(publicRoot, publicPath); + + if (isApp) { + plugins.push(new StatsLoggerPlugin() as any); + } + + const config = { + // Environment mode + mode: 'development', + + devtool: 'inline-source-map', + + // Entry point of app + entry: entryFiles.map((filePath) => resolveWorkspacePath(filePath)), + + output: { + // Development filename output + filename: 'static/js/[name].bundle.js', + + pathinfo: true, + + path: resolveWorkspacePath(publicDirectory), + + chunkFilename: 'static/js/[name].chunk.js', + + // point sourcemap entries to original disk locations (format as URL on windows) + devtoolModuleFilenameTemplate: (info: any) => pathNormalizeToLinux(resolve(info.absoluteResourcePath)) + + // this defaults to 'window', but by setting it to 'this' then + // module chunks which are built will work in web workers as well. + // Commented out to use the default (self) as according to tobias with webpack5 self is working with workers as well + // globalObject: 'this', + }, + + infrastructureLogging: { + level: 'error' + }, + + stats: 'errors-only', + + // @ts-ignore until types are updated with new options from webpack-dev-server v4 + devServer: { + static: [ + { + directory: resolveWorkspacePath(publicDirectory), + staticOptions: {}, + // Don't be confused with `dev.publicPath`, it is `publicPath` for static directory + // Can be: + // publicPath: ['/static-public-path-one/', '/static-public-path-two/'], + publicPath: publicDirectory, + // Can be: + // serveIndex: {} (options for the `serveIndex` option you can find https://github.com/expressjs/serve-index) + serveIndex: true, + // Can be: + // watch: {} (options for the `watch` option you can find https://github.com/paulmillr/chokidar) + watch: false + } + ], + + // Enable compression + compress: true, + + // Enable hot reloading + hot: false, + + liveReload: true, + + host, + + historyApiFallback: { + disableDotRule: true, + index: resolveWorkspacePath(publicDirectory) + }, + + client: { + overlay: false + }, + + webSocketServer: { + options: { + path: `/_hmr/${devServerID}` + // port automatically matches WDS + } + }, + + setupMiddlewares(middlewares: any, devServer: any) { + // Keep `evalSourceMapMiddleware` and `errorOverlayMiddleware` + // middlewares before `redirectServedPath` otherwise will not have any effect + // This lets us fetch source contents from webpack for the error overlay + middlewares.unshift(evalSourceMapMiddleware(devServer)); + // This lets us open files from the runtime error overlay. + middlewares.unshift(errorOverlayMiddleware()); + + // Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match + middlewares.push(redirectServedPath(publicUrlOrPath)); + // This service worker file is effectively a 'no-op' that will reset any + // previous service worker registered for the same host:port combination. + // We do this in development to avoid hitting the production cache if + // it used the same host and port. + // https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432 + middlewares.push(noopServiceWorkerMiddleware(publicUrlOrPath)); + + return middlewares; + }, + + devMiddleware: { + // Public path is root of content base + publicPath: join('/', publicRoot) + } + }, + + resolve: { + extensions: ['.ts', '.tsx', '.js', '.mdx', '.md'], + alias: fallbacksAliases, + fallback: { ...fallbacks, events: require.resolve('events/') } as any, + modules: nodeModulesPaths + }, + + module: { + rules: getModuleRulesConfig(false) + }, + + plugins: [ + new BitDedupeModuleResolvePlugin(nodeModulesPaths, workspaceDir, tempFolder, useNgcc), + new ProvidePlugin(fallbacksProvidePluginConfig), + new WebpackBitReporterPlugin({ + options: { pubsub, devServerID } + }), + ...plugins + ] + }; + + return config as WebpackConfigWithDevServer; +} diff --git a/angular/examples/my-angular-env/component.json b/angular/examples/my-angular-env/component.json index 493ca05b..5c315ebf 100644 --- a/angular/examples/my-angular-env/component.json +++ b/angular/examples/my-angular-env/component.json @@ -8,6 +8,7 @@ "teambit.dependencies/dependency-resolver": { "policy": { "dependencies": { + "@jest/globals": "^29.3.1", "@bitdev/angular.dev-services.linter.eslint": ">= 1.0.0", "@types/jest": "^29.5.0", "jest": "^29.5.0", diff --git a/angular/examples/my-angular-env/env.jsonc b/angular/examples/my-angular-env/env.jsonc index c357a9ed..b53502c9 100644 --- a/angular/examples/my-angular-env/env.jsonc +++ b/angular/examples/my-angular-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "0.13.1", - "supportedRange": "0.13.1" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/examples/my-angular-v12-env/env.jsonc b/angular/examples/my-angular-v12-env/env.jsonc index 2c40cfc5..c1281680 100644 --- a/angular/examples/my-angular-v12-env/env.jsonc +++ b/angular/examples/my-angular-v12-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.11.4", - "supportedRange": "~0.11.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/examples/my-angular-v13-env/env.jsonc b/angular/examples/my-angular-v13-env/env.jsonc index 1e2fda3f..af657c08 100644 --- a/angular/examples/my-angular-v13-env/env.jsonc +++ b/angular/examples/my-angular-v13-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.11.4", - "supportedRange": "~0.11.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/examples/my-angular-v14-env/env.jsonc b/angular/examples/my-angular-v14-env/env.jsonc index 2821b74c..ec6bf75b 100644 --- a/angular/examples/my-angular-v14-env/env.jsonc +++ b/angular/examples/my-angular-v14-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.11.6", - "supportedRange": "~0.11.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/examples/my-angular-v15-env/env.jsonc b/angular/examples/my-angular-v15-env/env.jsonc index 3925fd4b..0f4d544a 100644 --- a/angular/examples/my-angular-v15-env/env.jsonc +++ b/angular/examples/my-angular-v15-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "~0.12.0", - "supportedRange": "~0.12.0" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/examples/my-angular-v16-env/component.json b/angular/examples/my-angular-v16-env/component.json index da877220..c7d58cdd 100644 --- a/angular/examples/my-angular-v16-env/component.json +++ b/angular/examples/my-angular-v16-env/component.json @@ -8,6 +8,7 @@ "teambit.dependencies/dependency-resolver": { "policy": { "dependencies": { + "@jest/globals": "^29.3.1", "@bitdev/angular.dev-services.linter.eslint": ">= 1.0.0", "@types/jest": "^29.5.0", "jest": "^29.5.0", diff --git a/angular/examples/my-angular-v16-env/env.jsonc b/angular/examples/my-angular-v16-env/env.jsonc index c357a9ed..b53502c9 100644 --- a/angular/examples/my-angular-v16-env/env.jsonc +++ b/angular/examples/my-angular-v16-env/env.jsonc @@ -92,8 +92,8 @@ }, { "name": "zone.js", - "version": "0.13.1", - "supportedRange": "0.13.1" + "version": "~0.14.0", + "supportedRange": "~0.14.0" } ] }, diff --git a/angular/examples/my-angular-v17-env/component.json b/angular/examples/my-angular-v17-env/component.json new file mode 100644 index 00000000..1c46b70b --- /dev/null +++ b/angular/examples/my-angular-v17-env/component.json @@ -0,0 +1,20 @@ +{ + "componentId": { + "name": "examples/my-angular-v17-env", + "scope": "bitdev.angular" + }, + "propagate": true, + "extensions": { + "teambit.dependencies/dependency-resolver": { + "policy": { + "dependencies": { + "@jest/globals": "^29.3.1", + "@bitdev/angular.dev-services.linter.eslint": ">= 1.0.0", + "@types/jest": "^29.5.0", + "jest": "^29.5.0", + "jest-preset-angular": "~13.1.0" + } + } + } + } +} diff --git a/angular/examples/my-angular-v17-env/config/eslintrc.js b/angular/examples/my-angular-v17-env/config/eslintrc.js new file mode 100644 index 00000000..68b9519b --- /dev/null +++ b/angular/examples/my-angular-v17-env/config/eslintrc.js @@ -0,0 +1,7 @@ +/** + * @see https://bit.dev/reference/eslint/eslint-config + */ +module.exports = { + extends: [require.resolve('@bitdev/angular.dev-services.linter.eslint')], + rules: {}, +}; diff --git a/angular/examples/my-angular-v17-env/config/jest.config.ts b/angular/examples/my-angular-v17-env/config/jest.config.ts new file mode 100644 index 00000000..edf333d5 --- /dev/null +++ b/angular/examples/my-angular-v17-env/config/jest.config.ts @@ -0,0 +1,8 @@ +/** + * @see https://bit.dev/reference/jest/jest-config + */ +import { jestConfig } from '@bitdev/angular.envs.angular-v17-env'; + +export default { + ...jestConfig, +}; diff --git a/angular/examples/my-angular-v17-env/config/prettier.config.ts b/angular/examples/my-angular-v17-env/config/prettier.config.ts new file mode 100644 index 00000000..81493b26 --- /dev/null +++ b/angular/examples/my-angular-v17-env/config/prettier.config.ts @@ -0,0 +1,8 @@ +/** + * @see https://bit.dev/reference/prettier/prettier-config + */ +const { prettierConfig } = require('@bitdev/angular.envs.base-env'); + +module.exports = { + ...prettierConfig, +}; diff --git a/angular/examples/my-angular-v17-env/config/tsconfig.json b/angular/examples/my-angular-v17-env/config/tsconfig.json new file mode 100644 index 00000000..e32c1f2e --- /dev/null +++ b/angular/examples/my-angular-v17-env/config/tsconfig.json @@ -0,0 +1,7 @@ +/** + * @see https://bit.dev/reference/typescript/typescript-config + */ +{ + "extends": "@bitdev/angular.envs.base-env/config/tsconfig.json", + "include": ["**/*", "**/*.json"] +} diff --git a/angular/examples/my-angular-v17-env/env.jsonc b/angular/examples/my-angular-v17-env/env.jsonc new file mode 100644 index 00000000..4d347e5e --- /dev/null +++ b/angular/examples/my-angular-v17-env/env.jsonc @@ -0,0 +1,111 @@ +/** + * define the peer dependencies for your environment. + * these components would be resolved once for all components in + * in the dependency graph of your component. + **/ +{ + "policy": { + "runtime": [ + { + "name": "tslib", + "version": "^2.6.1", + "supportedRange": "^2.3.0" + } + ], + /** + * dev dependencies resolved in the workspace + * for components using this env. these dependencies would not be defined + * as a direct component dependencies. they are used for component development only. + **/ + "dev": [ + { + "name": "@types/jest", + "version": "^29.5.0", + "supportedRange": "^29.0.0", + "hidden": true, + "force": true + }, + { + "name": "@types/node", + "version": "^16.11.7", + "hidden": true, + "force": true + }, + { + "name": "jest-preset-angular", + "version": "~13.1.0", + "supportedRange": "~13.1.0", + "hidden": true, + "force": true + } + ], + "peers": [ + { + "name": "@angular/common", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "@angular/compiler", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0", + }, + { + "name": "@angular/compiler-cli", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0", + }, + { + "name": "@angular/core", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "@angular/platform-browser", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "@angular/platform-browser-dynamic", + "version": "^17.0.0-next.0", + "supportedRange": "^16.2.0" + }, + { + "name": "jest", + "version": "^29.5.0", + "supportedRange": "^29.5.0", + }, + { + "name": "rxjs", + "version": "^7.8.1", + "supportedRange": "^7.8.0" + }, + { + "name": "tslib", + "version": "^2.6.1", + "supportedRange": "^2.3.0" + }, + { + "name": "typescript", + "version": "~5.2.2", + "supportedRange": ">=5.2 <5.3" + }, + { + "name": "zone.js", + "version": "~0.14.0", + "supportedRange": "~0.14.0" + } + ] + }, + + /** + * used to define patterns to different + * files in your component and associate them with + * bit aspects. + **/ + "patterns": { + "compositions": ["**/*.composition.*", "**/*.preview.*"], + "docs": ["**/*.docs.*"], + "tests": ["**/*.spec.*", "**/*.test.*", "**/*.cy.*"], + } +} diff --git a/angular/examples/my-angular-v17-env/index.ts b/angular/examples/my-angular-v17-env/index.ts new file mode 100644 index 00000000..5f547581 --- /dev/null +++ b/angular/examples/my-angular-v17-env/index.ts @@ -0,0 +1 @@ +export { MyAngularV17Env, MyAngularV17Env as default } from './my-angular-v17-env.bit-env'; diff --git a/angular/examples/my-angular-v17-env/my-angular-v17-env.bit-env.ts b/angular/examples/my-angular-v17-env/my-angular-v17-env.bit-env.ts new file mode 100644 index 00000000..8d2a9b37 --- /dev/null +++ b/angular/examples/my-angular-v17-env/my-angular-v17-env.bit-env.ts @@ -0,0 +1,131 @@ +import { AngularPreview, BundlerProvider, DevServerProvider } from '@bitdev/angular.dev-services.preview.preview'; +import { AngularStarter } from '@bitdev/angular.templates.starters'; +import { NgAppTemplate, NgEnvTemplate, NgModuleTemplate } from '@bitdev/angular.templates.generators'; +import { AngularV17Env } from '@bitdev/angular.envs.angular-v17-env'; +import { BundlerContext, DevServerContext } from '@teambit/bundler'; +import { ESLintLinter, EslintTask } from '@teambit/defender.eslint-linter'; +import { JestTask, JestTester } from '@teambit/defender.jest-tester'; +import { PrettierFormatter } from '@teambit/defender.prettier-formatter'; +import { EnvHandler } from '@teambit/envs'; +import { StarterList, TemplateList } from '@teambit/generator'; +import { Linter } from '@teambit/linter'; +import { Preview } from '@teambit/preview'; +import { Tester } from '@teambit/tester'; +import { ESLint as ESLintLib } from 'eslint'; +import hostDependencies from './preview/host-dependencies'; + +export class MyAngularV17Env extends AngularV17Env { + // Name of the environment, used for friendly mentions across bit + name = 'my-angular-v17-env'; + + getTesterConfig() { + return { + jest: require.resolve('jest'), + config: require.resolve('./config/jest.config') + }; + } + + /** + * Returns a tester to use during development + * Required for `bit start` & `bit test` + */ + override tester(): EnvHandler { + /** + * @see https://bit.dev/reference/jest/using-jest + * */ + return JestTester.from(this.getTesterConfig()); + } + + getLinterConfig() { + return { + tsconfig: require.resolve('@bitdev/angular.dev-services.linter.eslint/config/tsconfig.json'), + eslint: ESLintLib, + configPath: require.resolve('./config/eslintrc'), + // resolve all plugins from the angular environment. + pluginsPath: __dirname, + extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs'] + }; + } + + /** + * The linter to use during development. + * Config files would be used to validate coding standards in components. + * bit will write the minimum required files in any workspace to optimize + * for dev experience. + */ + override linter(): EnvHandler { + return ESLintLinter.from(this.getLinterConfig()); + } + + /** + * The formatter to use during development + * (source files are not formatted as part of the components' build) + * */ + override formatter() { + /** + * @see https://bit.dev/reference/prettier/using-prettier + * */ + return PrettierFormatter.from({ + configPath: require.resolve('./config/prettier.config') + }); + } + + /** + * Generates the component previews during development and build + */ + override preview(): EnvHandler { + const ngEnvOptions = this.getNgEnvOptions(); + /** + * To customize the dev server or bundler behavior, you can change webpack transformers, angular + * options and webpack options in the getDevServer and getBundler methods. + */ + const devServerProvider: DevServerProvider = (devServerContext: DevServerContext) => this.getDevServer(devServerContext, ngEnvOptions); + const bundlerProvider: BundlerProvider = (bundlerContext: BundlerContext) => this.getBundler(bundlerContext, ngEnvOptions); + return AngularPreview.from({ + devServerProvider, + bundlerProvider, + ngEnvOptions, + hostDependencies, + mounterPath: require.resolve('./preview/mounter'), + }); + } + + /** + * Defines the build pipeline for a component. + * Pipelines are optimized for performance and consistency, making sure every component is + * independently built and tested. + * This is a set of processes to be performed before a component is snapped, during its build phase + * @see https://bit.dev/docs/angular-env/build-pipelines + */ + override build() { + return super.build().replace([ + EslintTask.from(this.getLinterConfig()), + JestTask.from(this.getTesterConfig()), + ]); + } + + /** + * Defines the component generators (templates) available with the command `bit templates`. + * @see https://bit.dev/docs/angular-env/component-generators + */ + override generators(): EnvHandler { + const envName = this.constructor.name; + return TemplateList.from([ + NgModuleTemplate.from({envName, angularVersion: this.angularVersion}), + NgEnvTemplate.from({envName, angularVersion: this.angularVersion}), + NgAppTemplate.from({envName, angularVersion: this.angularVersion}) + ]); + } + + /** + * Defines the Angular workspace starters available with the command `bit new`. + * @see https://bit.dev/docs/angular-env/workspace-starters + */ + override starters(): EnvHandler { + return StarterList.from([ + AngularStarter.from({envName: this.constructor.name, angularVersion: this.angularVersion}) + ]); + } +} + +export default new MyAngularV17Env(); diff --git a/angular/examples/my-angular-v17-env/my-angular-v17-env.docs.mdx b/angular/examples/my-angular-v17-env/my-angular-v17-env.docs.mdx new file mode 100644 index 00000000..1a63a1bd --- /dev/null +++ b/angular/examples/my-angular-v17-env/my-angular-v17-env.docs.mdx @@ -0,0 +1,86 @@ +--- +description: A Bit development environment for Angular Components +labels: ['angular', 'environment', 'env', 'aspect', 'extension'] +--- + +import { EnvOverview } from '@teambit/envs.docs.env-overview-template'; + + diff --git a/angular/examples/my-angular-v17-env/preview/host-dependencies.ts b/angular/examples/my-angular-v17-env/preview/host-dependencies.ts new file mode 100644 index 00000000..6f6a9bb7 --- /dev/null +++ b/angular/examples/my-angular-v17-env/preview/host-dependencies.ts @@ -0,0 +1,11 @@ +/** + * Dependencies to be bundled only once, in the env preview template, and not in each component preview. + * most of your peer dependencies should be listed here to avoid duplications in the preview. + * React, ReactDOM, and MDX are included as they are part of the preview ui. + */ +export default [ + '@teambit/mdx.ui.mdx-scope-context', + '@mdx-js/react', + 'react', + 'react-dom', +]; diff --git a/angular/examples/my-angular-v17-env/preview/mounter.ts b/angular/examples/my-angular-v17-env/preview/mounter.ts new file mode 100644 index 00000000..46e6d70b --- /dev/null +++ b/angular/examples/my-angular-v17-env/preview/mounter.ts @@ -0,0 +1,27 @@ +/* eslint-disable import/no-unresolved */ +import { createMounter } from '@bitdev/angular.dev-services.preview.mounter'; +import { Component, ViewEncapsulation } from '@angular/core'; + +/** + * Provide your component compositions (preview) with the context they need to run. + * for example, a router, a theme, a data provider, etc. + * components added here as providers should be listed as host-dependencies in your host-dependencies.ts file. + * @see https://bit.dev/docs/angular-env/components-preview#compositions-providers + */ +@Component({ + selector: 'bit-wrapper', + standalone: true, + imports: [], + encapsulation: ViewEncapsulation.None, + template: ` + + `, +}) export class WrapperComponent {} + + +/** + * the entry for the app (preview runtime) that renders your component previews. + * use the default template or create your own. + * @see https://bit.dev/docs/angular-env/components-preview#compositions-mounter + */ +export default createMounter(WrapperComponent); diff --git a/angular/templates/generators/ng-app/index.ts b/angular/templates/generators/ng-app/index.ts index 92412991..1641ad81 100644 --- a/angular/templates/generators/ng-app/index.ts +++ b/angular/templates/generators/ng-app/index.ts @@ -7,47 +7,67 @@ import { appComponentFile } from './template-files/src/app/app.component'; import { appComponentHtmlFile } from './template-files/src/app/app.component-html'; import { appComponentScssFile } from './template-files/src/app/app.component-scss'; import { appComponentSpecFile } from './template-files/src/app/app.component-spec'; +import { appConfigFile } from './template-files/src/app/app.config'; import { appModuleFile } from './template-files/src/app/app.module'; +import { appRoutesFile } from './template-files/src/app/app.routes'; import { gitKeepFile } from './template-files/src/assets/gitkeep'; -import { environmentFile } from './template-files/src/environments/environment'; -import { environmentProdFile } from './template-files/src/environments/environment.prod'; import { indexHtmlFile } from './template-files/src/index-html'; import { mainNgAppFile } from './template-files/src/main'; -import { polyfillFile } from './template-files/src/polyfills'; +import { polyfillsFile } from './template-files/src/polyfills'; import { stylesFile } from './template-files/src/styles'; import { tsconfigFile } from './template-files/tsconfig.app'; export class NgAppTemplate implements ComponentTemplate { private constructor( + readonly angularVersion: number, readonly name = 'ng-app', readonly description = 'create an Angular application', readonly hidden = false - ) {} + ) { + } generateFiles(context: ComponentContext) { - return [ + const files = [ docsFile(context), indexFile(context), - ngAppFile(context), - tsconfigFile(), + ngAppFile(context, this.angularVersion), + tsconfigFile(this.angularVersion), indexHtmlFile(context), - mainNgAppFile(), - polyfillFile(), + mainNgAppFile(this.angularVersion), stylesFile(), appComponentHtmlFile(), appComponentScssFile(), - appComponentSpecFile(context), - appComponentFile(context), - appModuleFile(), + appComponentSpecFile(context, this.angularVersion), + appComponentFile(context, this.angularVersion), gitKeepFile(), - environmentProdFile(), - environmentFile(), ]; + + if (this.angularVersion >= 15) { + files.push( + // starting from Angular 15, the `polyfills` option accept an array of module specifiers. + // https://github.com/angular/angular-cli/commit/597bfea1b29cc7b25d1f466eb313cbeeb6dffc98 + polyfillsFile(), + ); + } + + if (this.angularVersion >= 17) { + files.push( + appConfigFile(), + appRoutesFile(), + ); + } else { + files.push( + appModuleFile(), + ); + } + + return files; } - static from(options: AngularComponentTemplateOptions) { + static from(options: AngularComponentTemplateOptions & { angularVersion: number }) { return () => new NgAppTemplate( + options.angularVersion, options.name, options.description, options.hidden diff --git a/angular/templates/generators/ng-app/template-files/ng-app.ts b/angular/templates/generators/ng-app/template-files/ng-app.ts index c2290e1e..c3b1d6e5 100644 --- a/angular/templates/generators/ng-app/template-files/ng-app.ts +++ b/angular/templates/generators/ng-app/template-files/ng-app.ts @@ -1,6 +1,6 @@ import { ComponentContext, ComponentFile } from '@teambit/generator'; -export const ngAppFile = (context: ComponentContext): ComponentFile => { +export const ngAppFile = (context: ComponentContext, angularVersion: number): ComponentFile => { const { name, namePascalCase: Name } = context; return { relativePath: `${name}.ng-app.ts`, @@ -9,7 +9,10 @@ import { BrowserOptions, DevServerOptions } from '@bitdev/angular.dev-services.c const angularOptions: BrowserOptions & DevServerOptions = { main: './src/main.ts', - polyfills: './src/polyfills.ts', + polyfills: ${angularVersion >= 15 ? `[ + "zone.js", + "zone.js/testing" + ]` : `'./src/polyfills.ts'`}, index: './src/index.html', tsConfig: './tsconfig.app.json', assets: [{ diff --git a/angular/templates/generators/ng-app/template-files/src/app/app.component-html.ts b/angular/templates/generators/ng-app/template-files/src/app/app.component-html.ts index d7018e75..8365c070 100644 --- a/angular/templates/generators/ng-app/template-files/src/app/app.component-html.ts +++ b/angular/templates/generators/ng-app/template-files/src/app/app.component-html.ts @@ -315,19 +315,19 @@ export const appComponentHtmlFile = (): ComponentFile => { src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==" /> Welcome -
- - - - - - +
+ + + + + +
@@ -371,6 +371,12 @@ export const appComponentHtmlFile = (): ComponentFile => { + + + Angular Material + + + Angular Blog @@ -426,7 +432,7 @@ export const appComponentHtmlFile = (): ComponentFile => {
bit create ng-module ui/my-button
-
bit install @angular/material
+
bit install @angular/material
bit install _____
bit test
bit build
@@ -434,29 +440,6 @@ export const appComponentHtmlFile = (): ComponentFile => {
- - - - - - - - - - - - - Angular CLI Logo - - - - - - - - - - Meetup Logo @@ -475,16 +458,16 @@ export const appComponentHtmlFile = (): ComponentFile => {
- - Star -
-
- - - + Love Angular?  + Give our repo a star. +
+ + Star +
+
+ + + diff --git a/angular/templates/generators/ng-app/template-files/src/app/app.component-spec.ts b/angular/templates/generators/ng-app/template-files/src/app/app.component-spec.ts index b2785ae9..3e7358e3 100644 --- a/angular/templates/generators/ng-app/template-files/src/app/app.component-spec.ts +++ b/angular/templates/generators/ng-app/template-files/src/app/app.component-spec.ts @@ -1,6 +1,6 @@ import { ComponentContext, ComponentFile } from '@teambit/generator'; -export const appComponentSpecFile = (context: ComponentContext): ComponentFile => { +export const appComponentSpecFile = (context: ComponentContext, angularVersion: number): ComponentFile => { const { name } = context; return { relativePath: `src/app/app.component.spec.ts`, @@ -10,7 +10,7 @@ import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [AppComponent] + ${angularVersion >= 17 ? `imports: [AppComponent]` : `declarations: [AppComponent]`}, }).compileComponents(); }); @@ -20,7 +20,7 @@ describe('AppComponent', () => { expect(app).toBeTruthy(); }); - it(\`should have as title '${name}'\`, () => { + it(\`should have the '${name}' title\`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app.title).toEqual('${name}'); diff --git a/angular/templates/generators/ng-app/template-files/src/app/app.component.ts b/angular/templates/generators/ng-app/template-files/src/app/app.component.ts index 2f5b11ad..de9ede36 100644 --- a/angular/templates/generators/ng-app/template-files/src/app/app.component.ts +++ b/angular/templates/generators/ng-app/template-files/src/app/app.component.ts @@ -1,10 +1,24 @@ import { ComponentContext, ComponentFile } from '@teambit/generator'; -export const appComponentFile = (context: ComponentContext): ComponentFile => { +export const appComponentFile = (context: ComponentContext, angularVersion: number): ComponentFile => { const { name } = context; return { relativePath: `src/app/app.component.ts`, - content: `import { Component } from '@angular/core'; + content: angularVersion >= 17 ? `import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + selector: 'app-root', + standalone: true, + imports: [CommonModule, RouterOutlet], + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = '${name}'; +} +` : `import { Component } from '@angular/core'; @Component({ selector: 'app-root', diff --git a/angular/templates/generators/ng-app/template-files/src/app/app.config.ts b/angular/templates/generators/ng-app/template-files/src/app/app.config.ts new file mode 100644 index 00000000..59775b28 --- /dev/null +++ b/angular/templates/generators/ng-app/template-files/src/app/app.config.ts @@ -0,0 +1,16 @@ +import { ComponentFile } from '@teambit/generator'; + +export const appConfigFile = (): ComponentFile => { + return { + relativePath: `src/app/app.config.ts`, + content: `import { ApplicationConfig } from '@angular/core'; +import { provideRouter } from '@angular/router'; + +import { routes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [provideRouter(routes)] +}; +`, + }; +}; diff --git a/angular/templates/generators/ng-app/template-files/src/app/app.routes.ts b/angular/templates/generators/ng-app/template-files/src/app/app.routes.ts new file mode 100644 index 00000000..6ab5a4ae --- /dev/null +++ b/angular/templates/generators/ng-app/template-files/src/app/app.routes.ts @@ -0,0 +1,11 @@ +import { ComponentFile } from '@teambit/generator'; + +export const appRoutesFile = (): ComponentFile => { + return { + relativePath: `src/app/app.routes.ts`, + content: `import { Routes } from '@angular/router'; + +export const routes: Routes = []; +`, + }; +}; diff --git a/angular/templates/generators/ng-app/template-files/src/environments/environment.prod.ts b/angular/templates/generators/ng-app/template-files/src/environments/environment.prod.ts deleted file mode 100644 index babb7cb8..00000000 --- a/angular/templates/generators/ng-app/template-files/src/environments/environment.prod.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ComponentFile } from '@teambit/generator'; - -export const environmentProdFile = (): ComponentFile => { - return { - relativePath: `src/environments/environment.prod.ts`, - content: `export const environment = { - production: true -}; -`, - }; -}; diff --git a/angular/templates/generators/ng-app/template-files/src/environments/environment.ts b/angular/templates/generators/ng-app/template-files/src/environments/environment.ts deleted file mode 100644 index 14bf6fb2..00000000 --- a/angular/templates/generators/ng-app/template-files/src/environments/environment.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ComponentFile } from '@teambit/generator'; - -export const environmentFile = (): ComponentFile => { - return { - relativePath: `src/environments/environment.ts`, - content: `// This file can be replaced during build by using the \`fileReplacements\` array. -// \`ng build\` replaces \`environment.ts\` with \`environment.prod.ts\`. -// The list of file replacements can be found in \`angular.json\`. - -export const environment = { - production: false -}; - -/* - * For easier debugging in development mode, you can import the following file - * to ignore zone related error stack frames such as \`zone.run\`, \`zoneDelegate.invokeTask\`. - * - * This import should be commented out in production mode because it will have a negative impact - * on performance if an error is thrown. - */ -// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. -`, - }; -}; diff --git a/angular/templates/generators/ng-app/template-files/src/main.ts b/angular/templates/generators/ng-app/template-files/src/main.ts index d09e3435..c54d63f7 100644 --- a/angular/templates/generators/ng-app/template-files/src/main.ts +++ b/angular/templates/generators/ng-app/template-files/src/main.ts @@ -1,17 +1,16 @@ import { ComponentFile } from '@teambit/generator'; -export const mainNgAppFile = (): ComponentFile => { +export const mainNgAppFile = (angularVersion: number): ComponentFile => { return { relativePath: `src/main.ts`, - content: `import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + content: angularVersion >= 17 ? `import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; +bootstrapApplication(AppComponent, appConfig) + .catch((err) => console.error(err)); +` : `import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.error(err)); diff --git a/angular/templates/generators/ng-app/template-files/src/polyfills.ts b/angular/templates/generators/ng-app/template-files/src/polyfills.ts index 9b44826b..615bdbec 100644 --- a/angular/templates/generators/ng-app/template-files/src/polyfills.ts +++ b/angular/templates/generators/ng-app/template-files/src/polyfills.ts @@ -1,6 +1,6 @@ import { ComponentFile } from '@teambit/generator'; -export const polyfillFile = (): ComponentFile => { +export const polyfillsFile = (): ComponentFile => { return { relativePath: `src/polyfills.ts`, content: `/** diff --git a/angular/templates/generators/ng-app/template-files/tsconfig.app.ts b/angular/templates/generators/ng-app/template-files/tsconfig.app.ts index f0f552ed..27b38a2e 100644 --- a/angular/templates/generators/ng-app/template-files/tsconfig.app.ts +++ b/angular/templates/generators/ng-app/template-files/tsconfig.app.ts @@ -1,6 +1,6 @@ import { ComponentFile } from '@teambit/generator'; -export const tsconfigFile = (): ComponentFile => { +export const tsconfigFile = (angularVersion: number): ComponentFile => { return { relativePath: 'tsconfig.app.json', content: `/* To learn more about this file see: https://angular.io/config/tsconfig. */ @@ -13,19 +13,20 @@ export const tsconfigFile = (): ComponentFile => { "strict": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, "moduleResolution": "node", - "allowSyntheticDefaultImports": true, "importHelpers": true, "allowJs": true, - "target": "es2017", - "module": "es2020", + ${angularVersion >= 17 ? `"target": "ES2022", + "module": "ES2022"` : `"target": "es2017", + "module": "es2020"`}, "preserveSymlinks": false, "lib": [ - "es2018", + "${angularVersion >= 17 ? `ES2022` : `ES2018`}", "dom" ], "types": [] @@ -33,9 +34,7 @@ export const tsconfigFile = (): ComponentFile => { "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictGenerators": true, - "enableIvy": true + "strictInputAccessModifiers": true }, "files": [ "./src/main.ts", diff --git a/integration/demo-app/src/app/app.component.html b/integration/demo-app/src/app/app.component.html index 675eb49f..2a42646f 100644 --- a/integration/demo-app/src/app/app.component.html +++ b/integration/demo-app/src/app/app.component.html @@ -310,19 +310,19 @@ src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==" /> Welcome -
- - - - - - +
+ + + + + +
@@ -366,6 +366,12 @@

Resources

+ + + Angular Material + + + Angular Blog @@ -421,7 +427,7 @@

Next Steps

bit create ng-module ui/my-button
-
bit install @angular/material
+
bit install @angular/material
bit install _____
bit test
bit build
@@ -429,29 +435,6 @@

Next Steps

- - - - - - - - - - - - - Angular CLI Logo - - - - - - - - - - Meetup Logo @@ -470,16 +453,16 @@

Next Steps

diff --git a/integration/demo-lib-v17/public-api.ts b/integration/demo-lib-v17/public-api.ts new file mode 100644 index 00000000..b0c87230 --- /dev/null +++ b/integration/demo-lib-v17/public-api.ts @@ -0,0 +1,6 @@ +/** + * Entry point for this Angular library, do not move or rename this file. + */ +export * from './src/bit-test.component'; +export * from './src/bit-test2.component'; +export * from './src/bit-test.module'; diff --git a/integration/demo-lib-v17/src/bit-test.component.ts b/integration/demo-lib-v17/src/bit-test.component.ts new file mode 100644 index 00000000..e3c71891 --- /dev/null +++ b/integration/demo-lib-v17/src/bit-test.component.ts @@ -0,0 +1,13 @@ +import { Component } from "@angular/core"; +import { BitTestService } from './bit-test.service'; + +@Component({ + selector: 'bit-test', + template: ` +

bit-test component works!

+ {{ service.content }} + ` +}) +export class BitTestComponent { + constructor(public service: BitTestService) {} +} diff --git a/integration/demo-lib-v17/src/bit-test.docs.md b/integration/demo-lib-v17/src/bit-test.docs.md new file mode 100644 index 00000000..1fcc392a --- /dev/null +++ b/integration/demo-lib-v17/src/bit-test.docs.md @@ -0,0 +1,27 @@ +--- +labels: ['angular', 'typescript', 'bit-test'] +description: 'A `bit-test` component.' +--- + +# Bit test documentation +Import `BitTestModule` : + +```typescript +import { BitTestModule } from './bit-test.module'; + +// add it to your module imports +@NgModule({ + // ... + imports: [ + BitTestModule + ] + // ... +}) +export class AppModule {} +``` + +Use `BitTestComponent` in your templates : + +```html + +``` diff --git a/integration/demo-lib-v17/src/bit-test.module.ts b/integration/demo-lib-v17/src/bit-test.module.ts new file mode 100644 index 00000000..722ee247 --- /dev/null +++ b/integration/demo-lib-v17/src/bit-test.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { BitTestComponent } from './bit-test.component'; +import { BitTest2Component } from './bit-test2.component'; + +@NgModule({ + declarations: [ + BitTestComponent, + BitTest2Component + ], + exports: [ + BitTestComponent, + BitTest2Component + ] +}) +export class BitTestModule {} diff --git a/integration/demo-lib-v17/src/bit-test.service.ts b/integration/demo-lib-v17/src/bit-test.service.ts new file mode 100644 index 00000000..e5ced380 --- /dev/null +++ b/integration/demo-lib-v17/src/bit-test.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ providedIn: 'any' }) +export class BitTestService { + get content() { + return 'Content from service'; + } +} diff --git a/integration/demo-lib-v17/src/bit-test.spec.ts b/integration/demo-lib-v17/src/bit-test.spec.ts new file mode 100644 index 00000000..4fc29a4e --- /dev/null +++ b/integration/demo-lib-v17/src/bit-test.spec.ts @@ -0,0 +1,30 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { BitTestComponent } from './bit-test.component'; + +describe('BitTestComponent', () => { + let component: BitTestComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ BitTestComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BitTestComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should have a service', () => { + expect(component.service).toBeDefined(); + expect(component.service.content).toEqual('Content from service'); + }) +}); diff --git a/integration/demo-lib-v17/src/bit-test2.component.ts b/integration/demo-lib-v17/src/bit-test2.component.ts new file mode 100644 index 00000000..629586b0 --- /dev/null +++ b/integration/demo-lib-v17/src/bit-test2.component.ts @@ -0,0 +1,11 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'bit-test2', + template: ` +

+ bit-test 2 works as well! +

+ ` +}) +export class BitTest2Component {} diff --git a/integration/demo-lib-v17/src/compositions/bit-test.composition.ts b/integration/demo-lib-v17/src/compositions/bit-test.composition.ts new file mode 100644 index 00000000..5359c53f --- /dev/null +++ b/integration/demo-lib-v17/src/compositions/bit-test.composition.ts @@ -0,0 +1,16 @@ +import { Component, NgModule } from '@angular/core'; +import { BitTestModule } from '../bit-test.module'; + +@Component({ + selector: 'composition-cmp', + template: `Composition: ` +}) +class CompositionComponent {} + +@NgModule({ + declarations: [CompositionComponent], + imports: [BitTestModule], + bootstrap: [CompositionComponent] +}) +export class CompositionModule { +} diff --git a/integration/demo-lib-v17/src/compositions/cmp1.composition.ts b/integration/demo-lib-v17/src/compositions/cmp1.composition.ts new file mode 100644 index 00000000..eacc7b3d --- /dev/null +++ b/integration/demo-lib-v17/src/compositions/cmp1.composition.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { BitTestModule } from '../bit-test.module'; + +@Component({ + selector: 'bit-composition', + standalone: true, + imports: [BitTestModule], + template: ` +

+ Composition component 1 + +

+ `, + styles: [ + ] +}) +export class StandaloneCompositionComponent { +} diff --git a/workspace.jsonc b/workspace.jsonc index 126fcd67..d73994fb 100644 --- a/workspace.jsonc +++ b/workspace.jsonc @@ -78,6 +78,7 @@ "teambit.generator/generator": { "envs": [ "bitdev.angular/angular-env", + "bitdev.angular/envs/angular-v17-env", "bitdev.angular/envs/angular-v16-env", "bitdev.angular/envs/angular-v15-env", "bitdev.angular/envs/angular-v14-env", @@ -86,6 +87,7 @@ ] }, "bitdev.angular/angular-env": {}, + "bitdev.angular/envs/angular-v17-env": {}, "bitdev.angular/envs/angular-v16-env": {}, "bitdev.angular/envs/angular-v15-env": {}, "bitdev.angular/envs/angular-v14-env": {}, @@ -99,14 +101,6 @@ * new set of dependencies. **/ "teambit.workspace/variants": { - // Set the default variant configs to be used for all components (except integration). - "angular": { - "defaultScope": "bitdev.angular" - }, - // Set the default variant configs to be used for integration - "integration": { - "defaultScope": "integration.examples" - }, // Special rules for all aspect envs "angular/envs, angular/examples": { "teambit.harmony/aspect": "-", @@ -134,12 +128,15 @@ "teambit.envs/env": {} }, "integration/demo-app": { - // "bitdev.angular/angular-env": {} - "bitdev.angular/envs/angular-v16-env": {} + "bitdev.angular/angular-env": {} +// "bitdev.angular/envs/angular-v17-env": {} }, "integration/demo-lib": { "bitdev.angular/angular-env": {} }, + "integration/demo-lib-v17": { + "bitdev.angular/envs/angular-v17-env": {} + }, "integration/demo-lib-v16": { "bitdev.angular/envs/angular-v16-env": {} },