1- import { GenericAngularEnv } from '@bitdev/angular.dev-services.common' ;
2- import { AngularPreview , BundlerProvider , DevServerProvider } from '@bitdev/angular.dev-services.preview.preview' ;
1+ import { VERSION } from '@angular/cli' ;
2+ import {
3+ ApplicationOptions ,
4+ GenericAngularEnv ,
5+ normalizePath
6+ } from '@bitdev/angular.dev-services.common' ;
7+ import {
8+ AngularPreview ,
9+ BundlerProvider ,
10+ DevServerProvider
11+ } from '@bitdev/angular.dev-services.preview.preview' ;
312import { AppBuildContext , AppContext , Application } from '@teambit/application' ;
413import { Bundler , BundlerContext , DevServer , DevServerContext } from '@teambit/bundler' ;
514import { Component } from '@teambit/component' ;
615import { DependencyResolverMain } from '@teambit/dependency-resolver' ;
716import { EnvContext , EnvHandler } from '@teambit/envs' ;
817import { CACHE_ROOT } from '@teambit/legacy/dist/constants' ;
9- import { pathNormalizeToLinux } from '@teambit/legacy/dist/utils ' ;
18+ import { Logger } from '@teambit/logger ' ;
1019import { Preview } from '@teambit/preview' ;
1120import { Port } from '@teambit/toolbox.network.get-port' ;
1221import { Workspace } from '@teambit/workspace' ;
13- import { existsSync , mkdirSync , writeFileSync } from 'fs-extra' ;
22+ import assert from 'assert' ;
23+ import { existsSync , mkdirSync , outputJsonSync } from 'fs-extra' ;
1424import { cloneDeep } from 'lodash' ;
1525import objectHash from 'object-hash' ;
1626import { join } from 'path' ;
1727import { readConfigFile , sys } from 'typescript' ;
1828import { AngularAppOptions } from './angular-app-options' ;
1929import { AngularAppBuildResult } from './angular-build-result' ;
20- import { expandIncludeExclude } from './utils' ;
30+ import { buildApplication } from './application.bundler' ;
31+ import { serveApplication } from './application.dev-server' ;
32+ import { expandIncludeExclude , JsonObject } from './utils' ;
2133
2234const writeHash = new Map < string , string > ( ) ;
2335
@@ -35,17 +47,18 @@ export class AngularApp implements Application {
3547 private envContext : EnvContext ,
3648 readonly options : AngularAppOptions ,
3749 private depsResolver : DependencyResolverMain ,
50+ private logger : Logger ,
3851 private workspace ?: Workspace
3952 ) {
4053 this . name = options . name ;
4154
42- const idName = `bitdev.angular/${ this . name } ` ;
55+ const idName = `bitdev.angular/${ this . name } ` ;
4356 this . tempFolder = workspace ?. getTempDir ( idName ) || join ( CACHE_ROOT , idName ) ;
4457 if ( ! existsSync ( this . tempFolder ) ) {
4558 mkdirSync ( this . tempFolder , { recursive : true } ) ;
4659 }
4760
48- this . tsconfigPath = pathNormalizeToLinux ( join ( this . tempFolder , `__tsconfig -${ Date . now ( ) } .json` ) ) ;
61+ this . tsconfigPath = normalizePath ( join ( this . tempFolder , `tsconfig/tsconfig -${ Date . now ( ) } .json` ) ) ;
4962 this . preview = this . getPreview ( ) ;
5063 }
5164
@@ -55,19 +68,20 @@ export class AngularApp implements Application {
5568 return join ( artifactsDir , this . name ) ;
5669 }
5770
58- private getDevServerContext ( context : AppContext ) : DevServerContext {
71+ private getDevServerContext ( context : AppContext , appRootPath : string ) : DevServerContext {
72+ // const ngEnvOptions = this.angularEnv.getNgEnvOptions();
5973 return Object . assign ( cloneDeep ( context ) , {
6074 entry : [ ] ,
61- rootPath : '' ,
62- publicPath : `${ this . publicDir } /${ this . options . name } ` ,
75+ rootPath : /*ngEnvOptions.devServer === 'vite' ? appRootPath : */ '' ,
76+ publicPath : `${ this . publicDir } /${ this . options . name } ` ,
6377 title : this . options . name
6478 } ) ;
6579 }
6680
6781 private getBundlerContext ( context : AppBuildContext ) : BundlerContext {
6882 const { capsule, artifactsDir } = context ;
6983 const publicDir = this . getPublicDir ( artifactsDir ) ;
70- const outputPath = pathNormalizeToLinux ( join ( capsule . path , publicDir ) ) ;
84+ const outputPath = normalizePath ( join ( capsule . path , publicDir ) ) ;
7185
7286 return Object . assign ( cloneDeep ( context ) , {
7387 targets : [ {
@@ -76,7 +90,7 @@ export class AngularApp implements Application {
7690 outputPath
7791 } ] ,
7892 entry : [ ] ,
79- rootPath : '/ ' ,
93+ rootPath : '. ' ,
8094 appName : this . options . name
8195 } ) ;
8296 }
@@ -97,84 +111,115 @@ export class AngularApp implements Application {
97111 } ) ;
98112 }
99113
100- private generateTsConfig ( bitCmps : Component [ ] , appRootPath : string , tsconfigPath : string ) : string {
101- const tsconfigJSON = readConfigFile ( tsconfigPath , sys . readFile ) . config ;
114+ private generateTsConfig ( bitCmps : Component [ ] , appRootPath : string , tsconfigPath : string , serverEntry ? : string ) : void {
115+ const tsconfigJSON : JsonObject = readConfigFile ( tsconfigPath , sys . readFile ) . config ;
102116
103117 // Add the paths to tsconfig to remap bit components to local folders
104118 tsconfigJSON . compilerOptions . paths = tsconfigJSON . compilerOptions . paths || { } ;
105119 bitCmps . forEach ( ( dep : Component ) => {
106- let componentDir = this . workspace ?. componentDir ( dep . id , {
107- ignoreVersion : true
108- } ) ;
109- if ( componentDir ) {
110- componentDir = pathNormalizeToLinux ( componentDir ) ;
111- const pkgName = this . depsResolver . getPackageName ( dep ) ;
112- // TODO we should find a way to use the real entry file based on the component config because people can change it
113- tsconfigJSON . compilerOptions . paths [ pkgName ] = [ `${ componentDir } /public-api.ts` , `${ componentDir } ` ] ;
114- tsconfigJSON . compilerOptions . paths [ `${ pkgName } /*` ] = [ `${ componentDir } /*` ] ;
115- }
120+ let componentDir = this . workspace ?. componentDir ( dep . id , {
121+ ignoreVersion : true
122+ } ) ;
123+ if ( componentDir ) {
124+ componentDir = normalizePath ( componentDir ) ;
125+ const pkgName = this . depsResolver . getPackageName ( dep ) ;
126+ // TODO we should find a way to use the real entry file based on the component config because people can change it
127+ tsconfigJSON . compilerOptions . paths [ pkgName ] = [ `${ componentDir } /public-api.ts` , `${ componentDir } ` ] ;
128+ tsconfigJSON . compilerOptions . paths [ `${ pkgName } /*` ] = [ `${ componentDir } /*` ] ;
129+ }
116130 } ) ;
117131
132+ if ( serverEntry ) {
133+ tsconfigJSON . files . push ( serverEntry ) ;
134+ }
135+
118136 const tsconfigContent = expandIncludeExclude ( tsconfigJSON , this . tsconfigPath , [ appRootPath ] ) ;
119137 const hash = objectHash ( tsconfigContent ) ;
120-
121138 // write only if link has changed (prevents triggering fs watches)
122139 if ( writeHash . get ( this . tsconfigPath ) !== hash ) {
123- writeFileSync ( this . tsconfigPath , tsconfigContent ) ;
140+ outputJsonSync ( this . tsconfigPath , tsconfigContent , { spaces : 2 } ) ;
124141 writeHash . set ( this . tsconfigPath , hash ) ;
125142 }
143+ }
144+
145+ async getDevServer ( context : AppContext , appRootPath : string ) : Promise < DevServer > {
146+ const devServerContext = this . getDevServerContext ( context , appRootPath ) ;
147+ const preview = this . preview ( this . envContext ) ;
126148
127- return tsconfigContent ;
149+ return preview . getDevServer ( devServerContext ) ( this . envContext ) ;
128150 }
129151
130- async getDevServer ( context : AppContext ) : Promise < DevServer > {
131- if ( ! this . workspace ) {
132- throw new Error ( ' workspace is not defined') ;
133- }
152+ // TODO: fix return type once bit has a new stable version
153+ async run ( context : AppContext ) : Promise < any > {
154+ assert ( this . workspace , 'Workspace is not defined') ;
155+ const port = context . port || ( await Port . getPortFromRange ( this . options . portRange || [ 3000 , 4000 ] ) ) ;
134156 const appRootPath = this . workspace . componentDir ( context . appComponent . id , {
135157 ignoreVersion : true
136- } ) || '' ;
158+ } ) ;
137159 const tsconfigPath = join ( appRootPath , this . options . angularServeOptions . tsConfig ) ;
138160 const workspaceCmpsIDs = await this . workspace . listIds ( ) ;
139161 const bitCmps = await this . workspace . getMany ( workspaceCmpsIDs ) ;
140162 this . generateTsConfig ( bitCmps , appRootPath , tsconfigPath ) ;
141- const devServerContext = this . getDevServerContext ( context ) ;
142- const preview = this . preview ( this . envContext ) ;
143163
144- return preview . getDevServer ( devServerContext ) ( this . envContext ) ;
145- }
164+ if ( Number ( VERSION . major ) >= 16 ) {
165+ await serveApplication ( {
166+ angularOptions : {
167+ ...this . options . angularBuildOptions as ApplicationOptions ,
168+ tsConfig : this . tsconfigPath
169+ } ,
170+ sourceRoot : this . options . sourceRoot || 'src' ,
171+ workspaceRoot : appRootPath ,
172+ port,
173+ logger : this . logger ,
174+ tempFolder : this . tempFolder
175+ } ) ;
176+ return port ;
177+ }
146178
147- async run ( context : AppContext ) : Promise < number > {
148- const port = context . port || ( await Port . getPortFromRange ( this . options . portRange || [ 3000 , 4000 ] ) ) ;
149- const devServer = await this . getDevServer ( context ) ;
179+ const devServer = await this . getDevServer ( context , appRootPath ) ;
150180 await devServer . listen ( port ) ;
151181 return port ;
152182 }
153183
154184 async getBundler ( context : AppBuildContext ) : Promise < Bundler > {
155- if ( this . options . bundler && typeof this . options . bundler !== 'string' ) {
156- return this . options . bundler as Bundler ;
185+ if ( this . options . bundler ) {
186+ return this . options . bundler ;
157187 }
158188
159- if ( this . options . bundler === 'vite' ) {
160- throw new Error ( 'implement vite bundler' ) ;
161- }
162-
163- const { capsule } = context ;
164- const appRootPath = capsule . path ;
165- const tsconfigPath = join ( appRootPath , this . options . angularBuildOptions . tsConfig ) ;
166- this . generateTsConfig ( [ capsule . component ] , appRootPath , tsconfigPath ) ;
167189 const bundlerContext = this . getBundlerContext ( context ) ;
168190 const preview = this . preview ( this . envContext ) ;
169191
170192 return preview . getBundler ( bundlerContext ) ( this . envContext ) ;
171193 }
172194
173195 async build ( context : AppBuildContext ) : Promise < AngularAppBuildResult > {
174- const bundler = await this . getBundler ( context ) ;
175- await bundler . run ( ) ;
196+ const { capsule } = context ;
197+ const outputPath = this . getPublicDir ( context . artifactsDir ) ;
198+ const appRootPath = capsule . path ;
199+ const tsconfigPath = join ( appRootPath , this . options . angularBuildOptions . tsConfig ) ;
200+ const appOptions = this . options . angularBuildOptions as ApplicationOptions ;
201+ const entryServer = appOptions . ssr && Number ( VERSION . major ) >= 17 ? './entry.server.ts' : undefined ;
202+ this . generateTsConfig ( [ capsule . component ] , appRootPath , tsconfigPath , entryServer ) ;
203+
204+ if ( ! this . options . bundler && Number ( VERSION . major ) >= 16 ) {
205+ await buildApplication ( {
206+ angularOptions : {
207+ ...appOptions ,
208+ tsConfig : this . tsconfigPath
209+ } ,
210+ outputPath,
211+ sourceRoot : this . options . sourceRoot || 'src' ,
212+ workspaceRoot : context . capsule . path ,
213+ logger : this . logger ,
214+ tempFolder : this . tempFolder ,
215+ entryServer
216+ } ) ;
217+ } else {
218+ const bundler = await this . getBundler ( context ) ;
219+ await bundler . run ( ) ;
220+ }
176221 return {
177- publicDir : ` ${ this . getPublicDir ( context . artifactsDir ) } / ${ this . publicDir } `
222+ publicDir : outputPath
178223 } ;
179224 }
180225}
0 commit comments