Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions packages/@apphosting/adapter-angular/src/bin/build.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { OutputBundleOptions } from "../interface.js";
describe("build commands", () => {
let tmpDir: string;
let outputBundleOptions: OutputBundleOptions;
let defaultAngularVersion: string;
beforeEach(() => {
tmpDir = generateTmpDir();
outputBundleOptions = {
Expand All @@ -20,16 +21,18 @@ describe("build commands", () => {
serverFilePath: resolve(tmpDir, ".apphosting", "dist", "server", "server.mjs"),
needsServerGenerated: false,
};
defaultAngularVersion = "17.3.8";
});

it("expects all output bundle files to be generated", async () => {
const { generateOutputDirectory, validateOutputDirectory } = await importUtils;
const { generateOutputDirectory, validateOutputDirectory, createMetadata } = await importUtils;
const files = {
"dist/test/browser/browserfile": "",
"dist/test/server/server.mjs": "",
};
const packageVersion = createMetadata(defaultAngularVersion).adapterVersion;
generateTestFiles(tmpDir, files);
await generateOutputDirectory(tmpDir, outputBundleOptions);
await generateOutputDirectory(tmpDir, outputBundleOptions, defaultAngularVersion);
await validateOutputDirectory(outputBundleOptions);

const expectedFiles = {
Expand All @@ -42,6 +45,11 @@ neededDirs:
staticAssets:
- .apphosting/dist/browser
env: []
metadata:
adapterPackageName: "@apphosting/adapter-angular"
adapterVersion: ${packageVersion}
framework: angular
frameworkVersion: 17.3.8
`,
};
validateTestFiles(tmpDir, expectedFiles);
Expand All @@ -56,22 +64,12 @@ env: []
generateTestFiles(tmpDir, files);
await generateOutputDirectory(tmpDir, outputBundleOptions, "17.3.2");

const expectedFiles = {
".apphosting/dist/browser/browserfile": "",
".apphosting/dist/server/server.mjs": "",
".apphosting/bundle.yaml": `
runCommand: node .apphosting/dist/server/server.mjs
neededDirs:
- .apphosting
staticAssets:
- .apphosting/dist/browser
env:
const expectedContents = `env:
- variable: SSR_PORT
value: "8080"
availability: RUNTIME
`,
};
validateTestFiles(tmpDir, expectedFiles);
`;
validateFileExistsAndContains(tmpDir, ".apphosting/bundle.yaml", expectedContents);
});

it("test failed validateOutputDirectory", async () => {
Expand All @@ -81,7 +79,7 @@ env:
"dist/test/server/notserver.mjs": "",
};
generateTestFiles(tmpDir, files);
await generateOutputDirectory(tmpDir, outputBundleOptions);
await generateOutputDirectory(tmpDir, outputBundleOptions, defaultAngularVersion);
assert.rejects(async () => await validateOutputDirectory(outputBundleOptions));
});

Expand Down Expand Up @@ -134,3 +132,17 @@ function validateTestFiles(baseDir: string, expectedFiles: Object): void {
assert.deepEqual(ignoreBlankLines(contents), ignoreBlankLines(expectedContents));
});
}

function validateFileExistsAndContains(
baseDir: string,
expectedFileName: string,
expectedContents: string,
): void {
const fileToRead = path.join(baseDir, expectedFileName);
assert.ok(fs.existsSync(fileToRead), `File '${fileToRead}' does not exist.`);
const contents = fs.readFileSync(fileToRead).toString();
assert.ok(
contents.includes(expectedContents),
`Actual contents do not contain expected contents.\nExpected contained contents:\n${expectedContents}\nActual:\n${contents}`,
);
}
3 changes: 3 additions & 0 deletions packages/@apphosting/adapter-angular/src/bin/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const opts = getBuildOptions();

// Check build conditions, which vary depending on your project structure (standalone or monorepo)
await checkBuildConditions(opts);
if (!process.env.FRAMEWORK_VERSION) {
throw new Error("Could not find the angular version of the application");
}

// enable JSON build logs for application builder
process.env.NG_BUILD_LOGS_JSON = "1";
Expand Down
8 changes: 8 additions & 0 deletions packages/@apphosting/adapter-angular/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ export enum Availability {
Runtime = "RUNTIME",
}

// Metadata schema for bundle.yaml outputted by angular adapter
export interface Metadata {
adapterPackageName: string;
adapterVersion: string;
framework: string;
frameworkVersion: string;
}

// valid manifest schema
export interface ValidManifest {
errors: string[];
Expand Down
32 changes: 25 additions & 7 deletions packages/@apphosting/adapter-angular/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { stringify as yamlStringify } from "yaml";
import {
Availability,
EnvironmentVariable,
Metadata,
OutputBundleOptions,
OutputPaths,
buildManifestSchema,
Expand All @@ -17,7 +18,7 @@ import stripAnsi from "strip-ansi";
import { BuildOptions } from "@apphosting/common";

// fs-extra is CJS, readJson can't be imported using shorthand
export const { writeFile, move, readJson, mkdir, copyFile } = fsExtra;
export const { writeFile, move, readJson, mkdir, copyFile, readFileSync, existsSync } = fsExtra;

const require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -142,14 +143,31 @@ function extractManifestOutput(output: string): string {
return stripAnsi(output.substring(start, end + 1));
}

/**
* Create metadata needed for outputting adapter and framework metrics in bundle.yaml.
*/
export function createMetadata(angularVersion: string): Metadata {
const packageJsonPath = `${__dirname}/../package.json`;
if (!existsSync(packageJsonPath)) {
throw new Error(`Angular adapter package.json file does not exist at ${packageJsonPath}`);
}
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
return {
adapterPackageName: packageJson.name,
adapterVersion: packageJson.version,
framework: "angular",
frameworkVersion: angularVersion,
};
}

/**
* Move the base output directory, which contains the server and browser bundle directory, and prerendered routes
* as well as generating bundle.yaml.
*/
export async function generateOutputDirectory(
cwd: string,
outputBundleOptions: OutputBundleOptions,
angularVersion?: string,
angularVersion: string,
): Promise<void> {
await move(outputBundleOptions.baseDirectory, outputBundleOptions.outputBaseDirectory, {
overwrite: true,
Expand All @@ -161,10 +179,10 @@ export async function generateOutputDirectory(
}

// add environment variable to bundle.yaml if needed for specific versions
function addBundleYamlEnvVar(angularVersion?: string): EnvironmentVariable[] {
function generateEnvVars(angularVersion: string): EnvironmentVariable[] {
const runtimeEnvVars: EnvironmentVariable[] = [];
// add env var to solve angular port issue, existing only for Angular v17.3.2 (b/332896115)
if (angularVersion && angularVersion === "17.3.2") {
if (angularVersion === "17.3.2") {
const ssrPortEnvVar: EnvironmentVariable = {
variable: "SSR_PORT",
value: "8080",
Expand All @@ -179,16 +197,16 @@ function addBundleYamlEnvVar(angularVersion?: string): EnvironmentVariable[] {
async function generateBundleYaml(
outputBundleOptions: OutputBundleOptions,
cwd: string,
angularVersion?: string,
angularVersion: string,
): Promise<void> {
const runtimeEnvVars = addBundleYamlEnvVar(angularVersion);
await writeFile(
outputBundleOptions.bundleYamlPath,
yamlStringify({
runCommand: `node ${normalize(relative(cwd, outputBundleOptions.serverFilePath))}`,
neededDirs: [normalize(relative(cwd, outputBundleOptions.outputDirectory))],
staticAssets: [normalize(relative(cwd, outputBundleOptions.browserDirectory))],
env: runtimeEnvVars,
env: generateEnvVars(angularVersion),
metadata: createMetadata(angularVersion),
}),
);
}
Expand Down
Loading