Skip to content

Commit

Permalink
No more hosting init option, warn about deprecation
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesdaniels committed May 14, 2024
1 parent 76d8560 commit d2b2562
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 346 deletions.
40 changes: 1 addition & 39 deletions src/schematics/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import * as semver from 'semver';
import { FirebaseHostingSite, FirebaseRc } from './interfaces';
import { FirebaseHostingSite } from './interfaces';

export const shortSiteName = (site?: FirebaseHostingSite) => site?.name?.split('/').pop();

Expand All @@ -18,44 +18,6 @@ export const overwriteIfExists = (
}
};

function emptyFirebaseRc() {
return {
targets: {}
};
}

function generateFirebaseRcTarget(firebaseProject: string, firebaseHostingSite: FirebaseHostingSite|undefined, project: string) {
return {
hosting: {
[project]: [
shortSiteName(firebaseHostingSite) ?? firebaseProject
]
}
};
}

export function generateFirebaseRc(
tree: Tree,
path: string,
firebaseProject: string,
firebaseHostingSite: FirebaseHostingSite|undefined,
project: string
) {
const firebaseRc: FirebaseRc = tree.exists(path)
? safeReadJSON(path, tree)
: emptyFirebaseRc();

firebaseRc.targets = firebaseRc.targets || {};
firebaseRc.targets[firebaseProject] = generateFirebaseRcTarget(
firebaseProject,
firebaseHostingSite,
project
);
firebaseRc.projects = { default: firebaseProject };

overwriteIfExists(tree, path, stringifyFormatted(firebaseRc));
}

