Skip to content

Commit dbda308

Browse files
committed
Cleaning up the ng-add command a bit
1 parent 3a4854d commit dbda308

File tree

4 files changed

+104
-109
lines changed

4 files changed

+104
-109
lines changed

src/schematics/ng-add-ssr.ts

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { SchematicsException, Tree, SchematicContext } from '@angular-devkit/schematics';
1+
import { SchematicsException, Tree, SchematicContext, noop } from '@angular-devkit/schematics';
22
import {
33
addDependencies,
4+
DeployOptions,
45
generateFirebaseRc,
56
NgAddNormalizedOptions,
67
overwriteIfExists,
78
safeReadJSON,
89
stringifyFormatted
910
} from './ng-add-common';
1011
import { FirebaseJSON, Workspace, WorkspaceProject } from './interfaces';
11-
12-
import { default as defaultDependencies, firebaseFunctions as firebaseFunctionsDependencies } from './versions.json';
12+
import { getProject, projectTypePrompt } from './utils';
13+
import { firebaseFunctions as firebaseFunctionsDependencies } from './versions.json';
1314
import { dirname, join } from 'path';
15+
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
1416

1517
// We consider a project to be a universal project if it has a `server` architect
1618
// target. If it does, it knows how to build the application's server.
@@ -96,12 +98,23 @@ export function generateFirebaseJson(
9698
overwriteIfExists(tree, path, stringifyFormatted(firebaseJson));
9799
}
98100

