Skip to content

Commit 29bfd76

Browse files
authored
Merge branch 'main' into feature/nextjs-ecommerce
2 parents 09167ea + 121558a commit 29bfd76

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+7977
-4480
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
- name: Build
4444
run: npm run build
4545
- name: "Upload Artifact"
46-
uses: actions/upload-artifact@v3
46+
uses: actions/upload-artifact@v4
4747
with:
4848
path: |
4949
packages/*/dist/
@@ -89,7 +89,7 @@ jobs:
8989
path: ~/.cache/firebase/emulators
9090
key: firebase_emulators
9191
- name: Download Artifacts
92-
uses: actions/download-artifact@v3
92+
uses: actions/download-artifact@v4
9393
- name: Rsync Artifacts
9494
run: rsync -a artifact/ packages
9595
- name: Test
@@ -146,7 +146,7 @@ jobs:
146146
check-latest: false
147147
registry-url: "https://registry.npmjs.org"
148148
- name: "Download Artifacts"
149-
uses: actions/download-artifact@v3
149+
uses: actions/download-artifact@v4
150150
- name: Rsync Artifacts
151151
run: rsync -a artifact/ packages
152152
- name: Publish

CODEOWNERS

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Global reviewers
22
# TODO add group for global reviewers
3-
* @jamesdaniels @leoortizz @Yuangwang @tonyjhuang
3+
* @jamesdaniels @leoortizz @Yuangwang @annajowang
44

55
# App Hosting Platform Adapters code
66
# TODO add group for App Hosting
7-
/packages/@apphosting/adapter-*/ @Yuangwang @sjjj986 @jamesdaniels @tonyjhuang @blidd-google @taeold
8-
/packages/@apphosting/common/ @Yuangwang @sjjj986 @jamesdaniels @tonyjhuang @blidd-google @taeold
7+
/packages/@apphosting/adapter-*/ @Yuangwang @sjjj986 @jamesdaniels @annajowang @blidd-google @taeold
8+
/packages/@apphosting/common/ @Yuangwang @sjjj986 @jamesdaniels @annajowang @blidd-google @taeold
99

1010
# Web Frameworks code
1111
/packages/@apphosting/build/ @FirebaseExtended/firebase-full-time-employees @FirebaseExtended/monogram

README.md

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Any framework that can generate a build output in accordance with the App Hostin
1818
The output bundle primarily consists of a `bundle.yaml` file that sits inside of the `.apphosting` directory. This bundle.yaml contains all the ways that frameworks can configure App Hosting when users deploy their applications.
1919

2020
> [!NOTE]
21-
> App Hosting technically supports all all node applications, but no custom framework features will be enabled without the output bundle.
21+
> App Hosting technically supports all node applications, but no custom framework features will be enabled without the output bundle.
2222
2323
## Output bundle Schema
2424

@@ -37,6 +37,7 @@ interface OutputBundle {
3737
version: "v1"
3838
runConfig: RunConfig;
3939
metadata: Metadata;
40+
outputFiles?: OutputFiles;
4041
}
4142
```
4243

@@ -108,16 +109,44 @@ interface Metadata {
108109
| `framework` | `string` | Name of the framework that is being supported | y |
109110
| `frameworkVersion` | `string` |Version of the framework that is being supported | n |
110111

111-
Here is a sample `bundle.yaml` file putting all this together:
112+
### OutputFiles
113+
114+
OutputFiles is an optional field to configure outputFiles and optimize server files + static assets.
115+
116+
```typescript
117+
interface OutputFiles {
118+
serverApp: ServerApp
119+
}
112120

113121
```
114-
> cat .apphosting/bundle.yaml
115122

123+
| Field | Type | Description | Required? |
124+
| ---------- | ------- | - | - |
125+
| `serverApp` | `ServerApp` | ServerApp holds configurations related to the serving files at runtime from Cloud Run | y |
126+
127+
### ServerApp
128+
129+
OutputFiles is an optional field to configure outputFiles and optimize server files + static assets.
130+
131+
```typescript
132+
interface ServerApp {
133+
include: string[]
134+
}
135+
136+
```
137+
138+
| Field | Type | Description | Required? |
139+
| ---------- | ------- | - | - |
140+
| `include` | `string[]` | include holds a list of directories + files relative to the app root dir that frameworks need to deploy to the App Hosting server, generally this will be the output/dist directory (e.g. .output or dist). In the case that the framework wants to include all files they can use [“.”] | y |
141+
142+
## Sample
143+
144+
Here is a sample `.apphosting/bundle.yaml` file putting all this together:
145+
146+
```yaml
116147
version: v1
117148
runConfig:
118-
runCommand:
119-
- node
120-
- dist/index.js
149+
runCommand: node dist/index.js
121150
environmentVariables:
122151
- variable: VAR
123152
value: 8080
@@ -127,13 +156,18 @@ runConfig:
127156
memoryMiB: 512
128157
minInstances: 0
129158
maxInstances: 14
159+
160+
outputFiles:
161+
serverApp:
162+
include:
163+
- dist
164+
- .output
130165