export function safeReadJSON(path: string, tree: Tree) {
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Expand Down
10 changes: 9 additions & 1 deletion src/schematics/deploy/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ export default async function deploy(
options: DeployBuilderOptions,
firebaseToken?: string,
) {
const legacyNgDeploy = !options.version || options.version < 2;

if (!firebaseToken && !process.env.GOOGLE_APPLICATION_CREDENTIALS) {
await firebaseTools.login();
const user = await firebaseTools.login({ projectRoot: context.workspaceRoot });
Expand All @@ -401,6 +403,12 @@ export default async function deploy(
console.log(`Using Google Application Credentials.`);
}

if (legacyNgDeploy) {
console.error(`Legacy ng-deploy Firebase is deprecated.
Please migrate to Firebase Hosting's integration with Angular https://firebase.google.com/docs/hosting/frameworks/angular
or the new Firebase App Hosting product https://firebase.google.com/docs/app-hosting`);
}

if (prerenderBuildTarget) {
const run = await context.scheduleTarget(
targetFromTargetString(prerenderBuildTarget.name),
Expand Down Expand Up @@ -465,7 +473,7 @@ export default async function deploy(

firebaseTools.logger.logger.add(logger);

if ((!options.version || options.version < 2) && serverBuildTarget) {
if (legacyNgDeploy && serverBuildTarget) {
if (options.ssr === 'cloud-run') {
await deployToCloudRun(
firebaseTools,
Expand Down
11 changes: 0 additions & 11 deletions src/schematics/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { RuntimeOptions } from 'firebase-functions';

export const enum FEATURES {
Hosting,
Authentication,
Analytics,
AppCheck,
Expand All @@ -16,7 +15,6 @@ export const enum FEATURES {
}

export const featureOptions = [
{ name: 'ng deploy -- Hosting', value: FEATURES.Hosting },
{ name: 'Authentication', value: FEATURES.Authentication },
{ name: 'Google Analytics', value: FEATURES.Analytics },
{ name: 'App Check', value: FEATURES.AppCheck },
Expand Down Expand Up @@ -154,15 +152,6 @@ export interface FirebaseJSON {
functions?: FirebaseFunctionsConfig;
}

export interface FirebaseRcTarget {
hosting: Record<string, string[]>;
}

export interface FirebaseRc {
targets?: Record<string, FirebaseRcTarget>;
projects?: Record<string, string>;
}

export interface DeployBuilderSchema {
buildTarget?: string;
browserTarget?: string;
Expand Down
141 changes: 9 additions & 132 deletions src/schematics/setup/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
import { writeFileSync } from 'fs';
import { join } from 'path';
import { asWindowsPath, normalize } from '@angular-devkit/core';
import { SchematicContext, SchematicsException, Tree, chain } from '@angular-devkit/schematics';
import { SchematicContext, Tree, chain } from '@angular-devkit/schematics';
import { addRootProvider } from '@schematics/angular/utility';
import {
generateFirebaseRc,
overwriteIfExists,
safeReadJSON,
stringifyFormatted
} from '../common';
import { getFirebaseTools } from '../firebaseTools';
import {
DeployOptions, FEATURES, FirebaseApp, FirebaseHostingSite, FirebaseProject,
NgAddNormalizedOptions
} from '../interfaces';
import { FirebaseJSON, Workspace, WorkspaceProject } from '../interfaces';
import {
addIgnoreFiles,
featureToRules,
getFirebaseProjectNameFromHost, getProject, getWorkspace
getFirebaseProjectNameFromHost,
getProject,
} from '../utils';
import { appPrompt, featuresPrompt, projectPrompt, projectTypePrompt, sitePrompt, userPrompt } from './prompts';
import { appPrompt, featuresPrompt, projectPrompt, userPrompt } from './prompts';

export interface SetupConfig extends DeployOptions {
firebaseProject: FirebaseProject,
Expand All @@ -39,30 +32,7 @@ export const setupProject =

addIgnoreFiles(tree);

if (features.includes(FEATURES.Hosting)) {
const { path: workspacePath, workspace } = getWorkspace(tree);
const { project, projectName } = getProject(config, tree);
setupFirebase({
workspace,
workspacePath,
options: {
project: projectName,
firebaseProject: config.firebaseProject,
firebaseApp: config.firebaseApp,
firebaseHostingSite: config.firebaseHostingSite,
sdkConfig: config.sdkConfig,
buildTarget: config.buildTarget,
serveTarget: config.serveTarget,
ssrRegion: config.ssrRegion,
},
tree,
context,
project
});
}

const featuresToImport = features.filter(it => it !== FEATURES.Hosting);
if (featuresToImport.length > 0) {
if (features.length) {
return chain([
addRootProvider(projectName, ({code, external}) => {
external('initializeApp', '@angular/fire/app');
Expand Down Expand Up @@ -96,120 +66,27 @@ export const ngAddSetupProject = (
await firebaseTools.login.use(user.email, { projectRoot });
}

const { project: ngProject, projectName: ngProjectName } = getProject(options, host);
const { projectName: ngProjectName } = getProject(options, host);

const [ defaultProjectName ] = getFirebaseProjectNameFromHost(host, ngProjectName);

const firebaseProject = await projectPrompt(defaultProjectName, { projectRoot, account: user.email });

let hosting = { };
let firebaseHostingSite: FirebaseHostingSite|undefined;

if (features.includes(FEATURES.Hosting)) {
// TODO read existing settings from angular.json, if available
const results = await projectTypePrompt(ngProject, ngProjectName);
hosting = { ...hosting, ...results };
firebaseHostingSite = await sitePrompt(firebaseProject, { projectRoot });
}



let firebaseApp: FirebaseApp|undefined;
let sdkConfig: Record<string, string>|undefined;

if (features.find(it => it !== FEATURES.Hosting)) {
if (features.length) {

const defaultAppId = firebaseHostingSite?.appId;
firebaseApp = await appPrompt(firebaseProject, defaultAppId, { projectRoot });
firebaseApp = await appPrompt(firebaseProject, undefined, { projectRoot });

const result = await firebaseTools.apps.sdkconfig('web', firebaseApp.appId, { nonInteractive: true, projectRoot });
sdkConfig = result.sdkConfig;

}

return setupProject(host, context, features, {
...options, ...hosting, firebaseProject, firebaseApp, firebaseHostingSite, sdkConfig,
...options, firebaseProject, firebaseApp, sdkConfig,
});

}
};

export function generateFirebaseJson(
tree: Tree,
path: string,
project: string,
region: string|undefined,
) {
const firebaseJson: FirebaseJSON = tree.exists(path)
? safeReadJSON(path, tree)
: {};

const newConfig = {
target: project,
source: '.',
frameworksBackend: {
region
}
};
if (firebaseJson.hosting === undefined) {
firebaseJson.hosting = [newConfig];
} else if (Array.isArray(firebaseJson.hosting)) {
const existingConfigIndex = firebaseJson.hosting.findIndex(config => config.target === newConfig.target);
if (existingConfigIndex > -1) {
firebaseJson.hosting.splice(existingConfigIndex, 1, newConfig);
} else {
firebaseJson.hosting.push(newConfig);
}
} else {
firebaseJson.hosting = [firebaseJson.hosting, newConfig];
}

overwriteIfExists(tree, path, stringifyFormatted(firebaseJson));
}

export const setupFirebase = (config: {
project: WorkspaceProject;
options: NgAddNormalizedOptions;
workspacePath: string;
workspace: Workspace;
tree: Tree;
context: SchematicContext;
}) => {
const { tree, workspacePath, workspace, options } = config;
const project = workspace.projects[options.project];

if (!project.architect) {
throw new SchematicsException(`Angular project "${options.project}" has a malformed angular.json`);
}

project.architect.deploy = {
builder: '@angular/fire:deploy',
options: {
version: 2,
},
configurations: {
production: {
buildTarget: options.buildTarget?.[0],
serveTarget: options.serveTarget?.[0],
},
development: {
buildTarget: options.buildTarget?.[1],
serveTarget: options.serveTarget?.[1],
}
},
defaultConfiguration: 'production',
};

tree.overwrite(workspacePath, JSON.stringify(workspace, null, 2));

generateFirebaseJson(tree, 'firebase.json', options.project, options.ssrRegion);
generateFirebaseRc(
tree,
'.firebaserc',
options.firebaseProject.projectId,
options.firebaseHostingSite,
options.project
);

return tree;
};
Loading

0 comments on commit d2b2562

Please sign in to comment.