From 0e5b546ddb8ff0765e038124c205060c2aa48221 Mon Sep 17 00:00:00 2001 From: Olivier Combe Date: Mon, 29 Jan 2024 19:43:20 +0100 Subject: [PATCH] feat: use new app type format --- .../angular-app-type/angular-app-options.ts | 6 + .../angular-app-type/angular.app-type.ts | 30 +-- .../angular-app-type/angular.application.ts | 172 ++++++++++-------- angular/app-types/angular-app-type/index.ts | 1 + angular/devkit/common/utils.ts | 8 +- .../devkit/preview/preview/angular-preview.ts | 3 +- angular/devkit/webpack/ng-webpack-bundler.ts | 4 +- angular/envs/angular-env/index.ts | 2 +- .../angular-v13-env.bit-env.ts | 26 +-- angular/envs/angular-v13-env/index.ts | 2 +- .../angular-v14-env.bit-env.ts | 26 +-- angular/envs/angular-v14-env/index.ts | 2 +- .../angular-v15-env.bit-env.ts | 26 +-- angular/envs/angular-v15-env/index.ts | 2 +- .../angular-v16-env.bit-env.ts | 28 +-- angular/envs/angular-v16-env/index.ts | 2 +- .../angular-v17-env.bit-env.ts | 28 +-- angular/envs/angular-v17-env/index.ts | 2 +- .../envs/base-env/angular-base-env.bit-env.ts | 25 +-- angular/templates/generators/ng-app/index.ts | 2 +- .../template-files/{ng-app.ts => bit-app.ts} | 12 +- .../generators/ng-app/template-files/index.ts | 2 +- ...demo-app.ng-app.ts => demo-app.bit-app.ts} | 12 +- integration/demo-app/index.ts | 2 +- 24 files changed, 219 insertions(+), 206 deletions(-) rename angular/templates/generators/ng-app/template-files/{ng-app.ts => bit-app.ts} (77%) rename integration/demo-app/{demo-app.ng-app.ts => demo-app.bit-app.ts} (69%) diff --git a/angular/app-types/angular-app-type/angular-app-options.ts b/angular/app-types/angular-app-type/angular-app-options.ts index 69e36ab9..96c8fb6e 100644 --- a/angular/app-types/angular-app-type/angular-app-options.ts +++ b/angular/app-types/angular-app-type/angular-app-options.ts @@ -1,4 +1,5 @@ import { + AngularEnvOptions, ApplicationOptions, BrowserOptions, DevServerOptions @@ -52,4 +53,9 @@ export type AngularAppOptions = { * Angular options for `bit run` */ angularServeOptions: (BrowserOptions & DevServerOptions) | (ApplicationOptions & DevServerOptions); + + /** + * Env-specific options depending on the version of Angular used. + */ + ngEnvOptions: AngularEnvOptions; }; diff --git a/angular/app-types/angular-app-type/angular.app-type.ts b/angular/app-types/angular-app-type/angular.app-type.ts index ee45cea0..84644606 100644 --- a/angular/app-types/angular-app-type/angular.app-type.ts +++ b/angular/app-types/angular-app-type/angular.app-type.ts @@ -1,39 +1,27 @@ -import { GenericAngularEnv, getWorkspace, NG_APP_NAME } from '@bitdev/angular.dev-services.common'; +import { NG_APP_NAME } from '@bitdev/angular.dev-services.common'; import { Application, ApplicationType } from '@teambit/application'; -import { DependencyResolverAspect, DependencyResolverMain } from '@teambit/dependency-resolver'; -import { EnvContext, EnvHandler } from '@teambit/envs'; -import { Logger } from '@teambit/logger'; -import { Workspace } from '@teambit/workspace'; +import { EnvHandler } from '@teambit/envs'; import { AngularAppOptions } from './angular-app-options'; import { AngularApp } from './angular.application'; interface AngularAppTypeOptions { name?: string; - angularEnv: GenericAngularEnv; } export class AngularAppType implements ApplicationType { - constructor(readonly name: string, private angularEnv: GenericAngularEnv, private context: EnvContext, private depsResolver: DependencyResolverMain, private logger: Logger, private workspace?: Workspace) { - } + constructor(readonly name: string) {} createApp(options: AngularAppOptions): Application { - return new AngularApp( - this.angularEnv, - this.context, - options, - this.depsResolver, - this.logger, - this.workspace - ); + return new AngularApp({ + ...options, + name: this.name + }); } static from(options: AngularAppTypeOptions): EnvHandler { - return (context: EnvContext) => { + return () => { const name = options.name || NG_APP_NAME; - const depsResolver = context.getAspect(DependencyResolverAspect.id); - const workspace = getWorkspace(context); - const logger = context.createLogger(name); - return new AngularAppType(name, options.angularEnv, context, depsResolver, logger, workspace); + return new AngularAppType(name); }; } } diff --git a/angular/app-types/angular-app-type/angular.application.ts b/angular/app-types/angular-app-type/angular.application.ts index e75b6546..f63f9d83 100644 --- a/angular/app-types/angular-app-type/angular.application.ts +++ b/angular/app-types/angular-app-type/angular.application.ts @@ -1,21 +1,22 @@ import { VERSION } from '@angular/cli'; import { ApplicationOptions, - GenericAngularEnv, + getWorkspace, + NG_APP_NAME, normalizePath } from '@bitdev/angular.dev-services.common'; +import { AngularPreview } from '@bitdev/angular.dev-services.preview.preview'; import { - AngularPreview, - BundlerProvider, - DevServerProvider -} from '@bitdev/angular.dev-services.preview.preview'; -import { AppBuildContext, AppContext, Application } from '@teambit/application'; -import { Bundler, BundlerContext, DevServer, DevServerContext } from '@teambit/bundler'; + AppBuildContext, + AppContext, + Application, + ApplicationInstance +} from '@teambit/application'; +import { Bundler, BundlerContext, DevServerContext } from '@teambit/bundler'; import { Component } from '@teambit/component'; -import { DependencyResolverMain } from '@teambit/dependency-resolver'; +import { DependencyResolverAspect, DependencyResolverMain } from '@teambit/dependency-resolver'; import { EnvContext, EnvHandler } from '@teambit/envs'; import { CACHE_ROOT } from '@teambit/legacy/dist/constants'; -import { Logger } from '@teambit/logger'; import { Preview } from '@teambit/preview'; import { Port } from '@teambit/toolbox.network.get-port'; import { Workspace } from '@teambit/workspace'; @@ -35,34 +36,28 @@ const writeHash = new Map(); export class AngularApp implements Application { readonly name: string; - - readonly preview: EnvHandler; - - readonly tempFolder: string; - - readonly tsconfigPath: string; + readonly idName: string; constructor( - private angularEnv: GenericAngularEnv, - private envContext: EnvContext, - readonly options: AngularAppOptions, - private depsResolver: DependencyResolverMain, - private logger: Logger, - private workspace?: Workspace + readonly options: AngularAppOptions ) { - this.name = options.name; + this.name = options.name || NG_APP_NAME; + this.idName = `bitdev.angular/${ this.name }`; + } - const idName = `bitdev.angular/${ this.name }`; - this.tempFolder = workspace?.getTempDir(idName) || join(CACHE_ROOT, idName); - if (!existsSync(this.tempFolder)) { - mkdirSync(this.tempFolder, { recursive: true }); - } + readonly publicDir = 'public'; - this.tsconfigPath = normalizePath(join(this.tempFolder, `tsconfig/tsconfig-${ Date.now() }.json`)); - this.preview = this.getPreview(); + private getTempFolder(workspace?: Workspace): string { + const tempFolder = workspace?.getTempDir(this.idName) || join(CACHE_ROOT, this.idName); + if (!existsSync(tempFolder)) { + mkdirSync(tempFolder, { recursive: true }); + } + return tempFolder; } - readonly publicDir = 'public'; + private getTsconfigPath(tempFolder: string): string { + return normalizePath(join(tempFolder, `tsconfig/tsconfig-${ Date.now() }.json`)); + } private getPublicDir(artifactsDir: string) { return join(artifactsDir, this.name); @@ -95,35 +90,33 @@ export class AngularApp implements Application { }); } - private getPreview(): EnvHandler { - const ngEnvOptions = this.angularEnv.getNgEnvOptions(); - - const angularServeOptions: any = Object.assign(cloneDeep(this.options.angularServeOptions), { tsConfig: this.tsconfigPath }); - const angularBuildOptions: any = Object.assign(cloneDeep(this.options.angularBuildOptions), { tsConfig: this.tsconfigPath }); + private getPreview(tsconfigPath: string): EnvHandler { + const angularServeOptions: any = Object.assign(cloneDeep(this.options.angularServeOptions), { tsConfig: tsconfigPath }); + const angularBuildOptions: any = Object.assign(cloneDeep(this.options.angularBuildOptions), { tsConfig: tsconfigPath }); return AngularPreview.from({ webpackServeTransformers: this.options.webpackServeTransformers, webpackBuildTransformers: this.options.webpackBuildTransformers, angularServeOptions, angularBuildOptions, - ngEnvOptions, + ngEnvOptions: this.options.ngEnvOptions, sourceRoot: this.options.sourceRoot, }); } - private generateTsConfig(bitCmps: Component[], appRootPath: string, tsconfigPath: string, serverEntry?: string): void { - const tsconfigJSON: JsonObject = readConfigFile(tsconfigPath, sys.readFile).config; + private generateTsConfig(bitCmps: Component[], appRootPath: string, appTsconfigPath: string, tsconfigPath: string, depsResolver: DependencyResolverMain, workspace?: Workspace, serverEntry?: string): void { + const tsconfigJSON: JsonObject = readConfigFile(appTsconfigPath, sys.readFile).config; // Add the paths to tsconfig to remap bit components to local folders tsconfigJSON.compilerOptions.paths = tsconfigJSON.compilerOptions.paths || {}; bitCmps.forEach((dep: Component) => { - let componentDir = this.workspace?.componentDir(dep.id, { + let componentDir = workspace?.componentDir(dep.id, { ignoreVersion: true }); if (componentDir) { componentDir = normalizePath(componentDir); - const pkgName = this.depsResolver.getPackageName(dep); + const pkgName = depsResolver.getPackageName(dep); // TODO we should find a way to use the real entry file based on the component config because people can change it if (existsSync(join(componentDir, 'public-api.ts'))) { tsconfigJSON.compilerOptions.paths[pkgName] = [`${ componentDir }/public-api.ts`, `${ componentDir }`]; @@ -136,93 +129,114 @@ export class AngularApp implements Application { tsconfigJSON.files.push(serverEntry); } - const tsconfigContent = expandIncludeExclude(tsconfigJSON, this.tsconfigPath, [appRootPath]); + const tsconfigContent = expandIncludeExclude(tsconfigJSON, tsconfigPath, [appRootPath]); const hash = objectHash(tsconfigContent); // write only if link has changed (prevents triggering fs watches) - if (writeHash.get(this.tsconfigPath) !== hash) { - outputJsonSync(this.tsconfigPath, tsconfigContent, { spaces: 2 }); - writeHash.set(this.tsconfigPath, hash); + if (writeHash.get(tsconfigPath) !== hash) { + outputJsonSync(tsconfigPath, tsconfigContent, { spaces: 2 }); + writeHash.set(tsconfigPath, hash); } } - async getDevServer(context: AppContext, appRootPath: string): Promise { - const devServerContext = this.getDevServerContext(context, appRootPath); - const preview = this.preview(this.envContext); - - return preview.getDevServer(devServerContext)(this.envContext); + /** + * Transform the app context into env context to make typescript happy. + * Technically, we only use methods that exist in both interfaces, so it's fine. + */ + private getEnvContext(context: AppContext | AppBuildContext): EnvContext { + return context as any as EnvContext; } // TODO: fix return type once bit has a new stable version - async run(context: AppContext): Promise { - assert(this.workspace, 'Workspace is not defined'); + async run(context: AppContext): Promise { + const depsResolver = context.getAspect(DependencyResolverAspect.id); + assert(depsResolver, 'Dependency resolver is not defined'); + const workspace = getWorkspace(context); + assert(workspace, 'Workspace is not defined'); + const logger = context.createLogger(this.name); const port = context.port || (await Port.getPortFromRange(this.options.portRange || [3000, 4000])); - const appRootPath = this.workspace.componentDir(context.appComponent.id, { + const appRootPath = workspace.componentDir(context.appComponent.id, { ignoreVersion: true }); - const tsconfigPath = join(appRootPath, this.options.angularServeOptions.tsConfig); - const workspaceCmpsIDs = await this.workspace.listIds(); - const bitCmps = await this.workspace.getMany(workspaceCmpsIDs); - this.generateTsConfig(bitCmps, appRootPath, tsconfigPath); + const appTsconfigPath = join(appRootPath, this.options.angularServeOptions.tsConfig); + const workspaceCmpsIDs = await workspace.listIds(); + const bitCmps = await workspace.getMany(workspaceCmpsIDs); + const tempFolder = this.getTempFolder(workspace); + const tsconfigPath = this.getTsconfigPath(tempFolder); + this.generateTsConfig(bitCmps, appRootPath, appTsconfigPath, tsconfigPath, depsResolver, workspace); if (Number(VERSION.major) >= 16) { await serveApplication({ angularOptions: { ...this.options.angularBuildOptions as ApplicationOptions, - tsConfig: this.tsconfigPath + tsConfig: tsconfigPath }, sourceRoot: this.options.sourceRoot || 'src', workspaceRoot: appRootPath, port, - logger: this.logger, - tempFolder: this.tempFolder + logger: logger, + tempFolder: tempFolder }); - return port; - } - - const devServer = await this.getDevServer(context, appRootPath); - await devServer.listen(port); - return port; - } + } else { + const devServerContext = this.getDevServerContext(context, appRootPath); + const envContext = this.getEnvContext(context); + const preview = this.getPreview(tsconfigPath)(envContext); - async getBundler(context: AppBuildContext): Promise { - if (this.options.bundler) { - return this.options.bundler; + const devServer = await preview.getDevServer(devServerContext)(envContext); + await devServer.listen(port); } - const bundlerContext = this.getBundlerContext(context); - const preview = this.preview(this.envContext); - - return preview.getBundler(bundlerContext)(this.envContext); + return { + appName: this.name, + port + }; } async build(context: AppBuildContext): Promise { const { capsule } = context; + const depsResolver = context.getAspect(DependencyResolverAspect.id); + assert(depsResolver, 'Dependency resolver is not defined'); + const logger = context.createLogger(this.name); const outputPath = this.getPublicDir(context.artifactsDir); const appRootPath = capsule.path; - const tsconfigPath = join(appRootPath, this.options.angularBuildOptions.tsConfig); + const appTsconfigPath = join(appRootPath, this.options.angularBuildOptions.tsConfig); const appOptions = this.options.angularBuildOptions as ApplicationOptions; const entryServer = appOptions.ssr && Number(VERSION.major) >= 17 ? './entry.server.ts' : undefined; - this.generateTsConfig([capsule.component], appRootPath, tsconfigPath, entryServer); + const tempFolder = this.getTempFolder(); + const tsconfigPath = this.getTsconfigPath(tempFolder); + this.generateTsConfig([capsule.component], appRootPath, appTsconfigPath, tsconfigPath, depsResolver, undefined, entryServer); if (!this.options.bundler && Number(VERSION.major) >= 16) { await buildApplication({ angularOptions: { ...appOptions, - tsConfig: this.tsconfigPath + tsConfig: tsconfigPath }, outputPath, sourceRoot: this.options.sourceRoot || 'src', workspaceRoot: context.capsule.path, - logger: this.logger, - tempFolder: this.tempFolder, + logger: logger, + tempFolder: tempFolder, entryServer }); } else { - const bundler = await this.getBundler(context); + let bundler: Bundler; + if (this.options.bundler) { + bundler = this.options.bundler; + } else { + const bundlerContext = this.getBundlerContext(context); + const envContext = this.getEnvContext(context); + const preview = this.getPreview(tsconfigPath)(envContext); + + bundler = await preview.getBundler(bundlerContext)(envContext); + } await bundler.run(); } return { publicDir: outputPath }; } + + static from(options: AngularAppOptions): Application { + return new AngularApp(options); + } } diff --git a/angular/app-types/angular-app-type/index.ts b/angular/app-types/angular-app-type/index.ts index 72be5184..1d18c26f 100644 --- a/angular/app-types/angular-app-type/index.ts +++ b/angular/app-types/angular-app-type/index.ts @@ -2,3 +2,4 @@ export { AngularAppType } from './angular.app-type'; export type { AngularDeployContext } from './deploy-context'; export type { AngularAppOptions } from './angular-app-options'; export { NG_APP_NAME, NG_APP_PATTERN } from '@bitdev/angular.dev-services.common'; +export { AngularApp } from './angular.application'; diff --git a/angular/devkit/common/utils.ts b/angular/devkit/common/utils.ts index 74b46d64..02ee7f13 100644 --- a/angular/devkit/common/utils.ts +++ b/angular/devkit/common/utils.ts @@ -14,7 +14,7 @@ import normalize from 'normalize-path'; import objectHash from 'object-hash'; import { dirname, join, posix, resolve } from 'path'; -export const NG_APP_NAME = 'ng-app'; +export const NG_APP_NAME = 'bit-app'; export const NG_APP_PATTERN = `*.${ NG_APP_NAME }.*`; export enum BundlerSetup { @@ -33,7 +33,7 @@ export function componentIsApp(component: Component, application: ApplicationMai /** * Returns the workspace instance from the context, if it's available, or undefined otherwise. */ -export function getWorkspace(context: EnvContext): Workspace | undefined { +export function getWorkspace(context: EnvContext | AppContext): Workspace | undefined { // TODO: replace this try catch with context.hasAspect once it's available from harmony try { return context.getAspect(WorkspaceAspect.id); @@ -115,7 +115,7 @@ export function cmpIdToPkgName(componentId: ComponentID) { return `@${ partsToJoin.join('.') }`; } -export function isBuildContext(context: DevServerContext | BundlerContext): context is BundlerContext { +export function isBuildContext(context: any): context is BundlerContext { return (context as BundlerContext).capsuleNetwork !== undefined; } @@ -169,7 +169,7 @@ export function generateTsConfig( * Generates the tsconfig to load the preview app with compositions dynamically. */ export function writeTsconfig( - context: DevServerContext | BundlerContext, + context: DevServerContext | BundlerContext | AppContext | AppBuildContext, rootPath: string, tempFolder: string, application: ApplicationMain, diff --git a/angular/devkit/preview/preview/angular-preview.ts b/angular/devkit/preview/preview/angular-preview.ts index 50850b45..881a8922 100644 --- a/angular/devkit/preview/preview/angular-preview.ts +++ b/angular/devkit/preview/preview/angular-preview.ts @@ -139,7 +139,8 @@ export class AngularPreview implements Preview { getDevEnvId() { const objToHash = { webpack: this.ngEnvOptions.webpackModulePath, - webpackDevServer: this.ngEnvOptions.webpackDevServerModulePath + webpackDevServer: this.ngEnvOptions.webpackDevServerModulePath, + transformers: this.webpackServeTransformers }; return objectHash(objToHash); } diff --git a/angular/devkit/webpack/ng-webpack-bundler.ts b/angular/devkit/webpack/ng-webpack-bundler.ts index 6419f9a1..b8116957 100644 --- a/angular/devkit/webpack/ng-webpack-bundler.ts +++ b/angular/devkit/webpack/ng-webpack-bundler.ts @@ -9,7 +9,7 @@ import { isAppBuildContext, writeTsconfig } from '@bitdev/angular.dev-services.common'; -import { AppBuildContext, ApplicationAspect, ApplicationMain } from '@teambit/application'; +import { ApplicationAspect, ApplicationMain } from '@teambit/application'; import { BundlerContext } from '@teambit/bundler'; import { DevFilesAspect, DevFilesMain } from '@teambit/dev-files'; import { AsyncEnvHandler, EnvContext } from '@teambit/envs'; @@ -38,7 +38,7 @@ export type NgWebpackBundlerOptions = { /** * context of the bundler execution. */ - bundlerContext: BundlerContext | (BundlerContext & AppBuildContext); + bundlerContext: BundlerContext; /** * name of the dev server. diff --git a/angular/envs/angular-env/index.ts b/angular/envs/angular-env/index.ts index 1627c51a..09a4010e 100644 --- a/angular/envs/angular-env/index.ts +++ b/angular/envs/angular-env/index.ts @@ -1,2 +1,2 @@ export { AngularEnv } from './angular.bit-env'; -export { jestConfig } from '@bitdev/angular.envs.angular-v17-env'; +export { jestConfig, ngEnvOptions } from '@bitdev/angular.envs.angular-v17-env'; diff --git a/angular/envs/angular-v13-env/angular-v13-env.bit-env.ts b/angular/envs/angular-v13-env/angular-v13-env.bit-env.ts index 0e7a0c14..d3d95262 100644 --- a/angular/envs/angular-v13-env/angular-v13-env.bit-env.ts +++ b/angular/envs/angular-v13-env/angular-v13-env.bit-env.ts @@ -6,6 +6,19 @@ import { webpackConfigFactory } from './webpack-config.factory'; // Disable v8-caching because it breaks ESM loaders NativeCompileCache.uninstall(); +export const ngEnvOptions: AngularEnvOptions = { + useAngularElementsPreview: false, + // angularElementsModulePath: require.resolve('@angular/elements'), + jestConfigPath: require.resolve('./jest/jest.config'), + jestModulePath: require.resolve('jest'), + ngPackagrModulePath: require.resolve('ng-packagr'), + 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')] }) +} + export class AngularV13Env extends AngularBaseEnv { /** * name of the environment. used for friendly mentions across bit. @@ -14,18 +27,7 @@ export class AngularV13Env extends AngularBaseEnv { angularVersion = 13; - ngEnvOptions: AngularEnvOptions = { - useAngularElementsPreview: false, - // angularElementsModulePath: require.resolve('@angular/elements'), - jestConfigPath: require.resolve('./jest/jest.config'), - jestModulePath: require.resolve('jest'), - ngPackagrModulePath: require.resolve('ng-packagr'), - 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')] }) - }; + ngEnvOptions: AngularEnvOptions = ngEnvOptions; } export default new AngularV13Env(); diff --git a/angular/envs/angular-v13-env/index.ts b/angular/envs/angular-v13-env/index.ts index a4f88d0d..5651cdcd 100644 --- a/angular/envs/angular-v13-env/index.ts +++ b/angular/envs/angular-v13-env/index.ts @@ -1,2 +1,2 @@ -export { AngularV13Env } from './angular-v13-env.bit-env'; +export { AngularV13Env, ngEnvOptions } from './angular-v13-env.bit-env'; export { default as jestConfig } from './jest/jest.config'; diff --git a/angular/envs/angular-v14-env/angular-v14-env.bit-env.ts b/angular/envs/angular-v14-env/angular-v14-env.bit-env.ts index b8fd2039..87ef3208 100644 --- a/angular/envs/angular-v14-env/angular-v14-env.bit-env.ts +++ b/angular/envs/angular-v14-env/angular-v14-env.bit-env.ts @@ -6,6 +6,19 @@ import { webpackConfigFactory } from './webpack-config.factory'; // Disable v8-caching because it breaks ESM loaders NativeCompileCache.uninstall(); +export const ngEnvOptions: AngularEnvOptions = { + useAngularElementsPreview: false, + // angularElementsModulePath: require.resolve('@angular/elements'), + jestConfigPath: require.resolve('./jest/jest.config'), + jestModulePath: require.resolve('jest'), + ngPackagrModulePath: require.resolve('ng-packagr'), + 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')] }) +}; + export class AngularV14Env extends AngularBaseEnv { /** * name of the environment. used for friendly mentions across bit. @@ -14,18 +27,7 @@ export class AngularV14Env extends AngularBaseEnv { angularVersion = 14; - ngEnvOptions: AngularEnvOptions = { - useAngularElementsPreview: false, - // angularElementsModulePath: require.resolve('@angular/elements'), - jestConfigPath: require.resolve('./jest/jest.config'), - jestModulePath: require.resolve('jest'), - ngPackagrModulePath: require.resolve('ng-packagr'), - 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')] }) - }; + ngEnvOptions: AngularEnvOptions = ngEnvOptions; } export default new AngularV14Env(); diff --git a/angular/envs/angular-v14-env/index.ts b/angular/envs/angular-v14-env/index.ts index a0f0d5f0..7b75cf55 100644 --- a/angular/envs/angular-v14-env/index.ts +++ b/angular/envs/angular-v14-env/index.ts @@ -1,2 +1,2 @@ -export { AngularV14Env } from './angular-v14-env.bit-env'; +export { AngularV14Env, ngEnvOptions } from './angular-v14-env.bit-env'; export { default as jestConfig } from './jest/jest.config'; diff --git a/angular/envs/angular-v15-env/angular-v15-env.bit-env.ts b/angular/envs/angular-v15-env/angular-v15-env.bit-env.ts index ae8f3df5..7b4cb674 100644 --- a/angular/envs/angular-v15-env/angular-v15-env.bit-env.ts +++ b/angular/envs/angular-v15-env/angular-v15-env.bit-env.ts @@ -6,6 +6,19 @@ import { webpackConfigFactory } from './webpack-config.factory'; // Disable v8-caching because it breaks ESM loaders NativeCompileCache.uninstall(); +export const ngEnvOptions: AngularEnvOptions = { + useAngularElementsPreview: false, + // angularElementsModulePath: require.resolve('@angular/elements'), + jestConfigPath: require.resolve('./jest/jest.config'), + jestModulePath: require.resolve('jest'), + ngPackagrModulePath: require.resolve('ng-packagr'), + 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')] }) +}; + export class AngularV15Env extends AngularBaseEnv { /** * name of the environment. used for friendly mentions across bit. @@ -14,18 +27,7 @@ export class AngularV15Env extends AngularBaseEnv { angularVersion = 15; - ngEnvOptions: AngularEnvOptions = { - useAngularElementsPreview: false, - // angularElementsModulePath: require.resolve('@angular/elements'), - jestConfigPath: require.resolve('./jest/jest.config'), - jestModulePath: require.resolve('jest'), - ngPackagrModulePath: require.resolve('ng-packagr'), - 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')] }) - }; + ngEnvOptions: AngularEnvOptions = ngEnvOptions; } export default new AngularV15Env(); diff --git a/angular/envs/angular-v15-env/index.ts b/angular/envs/angular-v15-env/index.ts index 3c52439f..ce78f6d3 100644 --- a/angular/envs/angular-v15-env/index.ts +++ b/angular/envs/angular-v15-env/index.ts @@ -1,2 +1,2 @@ -export { AngularV15Env } from './angular-v15-env.bit-env'; +export { AngularV15Env, ngEnvOptions } from './angular-v15-env.bit-env'; export { default as jestConfig } from './jest/jest.config'; 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 ac13194e..5c702a58 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 @@ -6,6 +6,20 @@ import { webpackConfigFactory } from './webpack-config.factory'; // Disable v8-caching because it breaks ESM loaders NativeCompileCache.uninstall(); +export const ngEnvOptions: AngularEnvOptions = { + useAngularElementsPreview: false, + // angularElementsModulePath: require.resolve('@angular/elements'), + jestConfigPath: require.resolve('./jest/jest.config'), + jestModulePath: require.resolve('jest'), + ngPackagrModulePath: require.resolve('ng-packagr'), + 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', +}; + export class AngularV16Env extends AngularBaseEnv { /** * name of the environment. used for friendly mentions across bit. @@ -14,19 +28,7 @@ export class AngularV16Env extends AngularBaseEnv { angularVersion = 16; - ngEnvOptions: AngularEnvOptions = { - useAngularElementsPreview: false, - // angularElementsModulePath: require.resolve('@angular/elements'), - jestConfigPath: require.resolve('./jest/jest.config'), - jestModulePath: require.resolve('jest'), - ngPackagrModulePath: require.resolve('ng-packagr'), - 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', - }; + ngEnvOptions: AngularEnvOptions = ngEnvOptions; } export default new AngularV16Env(); diff --git a/angular/envs/angular-v16-env/index.ts b/angular/envs/angular-v16-env/index.ts index 7f72c4c7..ae2c89a3 100644 --- a/angular/envs/angular-v16-env/index.ts +++ b/angular/envs/angular-v16-env/index.ts @@ -1,2 +1,2 @@ -export { AngularV16Env } from './angular-v16-env.bit-env'; +export { AngularV16Env, ngEnvOptions } from './angular-v16-env.bit-env'; export { default as jestConfig } from './jest/jest.config'; 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 index 25fef3c7..2f8d756a 100644 --- a/angular/envs/angular-v17-env/angular-v17-env.bit-env.ts +++ b/angular/envs/angular-v17-env/angular-v17-env.bit-env.ts @@ -6,6 +6,20 @@ import { webpackConfigFactory } from './webpack-config.factory'; // Disable v8-caching because it breaks ESM loaders NativeCompileCache.uninstall(); +export const ngEnvOptions: AngularEnvOptions = { + useAngularElementsPreview: false, + // angularElementsModulePath: require.resolve('@angular/elements'), + jestConfigPath: require.resolve('./jest/jest.config'), + jestModulePath: require.resolve('jest'), + ngPackagrModulePath: require.resolve('ng-packagr'), + 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: 'vite', +}; + export class AngularV17Env extends AngularBaseEnv { /** * name of the environment. used for friendly mentions across bit. @@ -14,19 +28,7 @@ export class AngularV17Env extends AngularBaseEnv { angularVersion = 17; - ngEnvOptions: AngularEnvOptions = { - useAngularElementsPreview: false, - // angularElementsModulePath: require.resolve('@angular/elements'), - jestConfigPath: require.resolve('./jest/jest.config'), - jestModulePath: require.resolve('jest'), - ngPackagrModulePath: require.resolve('ng-packagr'), - 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: 'vite', - }; + ngEnvOptions: AngularEnvOptions = ngEnvOptions; } export default new AngularV17Env(); diff --git a/angular/envs/angular-v17-env/index.ts b/angular/envs/angular-v17-env/index.ts index ce036ab5..967d5a7a 100644 --- a/angular/envs/angular-v17-env/index.ts +++ b/angular/envs/angular-v17-env/index.ts @@ -1,2 +1,2 @@ -export { AngularV17Env } from './angular-v17-env.bit-env'; +export { AngularV17Env, ngEnvOptions } from './angular-v17-env.bit-env'; export { default as jestConfig } from './jest/jest.config'; diff --git a/angular/envs/base-env/angular-base-env.bit-env.ts b/angular/envs/base-env/angular-base-env.bit-env.ts index c1dd8962..a96a87f6 100644 --- a/angular/envs/base-env/angular-base-env.bit-env.ts +++ b/angular/envs/base-env/angular-base-env.bit-env.ts @@ -1,21 +1,9 @@ -import { AngularAppType } from '@bitdev/angular.app-types.angular-app-type'; -import { - AngularEnvOptions, - ApplicationOptions, - BrowserOptions, - DevServerOptions, - NG_APP_NAME -} from '@bitdev/angular.dev-services.common'; +import { AngularEnvOptions } from '@bitdev/angular.dev-services.common'; import { NgMultiCompiler, NgMultiCompilerTask } from '@bitdev/angular.dev-services.compiler.multi-compiler'; -import { - AngularPreview, - BundlerProvider, - DevServerProvider -} from '@bitdev/angular.dev-services.preview.preview'; -import { NgWebpackBundler, NgWebpackDevServer } from '@bitdev/angular.dev-services.webpack'; +import { AngularPreview } from '@bitdev/angular.dev-services.preview.preview'; import { NgAppTemplate, NgEnvTemplate, @@ -27,14 +15,12 @@ import { DesignSystemStarter, MaterialDesignSystemStarter } from '@bitdev/angular.templates.starters'; -import { AppTypeList } from '@teambit/application'; import { Pipeline } from '@teambit/builder'; -import { Bundler, BundlerContext, DevServer, DevServerContext } from '@teambit/bundler'; import { Compiler } from '@teambit/compiler'; import { EslintConfigWriter, ESLintLinter, EslintTask } from '@teambit/defender.eslint-linter'; import { JestTask, JestTester } from '@teambit/defender.jest-tester'; import { PrettierConfigWriter, PrettierFormatter } from '@teambit/defender.prettier-formatter'; -import { AsyncEnvHandler, EnvHandler } from '@teambit/envs'; +import { EnvHandler } from '@teambit/envs'; import { Formatter } from '@teambit/formatter'; import { StarterList, TemplateList } from '@teambit/generator'; import { Linter } from '@teambit/linter'; @@ -44,7 +30,6 @@ import { SchemaExtractor } from '@teambit/schema'; import { Tester } from '@teambit/tester'; import { TypeScriptExtractor } from '@teambit/typescript'; import { TypescriptConfigWriter } from '@teambit/typescript.typescript-compiler'; -import { WebpackConfigTransformer } from '@teambit/webpack'; import { ConfigWriterList } from '@teambit/workspace-config-files'; import { ESLint as ESLintLib } from 'eslint'; import { merge } from 'lodash'; @@ -237,8 +222,4 @@ export abstract class AngularBaseEnv implements AngularEnvInterface { tester(): EnvHandler { return JestTester.from(this.getTesterConfig()); } - - apps(): EnvHandler { - return AppTypeList.from([AngularAppType.from({ angularEnv: this, name: NG_APP_NAME })]); - } } diff --git a/angular/templates/generators/ng-app/index.ts b/angular/templates/generators/ng-app/index.ts index 2e33a435..9a8c603d 100644 --- a/angular/templates/generators/ng-app/index.ts +++ b/angular/templates/generators/ng-app/index.ts @@ -6,7 +6,7 @@ import { Logger } from '@teambit/logger'; import { isCI } from 'std-env'; import { indexFile } from './template-files'; import { docsFile } from './template-files/docs'; -import { ngAppFile } from './template-files/ng-app'; +import { ngAppFile } from './template-files/bit-app'; import { appComponentFile } from './template-files/src/app/app.component'; import { appComponentHtmlFile } from './template-files/src/app/app.component-html'; import { appComponentStyleSheetFile } from './template-files/src/app/app.component-scss'; diff --git a/angular/templates/generators/ng-app/template-files/ng-app.ts b/angular/templates/generators/ng-app/template-files/bit-app.ts similarity index 77% rename from angular/templates/generators/ng-app/template-files/ng-app.ts rename to angular/templates/generators/ng-app/template-files/bit-app.ts index 4445b08a..3e27f8ea 100644 --- a/angular/templates/generators/ng-app/template-files/ng-app.ts +++ b/angular/templates/generators/ng-app/template-files/bit-app.ts @@ -3,9 +3,10 @@ import { ComponentContext, ComponentFile } from '@teambit/generator'; export const ngAppFile = (context: ComponentContext, styleSheet: string, ssr: boolean): ComponentFile => { const { name, namePascalCase: Name } = context; return { - relativePath: `${name}.ng-app.ts`, - content: `import { AngularAppOptions } from '@bitdev/angular.app-types.angular-app-type'; + relativePath: `${name}.bit-app.ts`, + content: `import { type AngularAppOptions, AngularApp } from '@bitdev/angular.app-types.angular-app-type'; import { ${ssr ? `ApplicationOptions`: `BrowserOptions` }, DevServerOptions } from '@bitdev/angular.dev-services.common'; +import { ngEnvOptions } from '@bitdev/angular.envs.angular-v17-env'; const angularOptions: ${ssr ? `ApplicationOptions`: `BrowserOptions` } & DevServerOptions = { ${ssr ? `browser: './src/main.ts', @@ -39,13 +40,18 @@ export const ${Name}Options: AngularAppOptions = { */ angularServeOptions: angularOptions, + /** + * Env-specific options depending on the version of Angular used. + */ + ngEnvOptions, + /** * Folder containing the main file of your application */ sourceRoot: './src', }; -export default ${Name}Options; +export default AngularApp.from(${Name}Options); `, }; }; diff --git a/angular/templates/generators/ng-app/template-files/index.ts b/angular/templates/generators/ng-app/template-files/index.ts index 51fe4022..416d8fe6 100644 --- a/angular/templates/generators/ng-app/template-files/index.ts +++ b/angular/templates/generators/ng-app/template-files/index.ts @@ -5,6 +5,6 @@ export const indexFile = (context: ComponentContext): ComponentFile => { return { relativePath: `index.ts`, isMain: true, - content: `export * from './${name}.ng-app';` + content: `export * from './${name}.bit-app';` }; }; diff --git a/integration/demo-app/demo-app.ng-app.ts b/integration/demo-app/demo-app.bit-app.ts similarity index 69% rename from integration/demo-app/demo-app.ng-app.ts rename to integration/demo-app/demo-app.bit-app.ts index 5a56a413..3404d280 100644 --- a/integration/demo-app/demo-app.ng-app.ts +++ b/integration/demo-app/demo-app.bit-app.ts @@ -1,5 +1,6 @@ -import type { AngularAppOptions } from '@bitdev/angular.app-types.angular-app-type'; +import { type AngularAppOptions, AngularApp } from '@bitdev/angular.app-types.angular-app-type'; import type { ApplicationOptions, DevServerOptions } from '@bitdev/angular.dev-services.common'; +import { ngEnvOptions } from '@bitdev/angular.envs.angular-v17-env'; const angularOptions: ApplicationOptions & DevServerOptions = { browser: './src/main.ts', @@ -32,7 +33,12 @@ export const DemoAppOptions: AngularAppOptions = { /** * Angular options for `bit run` */ - angularServeOptions: angularOptions + angularServeOptions: angularOptions, + + /** + * Env-specific options depending on the version of Angular used. + */ + ngEnvOptions }; -export default DemoAppOptions; +export default AngularApp.from(DemoAppOptions); diff --git a/integration/demo-app/index.ts b/integration/demo-app/index.ts index 82da6d94..60d474cd 100644 --- a/integration/demo-app/index.ts +++ b/integration/demo-app/index.ts @@ -1 +1 @@ -export * from './demo-app.ng-app'; +export * from './demo-app.bit-app';