131166
metadata:
132-
adapterNpmPackageName: npm-name
167+
adapterPackageName: npm-name
133168
adapterVersion: 12.0.0
134-
frameworkNpmPackageName: framework-name
135-
adapterVersion: 1.0.0
136-
169+
framework: framework-name
170+
frameworkVersion: 1.0.0
137171
```
138172
139173
As long as you have the `bundle.yaml` in this format, App Hosting will be able to deploy any framework that supports server side rendering.

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@apphosting/adapter-angular/e2e/run-local.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import { parse as parseYaml } from "yaml";
66
import { spawn } from "child_process";
77
import fsExtra from "fs-extra";
88

9-
const { readFileSync, mkdirp, readJSON, writeJSON, rmdir } = fsExtra;
9+
const { readFileSync, mkdirp, readJSON, writeJSON, rm } = fsExtra;
1010
const __dirname = dirname(fileURLToPath(import.meta.url));
1111

1212
const starterTemplateDir = "../../../starters/angular/basic";
1313

1414
const errors: any[] = [];
1515

16-
await rmdir(join(__dirname, "runs"), { recursive: true }).catch(() => undefined);
16+
await rm(join(__dirname, "runs"), { recursive: true }).catch(() => undefined);
1717

1818
console.log("\nBuilding and starting test projects in parallel...");
1919

@@ -41,7 +41,15 @@ const tests = await Promise.all(
4141
stdio: "inherit",
4242
shell: true,
4343
});
44-
44+
if (parseInt(process.versions.node.split(".")[0]) > 18) {
45+
console.log(`[${runId}] updating angular to next tag`);
46+
console.log(`[${runId}] > npx ng update @angular/cli@next @angular/core@next`);
47+
await promiseSpawn("npx", ["ng", "update", "@angular/cli@next", "@angular/core@next"], {
48+
cwd,
49+
stdio: "inherit",
50+
shell: true,
51+
});
52+
}
4553
const angularJSON = JSON.parse((await readFile(join(cwd, "angular.json"))).toString());
4654

4755
if (!enableSSR) {

packages/@apphosting/adapter-angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apphosting/adapter-angular",
3-
"version": "17.2.12",
3+
"version": "17.2.13",
44
"main": "dist/index.js",
55
"description": "Experimental addon to the Firebase CLI to add web framework support",
66
"repository": {

packages/@apphosting/adapter-angular/src/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ export function populateOutputBundleOptions(outputPaths: OutputPaths): OutputBun
108108

109109
export function parseOutputBundleOptions(buildOutput: string): OutputBundleOptions {
110110
const strippedManifest = extractManifestOutput(buildOutput);
111-
const parsedManifest = JSON.parse(strippedManifest) as string;
111+
// TODO: add functional tests that test this flow
112+
const parsedManifest = JSON.parse(strippedManifest.replace(/[\r\n]+/g, "")) as string;
112113
const manifest = buildManifestSchema.parse(parsedManifest);
113114
if (manifest["errors"].length > 0) {
114115
// errors when extracting manifest

packages/@apphosting/adapter-nextjs/e2e/app.spec.ts

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
11
import * as assert from "assert";
22
import { posix } from "path";
3+
import fsExtra from "fs-extra";
34

45
export const host = process.env.HOST;
5-
66
if (!host) {
77
throw new Error("HOST environment variable expected");
88
}
99

10+
let adapterVersion: string;
11+
before(() => {
12+
const packageJson = fsExtra.readJSONSync("package.json");
13+
adapterVersion = packageJson.version;
14+
if (!adapterVersion) throw new Error("couldn't parse package.json version");
15+
});
16+
1017
describe("app", () => {
1118
it("/", async () => {
1219
const response = await fetch(host);
1320
assert.ok(response.ok);
1421
assert.equal(response.headers.get("content-type")?.toLowerCase(), "text/html; charset=utf-8");
15-
assert.equal(
16-
response.headers.get("cache-control"),
17-
"s-maxage=31536000, stale-while-revalidate",
18-
);
22+
assert.equal(response.headers.get("cache-control"), "s-maxage=31536000, ");
1923
});
2024

2125
it("/ssg", async () => {
2226
const response = await fetch(posix.join(host, "ssg"));
2327
assert.ok(response.ok);
2428
assert.equal(response.headers.get("content-type")?.toLowerCase(), "text/html; charset=utf-8");
25-
assert.equal(
26-
response.headers.get("cache-control"),
27-
"s-maxage=31536000, stale-while-revalidate",
28-
);
29+
assert.equal(response.headers.get("cache-control"), "s-maxage=31536000, ");
2930
const text = await response.text();
3031
assert.ok(text.includes("SSG"));
3132
assert.ok(text.includes("Generated"));
@@ -80,10 +81,7 @@ describe("app", () => {
8081
const response = await fetch(posix.join(host, "isr", "demand"));
8182
assert.ok(response.ok);
8283
assert.equal(response.headers.get("content-type")?.toLowerCase(), "text/html; charset=utf-8");
83-
assert.equal(
84-
response.headers.get("cache-control"),
85-
"s-maxage=31536000, stale-while-revalidate",
86-
);
84+
assert.equal(response.headers.get("cache-control"), "s-maxage=31536000, ");
8785
const text = await response.text();
8886
assert.ok(text.includes("A cached page"));
8987
assert.ok(text.includes("Generated"));
@@ -123,4 +121,30 @@ describe("app", () => {
123121
"private, no-cache, no-store, max-age=0, must-revalidate",
124122
);
125123
});
124+
125+
it("should have x-fah-adapter header and no x-fah-middleware header on all routes", async () => {
126+
const routes = [
127+
"/",
128+
"/ssg",
129+
"/ssr",
130+
"/ssr/streaming",
131+
"/isr/time",
132+
"/isr/demand",
133+
"/nonexistent-route",
134+
];
135+
136+
for (const route of routes) {
137+
const response = await fetch(posix.join(host, route));
138+
assert.equal(
139+
response.headers.get("x-fah-adapter"),
140+
`nextjs-${adapterVersion}`,
141+
`Route ${route} missing x-fah-adapter header`,
142+
);
143+
assert.equal(
144+
response.headers.get("x-fah-middleware"),
145+
null,
146+
`Route ${route} should not have x-fah-middleware header`,
147+
);
148+
}
149+
});
126150
});

0 commit comments

Comments
 (0)