6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
+ import { dirname , normalize , relative } from '@angular-devkit/core' ;
9
10
import { DirEntry , Rule , chain } from '@angular-devkit/schematics' ;
10
11
import { addDependency } from '../../utility' ;
11
12
import { getPackageJsonDependency , removePackageJsonDependency } from '../../utility/dependencies' ;
@@ -81,17 +82,47 @@ export default function (): Rule {
81
82
}
82
83
}
83
84
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
85
118
for ( const [ path , outputPath ] of serverMainFiles . entries ( ) ) {
86
119
tree . rename ( path , path + '.bak' ) ;
87
- tree . create ( path , getServerFileContents ( outputPath ) ) ;
88
- }
89
- }
120
+ tree . create ( path , getServerFileContents ( outputPath , hasExpressTokens ) ) ;
90
121
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
+ }
95
126
}
96
127
97
128
// Remove universal packages from deps.
@@ -104,16 +135,27 @@ export default function (): Rule {
104
135
} ;
105
136
}
106
137
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
+ `
109
149
import 'zone.js/node';
110
150
111
151
import { APP_BASE_HREF } from '@angular/common';
112
152
import { CommonEngine } from '@angular/ssr';
113
153
import * as express from 'express';
114
154
import { existsSync } from 'node:fs';
115
155
import { 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
+ `
117
159
118
160
// The Express app is exported so that it can be used by serverless Functions.
119
161
export function app(): express.Express {
@@ -145,7 +187,12 @@ export function app(): express.Express {
145
187
documentFilePath: indexHtml,
146
188
url: \`\${protocol}://\${headers.host}\${originalUrl}\`,
147
189
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
+ `],
149
196
})
150
197
.then((html) => res.send(html))
151
198
.catch((err) => next(err));
@@ -175,5 +222,6 @@ if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
175
222
}
176
223
177
224
export default bootstrap;
178
- ` ;
225
+ `
226
+ ) ;
179
227
}
0 commit comments