99-
export const addFirebaseFunctionsDependencies = (tree: Tree, context: SchematicContext) => {
100-
addDependencies(
101-
tree,
102-
firebaseFunctionsDependencies,
103-
context
104-
);
101+
export const addFirebaseFunctionsDependencies = (options: DeployOptions) => (tree: Tree, context: SchematicContext) => {
102+
const {project} = getProject(options, tree);
103+
projectTypePrompt(project).then(({universalProject}) => {
104+
if (universalProject) {
105+
(global as any).setupAsAngularUniversalApp = true;
106+
addDependencies(
107+
tree,
108+
firebaseFunctionsDependencies,
109+
context
110+
);
111+
context.addTask(new NodePackageInstallTask());
112+
return tree;
113+
} else {
114+
(global as any).setupAsAngularUniversalApp = false;
115+
return noop();
116+
}
117+
});
105118
};
106119

107120
export const setupUniversalDeployment = (config: {

src/schematics/ng-add-static.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { FirebaseJSON, Workspace, WorkspaceProject } from './interfaces';
1111

1212
import { default as defaultDependencies } from './versions.json';
13+
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
1314

1415
function emptyFirebaseJson() {
1516
return {
@@ -72,12 +73,14 @@ export function generateFirebaseJson(
7273
overwriteIfExists(tree, path, stringifyFormatted(firebaseJson));
7374
}
7475

75-
export const addFirebaseHostingDependencies = (tree: Tree, context: SchematicContext) => {
76+
export const addFirebaseHostingDependencies = () => async (tree: Tree, context: SchematicContext) => {
7677
addDependencies(
7778
tree,
7879
defaultDependencies,
7980
context
8081
);
82+
context.addTask(new NodePackageInstallTask());
83+
return tree;
8184
};
8285

8386
export const setupStaticDeployment = (config: {

src/schematics/ng-add.ts

+20-97
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,11 @@
1-
import { SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
2-
import { NodePackageInstallTask, RunSchematicTask } from '@angular-devkit/schematics/tasks';
3-
import { listProjects, projectPrompt, projectTypePrompt } from './utils';
4-
import { Workspace } from './interfaces';
1+
import { chain, Tree } from '@angular-devkit/schematics';
2+
import { listProjects, projectPrompt, getWorkspace, getProject } from './utils';
53
import { DeployOptions, NgAddNormalizedOptions } from './ng-add-common';
64
import { addFirebaseFunctionsDependencies, setupUniversalDeployment } from './ng-add-ssr';
75
import { addFirebaseHostingDependencies, setupStaticDeployment } from './ng-add-static';
86

9-
function getWorkspace(
10-
host: Tree
11-
): { path: string; workspace: Workspace } {
12-
const possibleFiles = ['/angular.json', '/.angular.json'];
13-
const path = possibleFiles.filter(p => host.exists(p))[0];
14-
15-
const configBuffer = host.read(path);
16-
if (configBuffer === null) {
17-
throw new SchematicsException(`Could not find angular.json`);
18-
}
19-
20-
// We can not depend on this library to have be included in older (or newer) Angular versions.
21-
// Require here, since the schematic will add it to the package.json and install it before
22-
// continuing.
23-
const { parse }: typeof import('jsonc-parser') = require('jsonc-parser');
24-
25-
const workspace = parse(configBuffer.toString()) as Workspace|undefined;
26-
if (!workspace) {
27-
throw new SchematicsException('Could not parse angular.json');
28-
}
29-
30-
return {
31-
path,
32-
workspace
33-
};
34-
}
35-
36-
const getProject = (options: DeployOptions, host: Tree) => {
37-
const { workspace } = getWorkspace(host);
38-
const projectName = options.project || workspace.defaultProject;
39-
40-
if (!projectName) {
41-
throw new SchematicsException(
42-
'No Angular project selected and no default project in the workspace'
43-
);
44-
}
45-
46-
const project = workspace.projects[projectName];
47-
if (!project) {
48-
throw new SchematicsException(
49-
'The specified Angular project is not defined in this workspace'
50-
);
51-
}
52-
53-
if (project.projectType !== 'application') {
54-
throw new SchematicsException(
55-
`Deploy requires an Angular project type of "application" in angular.json`
56-
);
57-
}
58-
59-
return {project, projectName};
60-
};
61-
627
export const setupProject =
63-
(host: Tree, options: DeployOptions & { isUniversalProject: boolean, firebaseProject: string }) => {
8+
(host: Tree, options: DeployOptions & { firebaseProject: string, isUniversalProject: boolean }) => {
649
const { path: workspacePath, workspace } = getWorkspace(host);
6510

6611
const {project, projectName} = getProject(options, host);
@@ -78,50 +23,28 @@ export const setupProject =
7823
tree: host,
7924
project
8025
});
26+
} else {
27+
return setupStaticDeployment({
28+
workspace,
29+
workspacePath,
30+
options: config,
31+
tree: host,
32+
project
33+
});
8134
}
82-
return setupStaticDeployment({
83-
workspace,
84-
workspacePath,
85-
options: config,
86-
tree: host,
87-
project
88-
});
89-
};
35+
};
9036

9137
export const ngAddSetupProject = (
92-
options: DeployOptions & { isUniversalProject: boolean }
38+
options: DeployOptions
9339
) => async (host: Tree) => {
9440
const projects = await listProjects();
9541
const { firebaseProject } = await projectPrompt(projects);
96-
return setupProject(host, {...options, firebaseProject});
42+
const isUniversalProject = (global as any).setupAsAngularUniversalApp;
43+
return setupProject(host, {...options, firebaseProject, isUniversalProject });
9744
};
9845

99-
export const ngAdd = (options: DeployOptions) => (
100-
host: Tree,
101-
context: SchematicContext
102-
) => {
103-
104-
addFirebaseHostingDependencies(host, context);
105-
106-
const {project} = getProject(options, host);
107-
108-
// In Angular 12 it appears I might need some sort of timeout to allow
109-
// node_modules to resolve?
110-
const timeout = new Promise(resolve => setTimeout(resolve, 1_000));
111-
112-
return timeout.
113-
then(() => projectTypePrompt(project)).
114-
then(({ universalProject }: { universalProject: boolean }) => {
115-
if (universalProject) {
116-
addFirebaseFunctionsDependencies(host, context);
117-
}
118-
const projectOptions: DeployOptions & { isUniversalProject: boolean } = {
119-
...options,
120-
isUniversalProject: universalProject
121-
};
122-
context.addTask(new RunSchematicTask('ng-add-setup-project', projectOptions), [
123-
context.addTask(new NodePackageInstallTask())
124-
]);
125-
}
126-
);
127-
};
46+
export const ngAdd = (options: DeployOptions) => chain([
47+
addFirebaseHostingDependencies(),
48+
addFirebaseFunctionsDependencies(options),
49+
ngAddSetupProject(options),
50+
]);

src/schematics/utils.ts

+58-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { readFileSync } from 'fs';
2-
import { FirebaseRc, Project, WorkspaceProject } from './interfaces';
2+
import { FirebaseRc, Project, Workspace, WorkspaceProject } from './interfaces';
33
import { join } from 'path';
44
import { isUniversalApp } from './ng-add-ssr';
5+
import { SchematicsException, Tree } from '@angular-devkit/schematics';
6+
import { DeployOptions } from './ng-add-common';
57

68
export async function listProjects() {
79
const firebase = require('firebase-tools');
@@ -41,6 +43,60 @@ const searchProjects = (projects: Project[]) => {
4143
};
4244
};
4345

46+
47+
export function getWorkspace(
48+
host: Tree
49+
): { path: string; workspace: Workspace } {
50+
const possibleFiles = ['/angular.json', '/.angular.json'];
51+
const path = possibleFiles.filter(p => host.exists(p))[0];
52+
53+
const configBuffer = host.read(path);
54+
if (configBuffer === null) {
55+
throw new SchematicsException(`Could not find angular.json`);
56+
}
57+
58+
// We can not depend on this library to have be included in older (or newer) Angular versions.
59+
// Require here, since the schematic will add it to the package.json and install it before
60+
// continuing.
61+
const { parse }: typeof import('jsonc-parser') = require('jsonc-parser');
62+
63+
const workspace = parse(configBuffer.toString()) as Workspace|undefined;
64+
if (!workspace) {
65+
throw new SchematicsException('Could not parse angular.json');
66+
}
67+
68+
return {
69+
path,
70+
workspace
71+
};
72+
}
73+
74+
export const getProject = (options: DeployOptions, host: Tree) => {
75+
const { workspace } = getWorkspace(host);
76+
const projectName = options.project || workspace.defaultProject;
77+
78+
if (!projectName) {
79+
throw new SchematicsException(
80+
'No Angular project selected and no default project in the workspace'
81+
);
82+
}
83+
84+
const project = workspace.projects[projectName];
85+
if (!project) {
86+
throw new SchematicsException(
87+
'The specified Angular project is not defined in this workspace'
88+
);
89+
}
90+
91+
if (project.projectType !== 'application') {
92+
throw new SchematicsException(
93+
`Deploy requires an Angular project type of "application" in angular.json`
94+
);
95+
}
96+
97+
return {project, projectName};
98+
};
99+
44100
export const projectPrompt = (projects: Project[]) => {
45101
const inquirer = require('inquirer');
46102
inquirer.registerPrompt(
@@ -55,7 +111,7 @@ export const projectPrompt = (projects: Project[]) => {
55111
});
56112
};
57113

58-
export const projectTypePrompt = (project: WorkspaceProject) => {
114+
export const projectTypePrompt = (project: WorkspaceProject): Promise<{ universalProject: boolean }> => {
59115
if (isUniversalApp(project)) {
60116
return require('inquirer').prompt({
61117
type: 'confirm',

0 commit comments

Comments
 (0)