Skip to content

Commit 502614a

Browse files
bboysokolleoortizz
andauthored
support for different angular builders (#8256)
* Added handling for different angular builders * Remove unused method from angular * Review changes, tests and cleaning * Removing empty jsdocs * Fixing tests * Update src/frameworks/angular/utils.ts --------- Co-authored-by: Leonardo Ortiz <leo@monogram.io>
1 parent a06ac1f commit 502614a

2 files changed

Lines changed: 97 additions & 99 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { getBuilderType, BuilderType } from "./utils";
2+
import { expect } from "chai";
3+
4+
describe("getBuilderType", () => {
5+
it("should return the correct builder type for valid builders", () => {
6+
expect(getBuilderType("@angular-devkit/build-angular:browser")).to.equal(BuilderType.BROWSER);
7+
expect(getBuilderType("@angular-devkit/build-angular:server")).to.equal(BuilderType.SERVER);
8+
expect(getBuilderType("@angular-devkit/build-angular:dev-server")).to.equal(
9+
BuilderType.DEV_SERVER,
10+
);
11+
expect(getBuilderType("@angular-devkit/build-angular:ssr-dev-server")).to.equal(
12+
BuilderType.SSR_DEV_SERVER,
13+
);
14+
expect(getBuilderType("@angular-devkit/build-angular:prerender")).to.equal(
15+
BuilderType.PRERENDER,
16+
);
17+
expect(getBuilderType("@angular-devkit/build-angular:application")).to.equal(
18+
BuilderType.APPLICATION,
19+
);
20+
expect(getBuilderType("@angular-devkit/build-angular:browser-esbuild")).to.equal(
21+
BuilderType.BROWSER_ESBUILD,
22+
);
23+
expect(getBuilderType("@angular-devkit/build-angular:deploy")).to.equal(BuilderType.DEPLOY);
24+
});
25+
26+
it("should return null for invalid builders", () => {
27+
expect(getBuilderType("@angular-devkit/build-angular:invalid")).to.be.null;
28+
expect(getBuilderType("invalid")).to.be.null;
29+
expect(getBuilderType(":")).to.be.null;
30+
expect(getBuilderType("::")).to.be.null;
31+
expect(getBuilderType("random:string")).to.be.null;
32+
});
33+
34+
it("should handle builders with no colon", () => {
35+
expect(getBuilderType("@angular-devkit/build-angular")).to.be.null;
36+
});
37+
});

src/frameworks/angular/utils.ts

Lines changed: 60 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -66,55 +66,32 @@ async function localesForTarget(
6666
return { locales, defaultLocale };
6767
}
6868

69-
const enum ExpectedBuilder {
70-
APPLICATION = "@angular-devkit/build-angular:application",
71-
BROWSER_ESBUILD = "@angular-devkit/build-angular:browser-esbuild",
72-
DEPLOY = "@angular/fire:deploy",
73-
DEV_SERVER = "@angular-devkit/build-angular:dev-server",
74-
LEGACY_BROWSER = "@angular-devkit/build-angular:browser",
75-
LEGACY_NGUNIVERSAL_PRERENDER = "@nguniversal/builders:prerender",
76-
LEGACY_DEVKIT_PRERENDER = "@angular-devkit/build-angular:prerender",
77-
LEGACY_SERVER = "@angular-devkit/build-angular:server",
78-
LEGACY_NGUNIVERSAL_SSR_DEV_SERVER = "@nguniversal/builders:ssr-dev-server",
79-
LEGACY_DEVKIT_SSR_DEV_SERVER = "@angular-devkit/build-angular:ssr-dev-server",
69+
export enum BuilderType {
70+
DEPLOY = "deploy",
71+
DEV_SERVER = "dev-server",
72+
SSR_DEV_SERVER = "ssr-dev-server",
73+
SERVER = "server",
74+
BROWSER = "browser",
75+
BROWSER_ESBUILD = "browser-esbuild",
76+
APPLICATION = "application",
77+
PRERENDER = "prerender",
8078
}
8179

82-
const enum ThirdPartyBuilder {
83-
CUSTOM_WEBPACK_DEV_SERVER = "@angular-builders/custom-webpack:dev-server",
84-
CUSTOM_WEBPACK_SERVER = "@angular-builders/custom-webpack:server",
85-
CUSTOM_WEBPACK_BROWSER = "@angular-builders/custom-webpack:browser",
86-
NGX_ENV_APPLICATION = "@ngx-env/builder:application",
87-
NGX_ENV_DEV_SERVER = "@ngx-env/builder:dev-server",
88-
}
89-
90-
const DEV_SERVER_TARGETS: string[] = [
91-
ExpectedBuilder.DEV_SERVER,
92-
ExpectedBuilder.LEGACY_NGUNIVERSAL_SSR_DEV_SERVER,
93-
ExpectedBuilder.LEGACY_DEVKIT_SSR_DEV_SERVER,
94-
ThirdPartyBuilder.CUSTOM_WEBPACK_DEV_SERVER,
95-
ThirdPartyBuilder.CUSTOM_WEBPACK_SERVER,
96-
ThirdPartyBuilder.NGX_ENV_DEV_SERVER,
97-
];
80+
const DEV_SERVER_TARGETS: BuilderType[] = [BuilderType.DEV_SERVER, BuilderType.SSR_DEV_SERVER];
9881

99-
function getValidBuilders(purpose: BUILD_TARGET_PURPOSE): string[] {
82+
function getValidBuilderTypes(purpose: BUILD_TARGET_PURPOSE): BuilderType[] {
10083
return [
101-
ExpectedBuilder.APPLICATION,
102-
ExpectedBuilder.BROWSER_ESBUILD,
103-
ExpectedBuilder.DEPLOY,
104-
ExpectedBuilder.LEGACY_BROWSER,
105-
ExpectedBuilder.LEGACY_DEVKIT_PRERENDER,
106-
ExpectedBuilder.LEGACY_NGUNIVERSAL_PRERENDER,
84+
BuilderType.APPLICATION,
85+
BuilderType.BROWSER_ESBUILD,
86+
BuilderType.DEPLOY,
87+
BuilderType.BROWSER,
88+
BuilderType.PRERENDER,
10789
...(purpose === "deploy" ? [] : DEV_SERVER_TARGETS),
10890
];
10991
}
11092

111-
function getValidThirdPartyBuilders(): string[] {
112-
return [ThirdPartyBuilder.CUSTOM_WEBPACK_BROWSER, ThirdPartyBuilder.NGX_ENV_APPLICATION];
113-
}
114-
11593
export async function getAllTargets(purpose: BUILD_TARGET_PURPOSE, dir: string) {
116-
const validBuilders = getValidBuilders(purpose);
117-
const validThirdPartyBuilders = getValidThirdPartyBuilders();
94+
const validBuilderTypes = getValidBuilderTypes(purpose);
11895
const [{ NodeJsAsyncHost }, { workspaces }, { targetStringFromTarget }] = await Promise.all([
11996
relativeRequire(dir, "@angular-devkit/core/node"),
12097
relativeRequire(dir, "@angular-devkit/core"),
@@ -127,15 +104,9 @@ export async function getAllTargets(purpose: BUILD_TARGET_PURPOSE, dir: string)
127104
workspace.projects.forEach((projectDefinition, project) => {
128105
if (projectDefinition.extensions.projectType !== "application") return;
129106
projectDefinition.targets.forEach((targetDefinition, target) => {
130-
if (
131-
!validBuilders.includes(targetDefinition.builder) &&
132-
!validThirdPartyBuilders.includes(targetDefinition.builder)
133-
) {
107+
const builderType = getBuilderType(targetDefinition.builder);
108+
if (builderType && !validBuilderTypes.includes(builderType)) {
134109
return;
135-
} else if (validThirdPartyBuilders.includes(targetDefinition.builder)) {
136-
console.warn(
137-
"You are using an unofficial Angular builder, in case of unexpected behavior please file a bug at https://github.com/firebase/firebase-tools/issues.",
138-
);
139110
}
140111
const configurations = Object.keys(targetDefinition.configurations || {});
141112
if (!configurations.includes("production")) configurations.push("production");
@@ -212,39 +183,32 @@ export async function getContext(dir: string, targetOrConfiguration?: string) {
212183

213184
if (overrideTarget) {
214185
const target = workspaceProject.targets.get(overrideTarget.target)!;
215-
const builder = target.builder;
216-
switch (builder) {
217-
case ExpectedBuilder.DEPLOY:
186+
const builderType = getBuilderType(target.builder);
187+
switch (builderType) {
188+
case BuilderType.DEPLOY:
218189
deployTarget = overrideTarget;
219190
break;
220-
case ExpectedBuilder.APPLICATION:
221-
case ThirdPartyBuilder.NGX_ENV_APPLICATION:
191+
case BuilderType.APPLICATION:
222192
buildTarget = overrideTarget;
223193
break;
224-
case ExpectedBuilder.BROWSER_ESBUILD:
225-
case ExpectedBuilder.LEGACY_BROWSER:
226-
case ThirdPartyBuilder.CUSTOM_WEBPACK_BROWSER:
194+
case BuilderType.BROWSER:
195+
case BuilderType.BROWSER_ESBUILD:
227196
browserTarget = overrideTarget;
228197
break;
229-
case ExpectedBuilder.LEGACY_DEVKIT_PRERENDER:
230-
case ExpectedBuilder.LEGACY_NGUNIVERSAL_PRERENDER:
198+
case BuilderType.PRERENDER:
231199
prerenderTarget = overrideTarget;
232200
break;
233-
case ExpectedBuilder.DEV_SERVER:
234-
case ExpectedBuilder.LEGACY_NGUNIVERSAL_SSR_DEV_SERVER:
235-
case ExpectedBuilder.LEGACY_DEVKIT_SSR_DEV_SERVER:
236-
case ThirdPartyBuilder.CUSTOM_WEBPACK_DEV_SERVER:
237-
case ThirdPartyBuilder.CUSTOM_WEBPACK_SERVER:
238-
case ThirdPartyBuilder.NGX_ENV_DEV_SERVER:
201+
case BuilderType.DEV_SERVER:
202+
case BuilderType.SSR_DEV_SERVER:
239203
serveTarget = overrideTarget;
240204
break;
241205
default:
242-
throw new FirebaseError(`builder ${builder} not known.`);
206+
throw new FirebaseError(`builder type ${builderType} not known.`);
243207
}
244208
} else if (workspaceProject.targets.has("deploy")) {
245209
const { builder, defaultConfiguration = "production" } =
246210
workspaceProject.targets.get("deploy")!;
247-
if (builder === ExpectedBuilder.DEPLOY) {
211+
if (getBuilderType(builder) === BuilderType.DEPLOY) {
248212
deployTarget = {
249213
project,
250214
target: "deploy",
@@ -324,15 +288,13 @@ export async function getContext(dir: string, targetOrConfiguration?: string) {
324288
if (!buildTarget && !browserTarget && workspaceProject.targets.has("build")) {
325289
const { builder, defaultConfiguration = "production" } =
326290
workspaceProject.targets.get("build")!;
291+
const builderType = getBuilderType(builder);
327292
const target = {
328293
project,
329294
target: "build",
330295
configuration: configuration || defaultConfiguration,
331296
};
332-
if (
333-
builder === ExpectedBuilder.LEGACY_BROWSER ||
334-
builder === ExpectedBuilder.BROWSER_ESBUILD
335-
) {
297+
if (builderType === BuilderType.BROWSER || builderType === BuilderType.BROWSER_ESBUILD) {
336298
browserTarget = target;
337299
} else {
338300
buildTarget = target;
@@ -383,30 +345,19 @@ export async function getContext(dir: string, targetOrConfiguration?: string) {
383345
const definition = workspaceProject.targets.get(target.target);
384346
if (!definition) throw new FirebaseError(`${target} could not be found in your angular.json`);
385347
const { builder } = definition;
386-
if (target === deployTarget && builder === ExpectedBuilder.DEPLOY) continue;
387-
if (target === buildTarget && builder === ExpectedBuilder.APPLICATION) continue;
388-
if (target === buildTarget && builder === ExpectedBuilder.LEGACY_BROWSER) continue;
389-
if (target === buildTarget && builder === ThirdPartyBuilder.CUSTOM_WEBPACK_BROWSER) continue;
390-
if (target === buildTarget && builder === ThirdPartyBuilder.NGX_ENV_APPLICATION) continue;
391-
if (target === browserTarget && builder === ExpectedBuilder.BROWSER_ESBUILD) continue;
392-
if (target === browserTarget && builder === ThirdPartyBuilder.CUSTOM_WEBPACK_BROWSER)
393-
continue;
394-
if (target === browserTarget && builder === ThirdPartyBuilder.NGX_ENV_APPLICATION) continue;
395-
if (target === browserTarget && builder === ExpectedBuilder.LEGACY_BROWSER) continue;
396-
if (target === prerenderTarget && builder === ExpectedBuilder.LEGACY_DEVKIT_PRERENDER)
397-
continue;
398-
if (target === prerenderTarget && builder === ExpectedBuilder.LEGACY_NGUNIVERSAL_PRERENDER)
399-
continue;
400-
if (target === serverTarget && builder === ExpectedBuilder.LEGACY_SERVER) continue;
401-
if (target === serveTarget && builder === ExpectedBuilder.LEGACY_NGUNIVERSAL_SSR_DEV_SERVER)
402-
continue;
403-
if (target === serveTarget && builder === ExpectedBuilder.LEGACY_DEVKIT_SSR_DEV_SERVER)
404-
continue;
405-
if (target === serveTarget && builder === ExpectedBuilder.DEV_SERVER) continue;
406-
if (target === serveTarget && builder === ThirdPartyBuilder.CUSTOM_WEBPACK_DEV_SERVER)
407-
continue;
408-
if (target === serveTarget && builder === ThirdPartyBuilder.CUSTOM_WEBPACK_SERVER) continue;
409-
if (target === serveTarget && builder === ThirdPartyBuilder.NGX_ENV_DEV_SERVER) continue;
348+
const builderType = getBuilderType(builder);
349+
if (target === deployTarget && builderType === BuilderType.DEPLOY) continue;
350+
if (target === buildTarget && builderType === BuilderType.APPLICATION) continue;
351+
if (target === buildTarget && builderType === BuilderType.BROWSER) continue;
352+
if (target === browserTarget && builderType === BuilderType.BROWSER_ESBUILD) continue;
353+
if (target === browserTarget && builderType === BuilderType.BROWSER) continue;
354+
if (target === browserTarget && builderType === BuilderType.APPLICATION) continue;
355+
if (target === prerenderTarget && builderType === BuilderType.PRERENDER) continue;
356+
if (target === prerenderTarget && builderType === BuilderType.PRERENDER) continue;
357+
if (target === serverTarget && builderType === BuilderType.SERVER) continue;
358+
if (target === serveTarget && builderType === BuilderType.SSR_DEV_SERVER) continue;
359+
if (target === serveTarget && builderType === BuilderType.DEV_SERVER) continue;
360+
if (target === serveTarget && builderType === BuilderType.SERVER) continue;
410361
throw new FirebaseError(
411362
`${definition.builder} (${targetString}) is not a recognized builder. Please check your angular.json`,
412363
);
@@ -464,11 +415,7 @@ export async function getBrowserConfig(sourceDir: string, configuration: string)
464415

465416
const outputPath = join(
466417
targetOptions.outputPath,
467-
buildTarget &&
468-
(builderName === ExpectedBuilder.APPLICATION ||
469-
builderName === ThirdPartyBuilder.NGX_ENV_APPLICATION)
470-
? "browser"
471-
: "",
418+
buildTarget && getBuilderType(builderName) === BuilderType.APPLICATION ? "browser" : "",
472419
);
473420
return { locales, baseHref, outputPath, defaultLocale };
474421
}
@@ -623,3 +570,17 @@ function throwCannotDetermineTarget(error?: Error): never {
623570
{ original: error },
624571
);
625572
}
573+
574+
/**
575+
* Extracts the builder type from a full builder string (everything after the colon)
576+
* @example
577+
* getBuilderType("@angular-devkit/build-angular:browser") // returns "browser"
578+
*/
579+
export function getBuilderType(builder: string): BuilderType | null {
580+
const colonIndex = builder.lastIndexOf(":");
581+
const builderType = colonIndex >= 0 ? builder.slice(colonIndex + 1) : undefined;
582+
if (!builderType || !Object.values(BuilderType).includes(builderType as BuilderType)) {
583+
return null;
584+
}
585+
return builderType as BuilderType;
586+
}

0 commit comments

Comments
 (0)