From d3585da65814e225c6b1325c9039e025357374ec Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 1 Dec 2023 16:10:58 -0500 Subject: [PATCH 1/5] Add supported range warnings --- src/frameworks/angular/index.ts | 6 ++++- src/frameworks/angular/utils.ts | 17 +++++++++++- src/frameworks/astro/index.ts | 5 +++- src/frameworks/constants.ts | 43 ++++++++++++++++++++++++++----- src/frameworks/docs/nextjs.md | 2 +- src/frameworks/index.ts | 7 ++++- src/frameworks/interfaces.ts | 2 ++ src/frameworks/next/index.ts | 7 +++-- src/frameworks/nuxt/index.ts | 9 ++++--- src/frameworks/nuxt2/index.ts | 7 ++--- src/frameworks/sveltekit/index.ts | 1 + src/frameworks/vite/index.ts | 9 +++++-- 12 files changed, 93 insertions(+), 22 deletions(-) diff --git a/src/frameworks/angular/index.ts b/src/frameworks/angular/index.ts index 8afaea089bd..b170e9c0b78 100644 --- a/src/frameworks/angular/index.ts +++ b/src/frameworks/angular/index.ts @@ -20,6 +20,7 @@ import { } from "../utils"; import { getAllTargets, + getAngularVersion, getBrowserConfig, getBuildConfig, getContext, @@ -35,10 +36,13 @@ export const docsUrl = "https://firebase.google.com/docs/hosting/frameworks/angu const DEFAULT_BUILD_SCRIPT = ["ng build"]; +export const supportedRange = "17 || 16 || 15 || 14"; + export async function discover(dir: string): Promise { if (!(await pathExists(join(dir, "package.json")))) return; if (!(await pathExists(join(dir, "angular.json")))) return; - return { mayWantBackend: true, publicDirectory: join(dir, "src", "assets") }; + const version = getAngularVersion(dir); + return { mayWantBackend: true, publicDirectory: join(dir, "src", "assets"), version }; } export function init(setup: any, config: any) { diff --git a/src/frameworks/angular/utils.ts b/src/frameworks/angular/utils.ts index 5627a47345f..2d5fd2e9408 100644 --- a/src/frameworks/angular/utils.ts +++ b/src/frameworks/angular/utils.ts @@ -3,12 +3,13 @@ import type { ProjectDefinition } from "@angular-devkit/core/src/workspace"; import type { WorkspaceNodeModulesArchitectHost } from "@angular-devkit/architect/node"; import { AngularI18nConfig } from "./interfaces"; -import { relativeRequire, validateLocales } from "../utils"; +import { findDependency, relativeRequire, validateLocales } from "../utils"; import { FirebaseError } from "../../error"; import { join, posix, sep } from "path"; import { BUILD_TARGET_PURPOSE } from "../interfaces"; import { AssertionError } from "assert"; import { assertIsString } from "../../utils"; +import { coerce } from "semver"; async function localesForTarget( dir: string, @@ -521,3 +522,17 @@ export async function getBuildConfig(sourceDir: string, configuration: string) { ssr, }; } + +/** + * Get Angular version in the following format: `major.minor.patch`, ignoring + * canary versions as it causes issues with semver comparisons. + */ +export function getAngularVersion(cwd: string): string | undefined { + const dependency = findDependency("@angular/core", { cwd, depth: 0, omitDev: false }); + if (!dependency) return undefined; + + const angularVersionSemver = coerce(dependency.version); + if (!angularVersionSemver) return dependency.version; + + return angularVersionSemver.toString(); +} diff --git a/src/frameworks/astro/index.ts b/src/frameworks/astro/index.ts index 665504183a3..86f6aa24384 100644 --- a/src/frameworks/astro/index.ts +++ b/src/frameworks/astro/index.ts @@ -9,14 +9,17 @@ import { getAstroVersion, getBootstrapScript, getConfig } from "./utils"; export const name = "Astro"; export const support = SupportLevel.Experimental; export const type = FrameworkType.MetaFramework; +export const supportedRange = "3 || 2"; export async function discover(dir: string): Promise { if (!existsSync(join(dir, "package.json"))) return; - if (!getAstroVersion(dir)) return; + const version = getAstroVersion(dir); + if (!version) return; const { output, publicDir: publicDirectory } = await getConfig(dir); return { mayWantBackend: output !== "static", publicDirectory, + version, }; } diff --git a/src/frameworks/constants.ts b/src/frameworks/constants.ts index 5d4c8c24296..0f15339ab84 100644 --- a/src/frameworks/constants.ts +++ b/src/frameworks/constants.ts @@ -1,20 +1,51 @@ import { SupportLevel } from "./interfaces"; +import { satisfies as semverSatisfied } from "semver"; import * as clc from "colorette"; export const NPM_COMMAND_TIMEOUT_MILLIES = 10_000; export const SupportLevelWarnings = { - [SupportLevel.Experimental]: (framework: string) => `Thank you for trying our ${clc.italic( + [SupportLevel.Experimental]: ( + framework: string, + version: string | undefined, + supportedRange: string | undefined + ) => `Thank you for trying our ${clc.italic( "experimental" )} support for ${framework} on Firebase Hosting. - ${clc.yellow(`While this integration is maintained by Googlers it is not a supported Firebase product. - Issues filed on GitHub will be addressed on a best-effort basis by maintainers and other community members.`)}`, - [SupportLevel.Preview]: (framework: string) => `Thank you for trying our ${clc.italic( + ${clc.red(`While this integration is maintained by Googlers it is not a supported Firebase product. + Issues filed on GitHub will be addressed on a best-effort basis by maintainers and other community members.`)}${ + supportedRange && (!version || !semverSatisfied(version, supportedRange)) + ? clc.yellow(` + The integration is known to work against ${framework} versions ${clc.italic( + supportedRange + .split("||") + .map((it) => it.trim()) + .join(", ") + )}. You may encounter errors. + `) + : `` + }`, + [SupportLevel.Preview]: ( + framework: string, + version: string | undefined, + supportedRange: string | undefined + ) => `Thank you for trying our ${clc.italic( "early preview" )} of ${framework} support on Firebase Hosting. - ${clc.yellow( + ${clc.red( "During the preview, support is best-effort and breaking changes can be expected. Proceed with caution." - )}`, + )}${ + supportedRange && (!version || !semverSatisfied(version, supportedRange)) + ? clc.yellow(` + The integration is known to work against ${framework} versions ${clc.italic( + supportedRange + .split("||") + .map((it) => it.trim()) + .join(", ") + )}. You may encounter errors. + `) + : `` + }`, }; export const DEFAULT_DOCS_URL = diff --git a/src/frameworks/docs/nextjs.md b/src/frameworks/docs/nextjs.md index 9d75c21c930..611bf5ae818 100644 --- a/src/frameworks/docs/nextjs.md +++ b/src/frameworks/docs/nextjs.md @@ -14,7 +14,7 @@ Using the {{firebase_cli}}, you can deploy your Next.js Web apps to Firebase and serve them with {{firebase_hosting}}. The {{cli}} respects your Next.js settings and translates them to Firebase settings with zero or minimal extra configuration on your part. If your app includes dynamic server-side logic, the {{cli}} deploys that -logic to {{cloud_functions_full}}. The latest supported Next.js version is 13.4.7. +logic to {{cloud_functions_full}}. <<_includes/_preview-disclaimer.md>> diff --git a/src/frameworks/index.ts b/src/frameworks/index.ts index b25bc4f49b3..330b52ea994 100644 --- a/src/frameworks/index.ts +++ b/src/frameworks/index.ts @@ -261,11 +261,16 @@ export async function prepareFrameworks( name, support, docsUrl, + supportedRange, getValidBuildTargets = GET_DEFAULT_BUILD_TARGETS, shouldUseDevModeHandle = DEFAULT_SHOULD_USE_DEV_MODE_HANDLE, } = WebFrameworks[framework]; logger.info( - `\n${frameworksCallToAction(SupportLevelWarnings[support](name), docsUrl, " ")}\n` + `\n${frameworksCallToAction( + SupportLevelWarnings[support](name, results.version, supportedRange), + docsUrl, + " " + )}\n` ); const hostingEmulatorInfo = emulators.find((e) => e.name === Emulators.HOSTING); diff --git a/src/frameworks/interfaces.ts b/src/frameworks/interfaces.ts index 06cf7062aaf..c3a47cb4a67 100644 --- a/src/frameworks/interfaces.ts +++ b/src/frameworks/interfaces.ts @@ -23,6 +23,7 @@ export const enum SupportLevel { export interface Discovery { mayWantBackend: boolean; publicDirectory: string; + version?: string; } export interface BuildResult { @@ -53,6 +54,7 @@ export type FrameworkContext = { }; export interface Framework { + supportedRange?: string; discover: (dir: string) => Promise; type: FrameworkType; name: string; diff --git a/src/frameworks/next/index.ts b/src/frameworks/next/index.ts index 852e9329755..8b76f840cda 100644 --- a/src/frameworks/next/index.ts +++ b/src/frameworks/next/index.ts @@ -72,6 +72,8 @@ import { logger } from "../../logger"; const DEFAULT_BUILD_SCRIPT = ["next build"]; const PUBLIC_DIR = "public"; +export const supportedRange = "14.0 || 13 || 12"; + export const name = "Next.js"; export const support = SupportLevel.Preview; export const type = FrameworkType.MetaFramework; @@ -89,9 +91,10 @@ function getReactVersion(cwd: string): string | undefined { */ export async function discover(dir: string) { if (!(await pathExists(join(dir, "package.json")))) return; - if (!(await pathExists("next.config.js")) && !getNextVersion(dir)) return; + const version = getNextVersion(dir); + if (!(await pathExists("next.config.js")) && !version) return; - return { mayWantBackend: true, publicDirectory: join(dir, PUBLIC_DIR) }; + return { mayWantBackend: true, publicDirectory: join(dir, PUBLIC_DIR), version }; } /** diff --git a/src/frameworks/nuxt/index.ts b/src/frameworks/nuxt/index.ts index 8b79667f9c1..3a029c5f34e 100644 --- a/src/frameworks/nuxt/index.ts +++ b/src/frameworks/nuxt/index.ts @@ -10,6 +10,7 @@ import { getNuxtVersion } from "./utils"; export const name = "Nuxt"; export const support = SupportLevel.Experimental; export const type = FrameworkType.Toolchain; +export const supportedRange = "3"; import { nuxtConfigFilesExist } from "./utils"; import type { NuxtOptions } from "./interfaces"; @@ -27,16 +28,16 @@ export async function discover(dir: string) { const anyConfigFileExists = await nuxtConfigFilesExist(dir); - const nuxtVersion = getNuxtVersion(dir); - if (!anyConfigFileExists && !nuxtVersion) return; - if (nuxtVersion && lt(nuxtVersion, "3.0.0-0")) return; + const version = getNuxtVersion(dir); + if (!anyConfigFileExists && !version) return; + if (version && lt(version, "3.0.0-0")) return; const { dir: { public: publicDirectory }, ssr: mayWantBackend, } = await getConfig(dir); - return { publicDirectory, mayWantBackend }; + return { publicDirectory, mayWantBackend, version }; } export async function build(cwd: string) { diff --git a/src/frameworks/nuxt2/index.ts b/src/frameworks/nuxt2/index.ts index f31a99ba6d7..381ed59a59b 100644 --- a/src/frameworks/nuxt2/index.ts +++ b/src/frameworks/nuxt2/index.ts @@ -12,6 +12,7 @@ import { spawn } from "cross-spawn"; export const name = "Nuxt"; export const support = SupportLevel.Experimental; export const type = FrameworkType.MetaFramework; +export const supportedRange = "2"; async function getAndLoadNuxt(options: { rootDir: string; for: string }) { const nuxt = await relativeRequire(options.rootDir, "nuxt/dist/nuxt.js"); @@ -27,10 +28,10 @@ async function getAndLoadNuxt(options: { rootDir: string; for: string }) { */ export async function discover(rootDir: string) { if (!(await pathExists(join(rootDir, "package.json")))) return; - const nuxtVersion = getNuxtVersion(rootDir); - if (!nuxtVersion || (nuxtVersion && gte(nuxtVersion, "3.0.0-0"))) return; + const version = getNuxtVersion(rootDir); + if (!version || (version && gte(version, "3.0.0-0"))) return; const { app } = await getAndLoadNuxt({ rootDir, for: "build" }); - return { mayWantBackend: true, publicDirectory: app.options.dir.static }; + return { mayWantBackend: true, publicDirectory: app.options.dir.static, version }; } /** diff --git a/src/frameworks/sveltekit/index.ts b/src/frameworks/sveltekit/index.ts index 962a7842795..c647bc28966 100644 --- a/src/frameworks/sveltekit/index.ts +++ b/src/frameworks/sveltekit/index.ts @@ -11,6 +11,7 @@ export const name = "SvelteKit"; export const support = SupportLevel.Experimental; export const type = FrameworkType.MetaFramework; export const discover = viteDiscoverWithNpmDependency("@sveltejs/kit"); + export { getDevModeHandle } from "../vite"; export async function build(root: string) { diff --git a/src/frameworks/vite/index.ts b/src/frameworks/vite/index.ts index 3a16558c069..d6c2037cbb1 100644 --- a/src/frameworks/vite/index.ts +++ b/src/frameworks/vite/index.ts @@ -56,11 +56,16 @@ export async function discover(dir: string, plugin?: string, npmDependency?: str pathExists(join(dir, "vite.config.ts")), ]); const anyConfigFileExists = configFilesExist.some((it) => it); - if (!anyConfigFileExists && !findDependency("vite", { cwd: dir, depth, omitDev: false })) return; + const viteVersion: string = findDependency("vite", { cwd: dir, depth, omitDev: false }); + if (!anyConfigFileExists && !viteVersion) return; if (npmDependency && !additionalDep) return; const { appType, publicDir: publicDirectory, plugins } = await getConfig(dir); if (plugin && !plugins.find(({ name }) => name === plugin)) return; - return { mayWantBackend: appType !== "spa", publicDirectory }; + return { + mayWantBackend: appType !== "spa", + publicDirectory, + version: plugin ? undefined : viteVersion, + }; } export async function build(root: string) { From cfd1f9957a5f04c6c7cdae659d0a6c4b5fb3f1fd Mon Sep 17 00:00:00 2001 From: James Daniels Date: Sat, 2 Dec 2023 20:49:08 -0500 Subject: [PATCH 2/5] Simplifying ranges --- src/frameworks/angular/index.ts | 2 +- src/frameworks/astro/index.ts | 2 +- src/frameworks/constants.ts | 39 ++++-------------------------- src/frameworks/index.ts | 9 +++++-- src/frameworks/interfaces.ts | 1 + src/frameworks/next/index.ts | 2 +- src/frameworks/sveltekit/index.ts | 2 +- src/frameworks/utils.ts | 40 +++++++++++++++++++++---------- src/frameworks/vite/index.ts | 8 ++++--- 9 files changed, 49 insertions(+), 56 deletions(-) diff --git a/src/frameworks/angular/index.ts b/src/frameworks/angular/index.ts index b170e9c0b78..8945b1f3099 100644 --- a/src/frameworks/angular/index.ts +++ b/src/frameworks/angular/index.ts @@ -36,7 +36,7 @@ export const docsUrl = "https://firebase.google.com/docs/hosting/frameworks/angu const DEFAULT_BUILD_SCRIPT = ["ng build"]; -export const supportedRange = "17 || 16 || 15 || 14"; +export const supportedRange = "14 - 17"; export async function discover(dir: string): Promise { if (!(await pathExists(join(dir, "package.json")))) return; diff --git a/src/frameworks/astro/index.ts b/src/frameworks/astro/index.ts index 86f6aa24384..3f0bd4923b5 100644 --- a/src/frameworks/astro/index.ts +++ b/src/frameworks/astro/index.ts @@ -9,7 +9,7 @@ import { getAstroVersion, getBootstrapScript, getConfig } from "./utils"; export const name = "Astro"; export const support = SupportLevel.Experimental; export const type = FrameworkType.MetaFramework; -export const supportedRange = "3 || 2"; +export const supportedRange = "2 - 3"; export async function discover(dir: string): Promise { if (!existsSync(join(dir, "package.json"))) return; diff --git a/src/frameworks/constants.ts b/src/frameworks/constants.ts index 0f15339ab84..68b7d93c946 100644 --- a/src/frameworks/constants.ts +++ b/src/frameworks/constants.ts @@ -1,51 +1,20 @@ import { SupportLevel } from "./interfaces"; -import { satisfies as semverSatisfied } from "semver"; import * as clc from "colorette"; export const NPM_COMMAND_TIMEOUT_MILLIES = 10_000; export const SupportLevelWarnings = { - [SupportLevel.Experimental]: ( - framework: string, - version: string | undefined, - supportedRange: string | undefined - ) => `Thank you for trying our ${clc.italic( + [SupportLevel.Experimental]: (framework: string) => `Thank you for trying our ${clc.italic( "experimental" )} support for ${framework} on Firebase Hosting. ${clc.red(`While this integration is maintained by Googlers it is not a supported Firebase product. - Issues filed on GitHub will be addressed on a best-effort basis by maintainers and other community members.`)}${ - supportedRange && (!version || !semverSatisfied(version, supportedRange)) - ? clc.yellow(` - The integration is known to work against ${framework} versions ${clc.italic( - supportedRange - .split("||") - .map((it) => it.trim()) - .join(", ") - )}. You may encounter errors. - `) - : `` - }`, - [SupportLevel.Preview]: ( - framework: string, - version: string | undefined, - supportedRange: string | undefined - ) => `Thank you for trying our ${clc.italic( + Issues filed on GitHub will be addressed on a best-effort basis by maintainers and other community members.`)}`, + [SupportLevel.Preview]: (framework: string) => `Thank you for trying our ${clc.italic( "early preview" )} of ${framework} support on Firebase Hosting. ${clc.red( "During the preview, support is best-effort and breaking changes can be expected. Proceed with caution." - )}${ - supportedRange && (!version || !semverSatisfied(version, supportedRange)) - ? clc.yellow(` - The integration is known to work against ${framework} versions ${clc.italic( - supportedRange - .split("||") - .map((it) => it.trim()) - .join(", ") - )}. You may encounter errors. - `) - : `` - }`, + )}`, }; export const DEFAULT_DOCS_URL = diff --git a/src/frameworks/index.ts b/src/frameworks/index.ts index 330b52ea994..01b8d21f665 100644 --- a/src/frameworks/index.ts +++ b/src/frameworks/index.ts @@ -265,11 +265,16 @@ export async function prepareFrameworks( getValidBuildTargets = GET_DEFAULT_BUILD_TARGETS, shouldUseDevModeHandle = DEFAULT_SHOULD_USE_DEV_MODE_HANDLE, } = WebFrameworks[framework]; + logger.info( `\n${frameworksCallToAction( - SupportLevelWarnings[support](name, results.version, supportedRange), + SupportLevelWarnings[support](name), docsUrl, - " " + " ", + name, + results.version, + supportedRange, + results.vite )}\n` ); diff --git a/src/frameworks/interfaces.ts b/src/frameworks/interfaces.ts index c3a47cb4a67..f3825c0660a 100644 --- a/src/frameworks/interfaces.ts +++ b/src/frameworks/interfaces.ts @@ -24,6 +24,7 @@ export interface Discovery { mayWantBackend: boolean; publicDirectory: string; version?: string; + vite?: boolean; } export interface BuildResult { diff --git a/src/frameworks/next/index.ts b/src/frameworks/next/index.ts index 8b76f840cda..144d0ffb450 100644 --- a/src/frameworks/next/index.ts +++ b/src/frameworks/next/index.ts @@ -72,7 +72,7 @@ import { logger } from "../../logger"; const DEFAULT_BUILD_SCRIPT = ["next build"]; const PUBLIC_DIR = "public"; -export const supportedRange = "14.0 || 13 || 12"; +export const supportedRange = "12 - 14.0"; export const name = "Next.js"; export const support = SupportLevel.Preview; diff --git a/src/frameworks/sveltekit/index.ts b/src/frameworks/sveltekit/index.ts index c647bc28966..44c8af1c18a 100644 --- a/src/frameworks/sveltekit/index.ts +++ b/src/frameworks/sveltekit/index.ts @@ -12,7 +12,7 @@ export const support = SupportLevel.Experimental; export const type = FrameworkType.MetaFramework; export const discover = viteDiscoverWithNpmDependency("@sveltejs/kit"); -export { getDevModeHandle } from "../vite"; +export { getDevModeHandle, supportedRange } from "../vite"; export async function build(root: string) { const config = await getConfig(root); diff --git a/src/frameworks/utils.ts b/src/frameworks/utils.ts index 0aafbc845fa..a0ac6ff8dea 100644 --- a/src/frameworks/utils.ts +++ b/src/frameworks/utils.ts @@ -5,6 +5,7 @@ import { readFile } from "fs/promises"; import { IncomingMessage, request as httpRequest, ServerResponse, Agent } from "http"; import { sync as spawnSync } from "cross-spawn"; import * as clc from "colorette"; +import { satisfies as semverSatisfied } from "semver"; import { logger } from "../logger"; import { FirebaseError } from "../error"; @@ -360,21 +361,36 @@ export function relativeRequire(dir: string, mod: string) { } } -export function conjoinOptions( - opts: any[], - conjunction: string = "and", - separator: string = "," -): string | undefined { - if (!opts.length) return; - if (opts.length === 1) return opts[0].toString(); - if (opts.length === 2) return `${opts[0].toString()} ${conjunction} ${opts[1].toString()}`; - const lastElement = opts.slice(-1)[0].toString(); - const allButLast = opts.slice(0, -1).map((it) => it.toString()); +export function conjoinOptions(_opts: any[], conjunction = "and", separator = ","): string { + if (!_opts.length) return ""; + const opts: string[] = _opts.map((it) => it.toString().trim()); + if (opts.length === 1) return opts[0]; + if (opts.length === 2) return `${opts[0]} ${conjunction} ${opts[1]}`; + const lastElement = opts.slice(-1)[0]; + const allButLast = opts.slice(0, -1); return `${allButLast.join(`${separator} `)}${separator} ${conjunction} ${lastElement}`; } -export function frameworksCallToAction(message: string, docsUrl = DEFAULT_DOCS_URL, prefix = "") { - return `${prefix}${message} +export function frameworksCallToAction( + message: string, + docsUrl = DEFAULT_DOCS_URL, + prefix = "", + framework?: string, + version?: string, + supportedRange?: string, + vite = false +): string { + return `${prefix}${message}${ + framework && supportedRange && (!version || !semverSatisfied(version, supportedRange)) + ? clc.yellow( + `\n${prefix}The integration is known to work with ${ + vite ? "Vite" : framework + } version ${clc.italic( + conjoinOptions(supportedRange.split("||")) + )}. You may encounter errors.` + ) + : `` + } ${prefix}${clc.bold("Documentation:")} ${docsUrl} ${prefix}${clc.bold("File a bug:")} ${FILE_BUG_URL} diff --git a/src/frameworks/vite/index.ts b/src/frameworks/vite/index.ts index d6c2037cbb1..4229f567174 100644 --- a/src/frameworks/vite/index.ts +++ b/src/frameworks/vite/index.ts @@ -16,6 +16,7 @@ import { export const name = "Vite"; export const support = SupportLevel.Experimental; export const type = FrameworkType.Toolchain; +export const supportedRange = "3 - 5"; export const DEFAULT_BUILD_SCRIPT = ["vite build", "tsc && vite build"]; @@ -56,15 +57,16 @@ export async function discover(dir: string, plugin?: string, npmDependency?: str pathExists(join(dir, "vite.config.ts")), ]); const anyConfigFileExists = configFilesExist.some((it) => it); - const viteVersion: string = findDependency("vite", { cwd: dir, depth, omitDev: false }); - if (!anyConfigFileExists && !viteVersion) return; + const version: string | undefined = findDependency("vite", { cwd: dir, depth, omitDev: false })?.version; + if (!anyConfigFileExists && !version) return; if (npmDependency && !additionalDep) return; const { appType, publicDir: publicDirectory, plugins } = await getConfig(dir); if (plugin && !plugins.find(({ name }) => name === plugin)) return; return { mayWantBackend: appType !== "spa", publicDirectory, - version: plugin ? undefined : viteVersion, + version, + vite: true, }; } From 333be704bba42e2bde24e2ae9f60ccc4edcc1def Mon Sep 17 00:00:00 2001 From: James Daniels Date: Sat, 2 Dec 2023 21:03:33 -0500 Subject: [PATCH 3/5] Use supported range in init functions --- src/frameworks/angular/index.ts | 2 +- src/frameworks/next/index.ts | 6 +++--- src/frameworks/vite/index.ts | 17 ++++++++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/frameworks/angular/index.ts b/src/frameworks/angular/index.ts index 8945b1f3099..69158462478 100644 --- a/src/frameworks/angular/index.ts +++ b/src/frameworks/angular/index.ts @@ -47,7 +47,7 @@ export async function discover(dir: string): Promise { export function init(setup: any, config: any) { execSync( - `npx --yes -p @angular/cli@latest ng new ${setup.projectId} --directory ${setup.hosting.source} --skip-git`, + `npx --yes -p @angular/cli@"${supportedRange}" ng new ${setup.projectId} --directory ${setup.hosting.source} --skip-git`, { stdio: "inherit", cwd: config.projectDir, diff --git a/src/frameworks/next/index.ts b/src/frameworks/next/index.ts index 144d0ffb450..b389cca52f1 100644 --- a/src/frameworks/next/index.ts +++ b/src/frameworks/next/index.ts @@ -312,9 +312,9 @@ export async function init(setup: any, config: any) { choices: ["JavaScript", "TypeScript"], }); execSync( - `npx --yes create-next-app@latest -e hello-world ${setup.hosting.source} --use-npm ${ - language === "TypeScript" ? "--ts" : "--js" - }`, + `npx --yes create-next-app@"${supportedRange}" -e hello-world ${ + setup.hosting.source + } --use-npm ${language === "TypeScript" ? "--ts" : "--js"}`, { stdio: "inherit", cwd: config.projectDir } ); } diff --git a/src/frameworks/vite/index.ts b/src/frameworks/vite/index.ts index 4229f567174..78075bf9a0f 100644 --- a/src/frameworks/vite/index.ts +++ b/src/frameworks/vite/index.ts @@ -33,10 +33,13 @@ export async function init(setup: any, config: any, baseTemplate: string = "vani { name: "TypeScript", value: `${baseTemplate}-ts` }, ], }); - execSync(`npm create vite@latest ${setup.hosting.source} --yes -- --template ${template}`, { - stdio: "inherit", - cwd: config.projectDir, - }); + execSync( + `npm create vite@"${supportedRange}" ${setup.hosting.source} --yes -- --template ${template}`, + { + stdio: "inherit", + cwd: config.projectDir, + } + ); execSync(`npm install`, { stdio: "inherit", cwd: join(config.projectDir, setup.hosting.source) }); } @@ -57,7 +60,11 @@ export async function discover(dir: string, plugin?: string, npmDependency?: str pathExists(join(dir, "vite.config.ts")), ]); const anyConfigFileExists = configFilesExist.some((it) => it); - const version: string | undefined = findDependency("vite", { cwd: dir, depth, omitDev: false })?.version; + const version: string | undefined = findDependency("vite", { + cwd: dir, + depth, + omitDev: false, + })?.version; if (!anyConfigFileExists && !version) return; if (npmDependency && !additionalDep) return; const { appType, publicDir: publicDirectory, plugins } = await getConfig(dir); From fea89fb1b8de4f72fe68af5e4f1d3c70f818bc8e Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 7 Dec 2023 10:35:00 -0500 Subject: [PATCH 4/5] Tests --- src/test/frameworks/angular/index.spec.ts | 1 + src/test/frameworks/astro/index.spec.ts | 2 ++ src/test/frameworks/nuxt/index.spec.ts | 2 ++ src/test/frameworks/utils.spec.ts | 4 ++-- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/frameworks/angular/index.spec.ts b/src/test/frameworks/angular/index.spec.ts index 2a29539ea23..20721ce619a 100644 --- a/src/test/frameworks/angular/index.spec.ts +++ b/src/test/frameworks/angular/index.spec.ts @@ -23,6 +23,7 @@ describe("Angular", () => { expect(await discover(cwd)).to.deep.equal({ mayWantBackend: true, publicDirectory: join(cwd, "src", "assets"), + version: undefined, }); }); }); diff --git a/src/test/frameworks/astro/index.spec.ts b/src/test/frameworks/astro/index.spec.ts index 7682b4b9404..6f1d42a7d19 100644 --- a/src/test/frameworks/astro/index.spec.ts +++ b/src/test/frameworks/astro/index.spec.ts @@ -54,6 +54,7 @@ describe("Astro", () => { expect(await discover(cwd)).to.deep.equal({ mayWantBackend: false, publicDirectory: publicDir, + version: "2.2.2", }); }); @@ -84,6 +85,7 @@ describe("Astro", () => { expect(await discover(cwd)).to.deep.equal({ mayWantBackend: true, publicDirectory: publicDir, + version: "2.2.2", }); }); }); diff --git a/src/test/frameworks/nuxt/index.spec.ts b/src/test/frameworks/nuxt/index.spec.ts index d2a5e9f70b7..2ffabcf6a17 100644 --- a/src/test/frameworks/nuxt/index.spec.ts +++ b/src/test/frameworks/nuxt/index.spec.ts @@ -45,6 +45,7 @@ describe("Nuxt 2 utils", () => { expect(await discoverNuxt2(discoverNuxtDir)).to.deep.equal({ mayWantBackend: true, publicDirectory: "static", + version: "2.15.8", }); }); @@ -75,6 +76,7 @@ describe("Nuxt 2 utils", () => { expect(await discoverNuxt3(discoverNuxtDir)).to.deep.equal({ mayWantBackend: true, publicDirectory: "public", + version: "3.0.0", }); }); }); diff --git a/src/test/frameworks/utils.spec.ts b/src/test/frameworks/utils.spec.ts index 55c99df27c5..28882c44e01 100644 --- a/src/test/frameworks/utils.spec.ts +++ b/src/test/frameworks/utils.spec.ts @@ -102,8 +102,8 @@ describe("Frameworks utils", () => { const defaultSeparator = ","; const defaultConjunction = "and"; - it("should return undefined if there's no options", () => { - expect(conjoinOptions([])).to.be.undefined; + it("should return empty string if there's no options", () => { + expect(conjoinOptions([])).to.be.eql(""); }); it("should return option if there's only one", () => { From 4acd7420b99648f69ff0d7c63b0f8f10f8464802 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 7 Dec 2023 10:38:00 -0500 Subject: [PATCH 5/5] Add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c76768396c9..68edae115db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,3 @@ - Fixed an issue preventing Angular apps using ng-deploy from being emulated or deployed. (#6584) +- Warn if a Web Framework is outside a well known version range on deploy/emulate. (#6562) +- Use Web Framework's well known version range in `firebase init hosting`. (#6562)