Skip to content

Commit d8af697

Browse files
committed
seperate version detection for angular/core and ssr
1 parent 5cafda5 commit d8af697

3 files changed

Lines changed: 53 additions & 21 deletions

File tree

src/helpers/getPackageVersion.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,15 @@ import { createRequire } from 'node:module'
33
import { join } from 'node:path'
44

55
/**
6-
* Get Angular version from package.json.
6+
* Get @angular/core version from package.json.
77
* @param {string} root
88
* @returns {Promise<string | undefined>}
99
*/
10-
export async function getAngularVersion(root) {
10+
export async function getAngularCoreVersion(root) {
1111
let packagePath
1212
try {
1313
const require = createRequire(import.meta.url)
14-
15-
// we're checking @angular/ssr version
16-
// there could be patch-level differences in this and @angular/core
17-
// but in serverModuleHelpers.js, we need patch-level matching of the ssr package
18-
// so we cannot rely on the version of core anymore
19-
packagePath = require.resolve('@angular/ssr/package.json', { paths: [root] })
14+
packagePath = require.resolve('@angular/core/package.json', { paths: [root] })
2015
} catch {
2116
// module not found
2217
return
@@ -46,3 +41,23 @@ export async function getAngularRuntimeVersion(root) {
4641
const { version } = JSON.parse(contents)
4742
return version
4843
}
44+
45+
/**
46+
* Get @angular/ssr from package.json.
47+
* @param {string} root
48+
* @returns {Promise<string | undefined>}
49+
*/
50+
export async function getAngularSsrVersion(root) {
51+
let packagePath
52+
try {
53+
const require = createRequire(import.meta.url)
54+
packagePath = require.resolve('@angular/ssr/package.json', { paths: [root] })
55+
} catch {
56+
// module not found
57+
return
58+
}
59+
60+
const contents = await readFile(packagePath)
61+
const { version } = JSON.parse(contents)
62+
return version
63+
}

src/helpers/serverModuleHelpers.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,22 +125,30 @@ function guessUsedEngine(serverModuleContents) {
125125
*
126126
* @returns {'AppEngine' | 'CommonEngine' | undefined}
127127
*/
128-
export async function fixServerTs({ angularVersion, siteRoot, failPlugin, failBuild, workspaceType, packagePath }) {
129-
if (!satisfies(angularVersion, '>=19.0.0-rc', { includePrerelease: true })) {
128+
export async function fixServerTs({
129+
angularCoreVersion,
130+
angularSsrVersion,
131+
siteRoot,
132+
failPlugin,
133+
failBuild,
134+
workspaceType,
135+
packagePath,
136+
}) {
137+
if (!satisfies(angularCoreVersion, '>=19.0.0-rc', { includePrerelease: true })) {
130138
// for pre-19 versions, we don't need to do anything
131139
return
132140
}
133141

134142
const angularJson = getAngularJson({ failPlugin, siteRoot, workspaceType, packagePath })
135143

136-
// Angular v21.1 introduced `allowedHosts`: https://github.com/angular/angular-cli/blob/21.1.x/packages/angular/ssr/src/app-engine.ts
137-
// Angular v21.2.9 introduced `trustProxyHeaders` as well: https://github.com/angular/angular-cli/blob/21.2.x/packages/angular/ssr/src/app-engine.ts
144+
// @angular/ssr v21.1.5 introduced `allowedHosts`: https://github.com/angular/angular-cli/releases/tag/v21.1.5
145+
// @angular/ssr v21.2.9 introduced `trustProxyHeaders`: https://github.com/angular/angular-cli/releases/tag/v21.2.9
138146
// we cannot add the config if the version doesn't support it
139147
// because TypeScript complains about invalid properties
140148
let NetlifyServerTsAppEngine = NetlifyServerTsAppEngine21Dot0
141-
if (satisfies(angularVersion, '>=21.2.9', { includePrerelease: true })) {
149+
if (satisfies(angularSsrVersion, '>=21.2.9', { includePrerelease: true })) {
142150
NetlifyServerTsAppEngine = NetlifyServerTsAppEngine21Dot2Dot9
143-
} else if (satisfies(angularVersion, '>=21.1.5', { includePrerelease: true })) {
151+
} else if (satisfies(angularSsrVersion, '>=21.1.5', { includePrerelease: true })) {
144152
NetlifyServerTsAppEngine = NetlifyServerTsAppEngine21Dot1Dot5
145153
}
146154

@@ -158,11 +166,11 @@ export async function fixServerTs({ angularVersion, siteRoot, failPlugin, failBu
158166
const angularRuntimeVersionInstalledByUser = await getAngularRuntimeVersion(siteRoot)
159167
if (!angularRuntimeVersionInstalledByUser) {
160168
failBuild(
161-
`Angular@${angularVersion} SSR on Netlify requires '@netlify/angular-runtime' version 2.2.0 or later to be installed. Please install it and try again.`,
169+
`Angular@${angularCoreVersion} SSR on Netlify requires '@netlify/angular-runtime' version 2.2.0 or later to be installed. Please install it and try again.`,
162170
)
163171
} else if (!satisfies(angularRuntimeVersionInstalledByUser, '>=2.2.0', { includePrerelease: true })) {
164172
failBuild(
165-
`Angular@${angularVersion} SSR on Netlify requires '@netlify/angular-runtime' version 2.2.0 or later to be installed. Found version "${angularRuntimeVersionInstalledByUser}". Please update it to version 2.2.0 or later and try again.`,
173+
`Angular@${angularCoreVersion} SSR on Netlify requires '@netlify/angular-runtime' version 2.2.0 or later to be installed. Found version "${angularRuntimeVersionInstalledByUser}". Please update it to version 2.2.0 or later and try again.`,
166174
)
167175
}
168176

@@ -212,7 +220,7 @@ export async function fixServerTs({ angularVersion, siteRoot, failPlugin, failBu
212220
return 'CommonEngine'
213221
}
214222

215-
if (satisfies(angularVersion, '<20', { includePrerelease: true })) {
223+
if (satisfies(angularCoreVersion, '<20', { includePrerelease: true })) {
216224
// at this point we know that user's server.ts is not Netlify compatible so user intervention is required
217225
// we will try to inspect server.ts to determine which engine is used and provide more accurate error message
218226
const guessedUsedEngine = guessUsedEngine(serverModuleContents)

src/index.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ensureNoCompetingPlugin from './helpers/ensureNoCompetingPlugin.js'
44
import fixOutputDir from './helpers/fixOutputDir.js'
55
import getAngularJson from './helpers/getAngularJson.js'
66
import { getAngularRoot } from './helpers/getAngularRoot.js'
7-
import { getAngularVersion } from './helpers/getPackageVersion.js'
7+
import { getAngularCoreVersion, getAngularSsrVersion } from './helpers/getPackageVersion.js'
88
import { fixServerTs, revertServerTsFix } from './helpers/serverModuleHelpers.js'
99
import { getBuildInformation, setUpEdgeFunction } from './helpers/setUpEdgeFunction.js'
1010
import { setUpHeaders } from './helpers/setUpHeaders.js'
@@ -16,8 +16,16 @@ let usedEngine
1616
export async function onPreBuild({ netlifyConfig, utils, constants }) {
1717
const { failBuild, failPlugin } = utils.build
1818
const { siteRoot, workspaceType } = getAngularRoot({ failBuild, netlifyConfig })
19-
const angularVersion = await getAngularVersion(siteRoot)
20-
isValidAngularProject = validateAngularVersion(angularVersion)
19+
20+
// @angular/core and @angular/ssr are only synced to major versions
21+
// for minor or patch versions, it's not guaranteed to be in sync
22+
// we need to check versions of both deps as @angular/ssr might not
23+
// be installed by users not trying to use SSR, but we need
24+
// patch-version level detection in serverModuleHelpers.js
25+
const angularCoreVersion = await getAngularCoreVersion(siteRoot)
26+
const angularSsrVersion = await getAngularSsrVersion(siteRoot)
27+
28+
isValidAngularProject = validateAngularVersion(angularCoreVersion)
2129

2230
if (!isValidAngularProject) {
2331
console.warn('Skipping build plugin.')
@@ -40,7 +48,8 @@ export async function onPreBuild({ netlifyConfig, utils, constants }) {
4048
})
4149

4250
usedEngine = await fixServerTs({
43-
angularVersion,
51+
angularCoreVersion,
52+
angularSsrVersion,
4453
siteRoot,
4554
failPlugin,
4655
failBuild,

0 commit comments

Comments
 (0)