11import * as clc from "colorette" ;
22import { join } from "path" ;
33import { Client } from "../../../apiv2" ;
4- import { discover , WebFrameworks } from "../../../frameworks" ;
4+ import { discover } from "../../../frameworks" ;
55import * as github from "./github" ;
66import { confirm , input } from "../../../prompt" ;
77import { logger } from "../../../logger" ;
@@ -10,16 +10,17 @@ import { Options } from "../../../options";
1010import { logSuccess } from "../../../utils" ;
1111import { pickHostingSiteName } from "../../../hosting/interactive" ;
1212import { readTemplateSync } from "../../../templates" ;
13- import { FirebaseError } from "../../../error" ;
1413import { Setup } from "../.." ;
1514import { Config } from "../../../config" ;
1615import { createSite } from "../../../hosting/api" ;
16+ import { FirebaseError } from "../../../error" ;
1717
1818const INDEX_TEMPLATE = readTemplateSync ( "init/hosting/index.html" ) ;
1919const MISSING_TEMPLATE = readTemplateSync ( "init/hosting/404.html" ) ;
2020const DEFAULT_IGNORES = [ "firebase.json" , "**/.*" , "**/node_modules/**" ] ;
2121
2222export interface RequiredInfo {
23+ redirectToAppHosting ?: boolean ;
2324 newSiteId ?: string ;
2425 public ?: string ;
2526 spa ?: boolean ;
@@ -28,12 +29,23 @@ export interface RequiredInfo {
2829// TODO: come up with a better way to type this
2930// eslint-disable-next-line @typescript-eslint/no-explicit-any
3031export async function askQuestions ( setup : Setup , config : Config , options : Options ) : Promise < void > {
32+ // Detect frameworks first, before asking any hosting questions
33+ const discoveredFramework = await discover ( config . projectDir , false ) ;
34+ if ( discoveredFramework && discoveredFramework . mayWantBackend ) {
35+ const frameworkName = discoveredFramework . framework ;
36+ logger . info ( ) ;
37+ logger . info (
38+ `Detected a ${ frameworkName } codebase. Setting up ${ clc . bold ( "App Hosting" ) } instead.` ,
39+ ) ;
40+ setup . featureInfo ||= { } ;
41+ setup . featureInfo . hosting = { redirectToAppHosting : true } ;
42+ setup . features ?. unshift ( "apphosting" ) ;
43+ return ;
44+ }
45+
3146 setup . featureInfo = setup . featureInfo || { } ;
3247 setup . featureInfo . hosting = { } ;
3348
34- // Fire off framework detection concurrently so it runs while the site check happens
35- const discoverPromise = discover ( config . projectDir , false ) ;
36-
3749 // There's a path where we can set up Hosting without a project, so if
3850 // if setup.projectId is empty, we don't do any checking for a Hosting site.
3951 if ( setup . projectId ) {
@@ -62,15 +74,6 @@ export async function askQuestions(setup: Setup, config: Config, options: Option
6274 }
6375 }
6476
65- const discoveredFramework = await discoverPromise ;
66- if ( discoveredFramework && discoveredFramework . mayWantBackend ) {
67- const frameworkName =
68- WebFrameworks [ discoveredFramework . framework ] ?. name ?? discoveredFramework . framework ;
69- throw new FirebaseError (
70- `Detected a ${ frameworkName } codebase. Use ${ clc . bold ( "firebase init apphosting" ) } instead.` ,
71- ) ;
72- }
73-
7477 logger . info ( ) ;
7578 logger . info (
7679 `Your ${ clc . bold ( "public" ) } directory is the folder (relative to your project directory) that` ,
@@ -106,6 +109,11 @@ export async function actuate(setup: Setup, config: Config, options: Options): P
106109 ) ;
107110 }
108111
112+ // if the user was redirected to App Hosting, we don't need to do anything here
113+ if ( hostingInfo . redirectToAppHosting ) {
114+ return ;
115+ }
116+
109117 if ( hostingInfo . newSiteId && setup . projectId ) {
110118 await createSite ( setup . projectId , hostingInfo . newSiteId ) ;
111119 logger . info ( ) ;
0 commit comments