66 * found in the LICENSE file at https://angular.io/license
77 */
88
9+ import { dirname , normalize , relative } from '@angular-devkit/core' ;
910import { DirEntry , Rule , chain } from '@angular-devkit/schematics' ;
1011import { addDependency } from '../../utility' ;
1112import { getPackageJsonDependency , removePackageJsonDependency } from '../../utility/dependencies' ;
@@ -81,17 +82,47 @@ export default function (): Rule {
8182 }
8283 }
8384
84- // Replace server file
85+ // Replace all import specifiers in all files.
86+ let hasExpressTokens = false ;
87+ const root = project . sourceRoot ?? `${ project . root } /src` ;
88+ const tokensFilePath = `/${ root } /express.tokens.ts` ;
89+
90+ for ( const file of visit ( tree . getDir ( root ) ) ) {
91+ const [ path , content ] = file ;
92+ let updatedContent = content ;
93+
94+ // Check if file is importing tokens
95+ if ( content . includes ( '@nguniversal/express-engine/tokens' ) ) {
96+ hasExpressTokens ||= true ;
97+
98+ let tokensFileRelativePath : string = relative (
99+ dirname ( normalize ( path ) ) ,
100+ normalize ( tokensFilePath ) ,
101+ ) ;
102+
103+ if ( tokensFileRelativePath . charAt ( 0 ) !== '.' ) {
104+ tokensFileRelativePath = './' + tokensFileRelativePath ;
105+ }
106+
107+ updatedContent = updatedContent . replaceAll (
108+ '@nguniversal/express-engine/tokens' ,
109+ tokensFileRelativePath . slice ( 0 , - 3 ) ,
110+ ) ;
111+ }
112+
113+ updatedContent = updatedContent . replaceAll ( NGUNIVERSAL_PACKAGE_REGEXP , '@angular/ssr' ) ;
114+ tree . overwrite ( path , updatedContent ) ;
115+ }
116+
117+ // Replace server file and add tokens file if needed
85118 for ( const [ path , outputPath ] of serverMainFiles . entries ( ) ) {
86119 tree . rename ( path , path + '.bak' ) ;
87- tree . create ( path , getServerFileContents ( outputPath ) ) ;
88- }
89- }
120+ tree . create ( path , getServerFileContents ( outputPath , hasExpressTokens ) ) ;
90121
91- // Replace all import specifiers in all files.
92- for ( const file of visit ( tree . root ) ) {
93- const [ path , content ] = file ;
94- tree . overwrite ( path , content . replaceAll ( NGUNIVERSAL_PACKAGE_REGEXP , '@angular/ssr' ) ) ;
122+ if ( hasExpressTokens ) {
123+ tree . create ( tokensFilePath , TOKENS_FILE_CONTENT ) ;
124+ }
125+ }
95126 }
96127
97128 // Remove universal packages from deps.
@@ -104,16 +135,27 @@ export default function (): Rule {
104135 } ;
105136}
106137
107- function getServerFileContents ( outputPath : string ) : string {
108- return `
138+ const TOKENS_FILE_CONTENT = `
139+ import { InjectionToken } from '@angular/core';
140+ import { Request, Response } from 'express';
141+
142+ export const REQUEST = new InjectionToken<Request>('REQUEST');
143+ export const RESPONSE = new InjectionToken<Response>('RESPONSE');
144+ ` ;
145+
146+ function getServerFileContents ( outputPath : string , hasExpressTokens : boolean ) : string {
147+ return (
148+ `
109149import 'zone.js/node';
110150
111151import { APP_BASE_HREF } from '@angular/common';
112152import { CommonEngine } from '@angular/ssr';
113153import * as express from 'express';
114154import { existsSync } from 'node:fs';
115155import { join } from 'node:path';
116- import bootstrap from './src/main.server';
156+ import bootstrap from './src/main.server';` +
157+ ( hasExpressTokens ? `\nimport { REQUEST, RESPONSE } from './src/express.tokens';` : '' ) +
158+ `
117159
118160// The Express app is exported so that it can be used by serverless Functions.
119161export function app(): express.Express {
@@ -145,7 +187,12 @@ export function app(): express.Express {
145187 documentFilePath: indexHtml,
146188 url: \`\${protocol}://\${headers.host}\${originalUrl}\`,
147189 publicPath: distFolder,
148- providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
190+ providers: [
191+ { provide: APP_BASE_HREF, useValue: baseUrl },` +
192+ ( hasExpressTokens
193+ ? '\n { provide: RESPONSE, useValue: res },\n { provide: REQUEST, useValue: req }\n'
194+ : '' ) +
195+ `],
149196 })
150197 .then((html) => res.send(html))
151198 .catch((err) => next(err));
@@ -175,5 +222,6 @@ if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
175222}
176223
177224export default bootstrap;
178- ` ;
225+ `
226+ ) ;
179227}
0 commit comments