Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: throw an error when server.ts calls run function #6977

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -0,0 +1 @@
- (Angular 17+) throw an error when server.ts calls `run` function (#6651)
49 changes: 49 additions & 0 deletions src/frameworks/angular/utils.ts
Expand Up @@ -11,7 +11,46 @@
import { assertIsString } from "../../utils";
import { coerce } from "semver";

/**
* @param serverFilePath path to server.ts
* @return true when `run` function is called in server.ts, it breaks SSR (Angular 17+) on Firebase.
*/
const isRunImplementedAndCalledInServer = async (serverFilePath: string): Promise<boolean> => {
// Dynamically import the TypeScript compiler module
const ts = await import("typescript");
const sourceCode = ts.sys.readFile(serverFilePath);
const functionName = "run";

if (!sourceCode) {
return false;
}

const sourceFile = ts.createSourceFile("server.ts", sourceCode, ts.ScriptTarget.Latest, true);

let isRunDefined = false;
let isRunCalled = false;

// Recursive function to traverse the AST
const traverse = (node: any): void => {

Check warning on line 34 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
if (ts.isFunctionDeclaration(node) && node.name && node.name.getText() === functionName) {

Check warning on line 35 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe argument of type `any` assigned to a parameter of type `Node`
isRunDefined = true;
}
if (
ts.isCallExpression(node) &&

Check warning on line 39 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe argument of type `any` assigned to a parameter of type `Node`
ts.isIdentifier(node.expression) &&
node.expression.getText() === functionName
) {
isRunCalled = true;
}
ts.forEachChild(node, traverse);

Check warning on line 45 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe argument of type `any` assigned to a parameter of type `Node`
};

traverse(sourceFile);

return isRunDefined && isRunCalled;
};

async function localesForTarget(

Check warning on line 53 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing return type on function
dir: string,
architectHost: WorkspaceNodeModulesArchitectHost,
target: Target,
Expand All @@ -27,7 +66,7 @@
let locales: string[] | undefined = undefined;
let defaultLocale: string | undefined = undefined;
if (targetOptions.localize) {
const i18n: AngularI18nConfig | undefined = workspaceProject.extensions?.i18n as any;

Check warning on line 69 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unsafe assignment of an `any` value

Check warning on line 69 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unexpected any. Specify a different type
if (!i18n) throw new FirebaseError(`No i18n config on project.`);
if (typeof i18n.sourceLocale === "string") {
throw new FirebaseError(`All your i18n locales must have a baseHref of "" on Firebase, use an object for sourceLocale in your angular.json:
Expand All @@ -49,7 +88,7 @@
for (const [locale, { baseHref }] of Object.entries(i18n.locales)) {
if (baseHref !== "")
throw new FirebaseError(
`All your i18n locales must have a baseHref of \"\" on Firebase, errored on ${locale}.`,

Check warning on line 91 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unnecessary escape character: \"

Check warning on line 91 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Unnecessary escape character: \"
);
locales.push(locale);
}
Expand Down Expand Up @@ -96,7 +135,7 @@
];
}

export async function getAllTargets(purpose: BUILD_TARGET_PURPOSE, dir: string) {

Check warning on line 138 in src/frameworks/angular/utils.ts

View workflow job for this annotation

GitHub Actions / lint (20)

Missing return type on function
const validBuilders = getValidBuilders(purpose);
const [{ NodeJsAsyncHost }, { workspaces }, { targetStringFromTarget }] = await Promise.all([
relativeRequire(dir, "@angular-devkit/core/node"),
Expand Down Expand Up @@ -482,6 +521,16 @@
);
}
const serverEntry = buildTarget ? "server.mjs" : serverTarget && "main.js";

if (
serverEntry === "server.mjs" &&
(await isRunImplementedAndCalledInServer(join(sourceDir, "server.ts")))
) {
throw new FirebaseError(
"For SSR to work properly, please remove the `run` function call from the `server.ts` file.",
);
}

const externalDependencies: string[] = (serverTargetOptions.externalDependencies as any) || [];
const bundleDependencies = serverTargetOptions.bundleDependencies ?? true;
const { locales: browserLocales } = await localesForTarget(
Expand Down