Skip to content

Commit c1959ce

Browse files
Update getting started experience (#320)
* checkpoint * Post emulators-init * Update gitignore again * Fix typo * Add step for deploying * Fix malformed yaml * Update firebase.json --------- Co-authored-by: James Daniels <[email protected]>
1 parent 29bfd76 commit c1959ce

File tree

10 files changed

+261
-388
lines changed

10 files changed

+261
-388
lines changed

starters/nextjs/firebase-ecommerce/.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,9 @@ vsce-debug.log*
4040
# Firebase
4141
firebase-debug.log*
4242
firebase-debug.*
43-
.firebase
43+
.firebase
44+
.firebaserc
45+
46+
# dataconnect
47+
dataconnect-generated/
48+
dataconnect/.dataconnect/

starters/nextjs/firebase-ecommerce/README.md

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,18 @@ The application provides a quick and easy to use shopping experience with featur
2828

2929
1. Create a new Firebase project in the [Firebase Console](https://console.firebase.google.com).
3030
2. Enable **Email/Password Authentication**.
31-
3. Add Firebase app secrets to `.env.local`.
32-
4. Include Firebase app secrets in **App Hosting**.
31+
3. Replace the relevant commented-out environment variables in `apphosting.yaml`
32+
with your firebase config.
3333

3434
#### Firebase Data Connect
3535

3636
1. Install the **Firebase Data Connect** extension for VS Code.
3737
2. Create a new Data Connect instance and service.
3838
3. Set up billing for the Firebase project.
3939
4. Switch to the Blaze plan.
40-
5. Define the required schema, queries, and mutations.
40+
5. Modify `dataconnect/dataconnect.yaml` to specify `serviceId`, `location`,
41+
`schema.datasource.postgresql.database` and
42+
`schema.datasource.postgressql.cloudSql.instanceId`
4143
6. Deploy the schema, queries, and mutations to production.
4244

4345
#### Firebase Storage
@@ -48,13 +50,18 @@ The application provides a quick and easy to use shopping experience with featur
4850
#### Firebase App Hosting
4951

5052
1. Connect the Firebase app to your GitHub repository.
51-
2. Create a new backend for the application.
52-
3. Deploy secrets to app hosting using the Firebase CLI.
53-
4. Deploy the application to Firebase Hosting.
53+
2. Create a new backend for the application, but do not deploy yet.
54+
We need to set up environment variables first for the app to work.
5455

5556
### Stripe Setup
5657

5758
1. Create a new Stripe account.
59+
2. Follow the instructions in apphosting.yaml to create the
60+
public and private keys for your stripe application.
61+
3. Create a webhook that listen to "Events on your account" at
62+
<your domain>/api/stripe/webhook that receives at least
63+
the following events: `payment_intent.succeeded`, `payment_intent.failed`,
64+
`charge.succeeded`, `charge.updated`.
5865
2. Add API keys (Publishable and Secret) to `.env.local`.
5966
3. Set up a webhook endpoint in the Firebase project.
6067
4. Add the webhook secret to `.env.local`.
@@ -63,12 +70,18 @@ The application provides a quick and easy to use shopping experience with featur
6370

6471
## Environment Variables
6572

66-
The following environment variables must be configured in `.env.local`:
73+
The following environment variables must be configured in `apphosting.yaml`
74+
(there are comments for where to find these values)
6775

68-
- **Firebase Secrets**: `NEXT_PUBLIC_FIREBASE_API_KEY`, `NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN`, `NEXT_PUBLIC_FIREBASE_PROJECT_ID`, `NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET`, `NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID`, `NEXT_PUBLIC_FIREBASE_APP_ID`.
69-
- **Stripe Secrets**: `NEXT_PUBLIC_STRIPE_PUB_KEY`, `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`
76+
- **Firebase Config**: `NEXT_PUBLIC_FIREBASE_API_KEY`, `NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN`, `NEXT_PUBLIC_FIREBASE_PROJECT_ID`, `NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET`, `NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID`, `NEXT_PUBLIC_FIREBASE_APP_ID`.
77+
- **Stripe Config**: `NEXT_PUBLIC_STRIPE_PUB_KEY`, `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`
7078
- **Google/Gemini API Key**: `GOOGLE_API_KEY`
7179

80+
## Deploy
81+
Once you have set up Stripe, Data Connect, and configured your App Hosting environment, it's time to deploy!
82+
If you have automatic rollouts enabled, simply push your changes. Otherwise, after pushing, go to the
83+
Firebase console and click "Create Rollout".
84+
7285
## Application Features
7386

7487
### Homepage
@@ -148,18 +161,17 @@ To run this project locally, follow these steps:
148161
```
149162
npm install
150163
```
151-
4. Copy the example environment variables:
152-
```
153-
cp .env.example .env.local
154-
```
155-
• Fill in the required values (Firebase config, Stripe keys, Google API key, etc.).
156-
5. Start the development server:
164+
4. Fill in `apphosting.yaml` as guided by the comments.
165+
5. Initialize the firebase emulator suite with `firebase init emulators`. You may
166+
create an `apphosting.emulator.yaml` if you choose to use different configurations
167+
during local development or you can test against your production config.
168+
5. Start the emulator
157169
```
158-
npm run dev
170+
firebase emulators:start
159171
```
160172
6. Open the application in your browser at:
161173
```
162-
http://localhost:3000
174+
http://localhost:5002
163175
```
164176

165177
---

starters/nextjs/firebase-ecommerce/apphosting.yaml

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,46 @@ runConfig:
44
minInstances: 0
55

66
# Environment variables and secrets.
7+
# Grant access to secrets in Cloud Secret Manager.
8+
# See https://firebase.google.com/docs/app-hosting/configure#secret-parameters
9+
# If you would like to change any keys' values in local development with the emulator
10+
# (e.g. using Stripe Sandbox keys), you can overwrite values in apphosting.emulator.yaml
711
env:
8-
# Grant access to secrets in Cloud Secret Manager.
9-
# See https://firebase.google.com/docs/app-hosting/configure#secret-parameters
10-
- variable: NEXT_PUBLIC_FIREBASE_API_KEY
11-
secret: FIREBASE_API_KEY
12-
- variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
13-
secret: FIREBASE_AUTH_DOMAIN
14-
- variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
15-
secret: FIREBASE_PROJECT_ID
16-
- variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
17-
secret: FIREBASE_STORAGE_BUCKET
18-
- variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
19-
secret: FIREBASE_MESSAGING_SENDER_ID
20-
- variable: NEXT_PUBLIC_FIREBASE_APP_ID
21-
secret: FIREBASE_APP_ID
22-
- variable: GOOGLE_API_KEY
23-
secret: GOOGLE_API_KEY
24-
- variable: STRIPE_ACCOUNT_ID
25-
secret: STRIPE_ACCOUNT_ID
26-
- variable: STRIPE_SECRET_KEY
27-
secret: STRIPE_SECRET_KEY
28-
- variable: NEXT_PUBLIC_STRIPE_PUB_KEY
29-
secret: STRIPE_PUB_KEY
30-
- variable: STRIPE_WEBHOOK_SECRET
31-
secret: STRIPE_WEBHOOK_SECRET
12+
# Values for Firebase config can be found by clicking the cog next to "Project Overview"
13+
# in the firebase console and clicking "project settings"
14+
# - variable: NEXT_PUBLIC_FIREBASE_API_KEY
15+
# value: <YOUR VALUE HERE>
16+
# - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
17+
# value: <YOUR VALUE HERE>
18+
# - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
19+
# value: <YOUR VALUE HERE>
20+
# - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
21+
# value: <YOUR VALUE HERE>
22+
# - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
23+
# value: <YOUR VALUE HERE>
24+
# - variable: NEXT_PUBLIC_FIREBASE_APP_ID
25+
# value: <YOUR VALUE HERE>
26+
27+
# The Google API key needs access to the Generative AI APIs. Create your key by visiting
28+
# https://ai.google.dev/gemini-api/docs and clicking "Get a Gemini API Key"
29+
# You can then run `firebase apphosting:secrets:set google-api-key and pasting the value.
30+
# - variable: GOOGLE_API_KEY
31+
# secret: google-api-key
32+
33+
# To use stripe, you must create an account on stripe.com. From the stripe dashboard
34+
# You can copy the NEXT_PUBLIC_STRIPE_PUB_KEY from "Publishable key" in the dashboard.
35+
# You can set STRIPE_SECRET_KEY by calling `firebase apphosting:secrets:set stripe-secret-key`
36+
# and pasting the value listed as "Secret key" in the dashboard.
37+
# To get the stripe webhook secret, create a stripe webhook as described in README.md,
38+
# go to the webhook details page and click "Reveal" under "Signing secret". Copy that value,
39+
# run `firebase apphosting:secrets:set stripe-webhook-secret` and paste the secret value when
40+
# prompted. The value for STRIPE_ACCOUNT_ID can be found in the upper right corner of the
41+
# webhook details page.
42+
# - variable: NEXT_PUBLIC_STRIPE_PUB_KEY
43+
# value: <YOUR VALUE HERE>
44+
# - variable: STRIPE_SECRET_KEY
45+
# secret: stripe-secret-key
46+
# - variable: STRIPE_ACCOUNT_ID
47+
# value: <YOUR VALUE HERE>
48+
# - variable: STRIPE_WEBHOOK_SECRET
49+
# secret: stripe-webhook-secret

starters/nextjs/firebase-ecommerce/dataconnect-generated/js/default-connector/README.md

Lines changed: 24 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
- [*SearchProductTitleUsingL2Similarity*](#searchproducttitleusingl2similarity)
1313
- [*SearchProductReviewContentUsingL2Similarity*](#searchproductreviewcontentusingl2similarity)
1414
- [*GetOrdersByCustomerId*](#getordersbycustomerid)
15-
- [*GetCurrentCustomerOrders*](#getcurrentcustomerorders)
1615
- [*GetOrderById*](#getorderbyid)
1716
- [**Mutations**](#mutations)
1817
- [*UpsertCustomer*](#upsertcustomer)
@@ -988,124 +987,10 @@ Recall that executing the `GetOrdersByCustomerId` query returns a `QueryPromise`
988987
The `data` property is an object of type `GetOrdersByCustomerIdData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields:
989988
```javascript
990989
export interface GetOrdersByCustomerIdData {
991-
orders: ({
992-
id: UUIDString;
993-
customerId: string;
994-
processedAt: DateString;
995-
chargeId?: string | null;
996-
paymentIntentId?: string | null;
997-
receiptUrl?: string | null;
998-
subtotalPrice: number;
999-
totalPrice: number;
1000-
financialStatus: string;
1001-
fulfillmentStatus: string;
1002-
orderItems_on_order: ({
1003-
id: UUIDString;
1004-
quantity: number;
1005-
price: number;
1006-
product: {
1007-
id: UUIDString;
1008-
title: string;
1009-
handle: string;
1010-
productImages_on_product: ({
1011-
url: string;
1012-
altText?: string | null;
1013-
width: number;
1014-
height: number;
1015-
})[];
1016-
} & Product_Key;
1017-
} & OrderItem_Key)[];
1018-
} & Order_Key)[];
1019-
}
1020-
```
1021-
### Using `GetOrdersByCustomerId`'s action shortcut function
1022-
1023-
```javascript
1024-
import { getDataConnect, DataConnect } from 'firebase/data-connect';
1025-
import { connectorConfig, getOrdersByCustomerId, GetOrdersByCustomerIdVariables } from '@firebasegen/default-connector';
1026-
1027-
// The `GetOrdersByCustomerId` query requires an argument of type `GetOrdersByCustomerIdVariables`:
1028-
const getOrdersByCustomerIdVars: GetOrdersByCustomerIdVariables = {
1029-
customerId: ...,
1030-
};
1031-
1032-
// Call the `getOrdersByCustomerId()` function to execute the query.
1033-
// You can use the `await` keyword to wait for the promise to resolve.
1034-
const { data } = await getOrdersByCustomerId(getOrdersByCustomerIdVars);
1035-
// Variables can be defined inline as well.
1036-
const { data } = await getOrdersByCustomerId({ customerId: ..., });
1037-
1038-
// You can also pass in a `DataConnect` instance to the action shortcut function.
1039-
const dataConnect = getDataConnect(connectorConfig);
1040-
const { data } = await getOrdersByCustomerId(dataConnect, getOrdersByCustomerIdVars);
1041-
1042-
console.log(data.orders);
1043-
1044-
// Or, you can use the `Promise` API.
1045-
getOrdersByCustomerId(getOrdersByCustomerIdVars).then((response) => {
1046-
const data = response.data;
1047-
console.log(data.orders);
1048-
});
1049-
```
1050-
1051-
### Using `GetOrdersByCustomerId`'s `QueryRef` function
1052-
1053-
```javascript
1054-
import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect';
1055-
import { connectorConfig, getOrdersByCustomerIdRef, GetOrdersByCustomerIdVariables } from '@firebasegen/default-connector';
1056-
1057-
// The `GetOrdersByCustomerId` query requires an argument of type `GetOrdersByCustomerIdVariables`:
1058-
const getOrdersByCustomerIdVars: GetOrdersByCustomerIdVariables = {
1059-
customerId: ...,
1060-
};
1061-
1062-
// Call the `getOrdersByCustomerIdRef()` function to get a reference to the query.
1063-
const ref = getOrdersByCustomerIdRef(getOrdersByCustomerIdVars);
1064-
// Variables can be defined inline as well.
1065-
const ref = getOrdersByCustomerIdRef({ customerId: ..., });
1066-
1067-
// You can also pass in a `DataConnect` instance to the `QueryRef` function.
1068-
const dataConnect = getDataConnect(connectorConfig);
1069-
const ref = getOrdersByCustomerIdRef(dataConnect, getOrdersByCustomerIdVars);
1070-
1071-
// Call `executeQuery()` on the reference to execute the query.
1072-
// You can use the `await` keyword to wait for the promise to resolve.
1073-
const { data } = await executeQuery(ref);
1074-
1075-
console.log(data.orders);
1076-
1077-
// Or, you can use the `Promise` API.
1078-
executeQuery(ref).then((response) => {
1079-
const data = response.data;
1080-
console.log(data.orders);
1081-
});
1082-
```
1083-
1084-
## GetCurrentCustomerOrders
1085-
You can execute the `GetCurrentCustomerOrders` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts):
1086-
```javascript
1087-
getCurrentCustomerOrders(): QueryPromise<GetCurrentCustomerOrdersData, undefined>;
1088-
1089-
getCurrentCustomerOrdersRef(): QueryRef<GetCurrentCustomerOrdersData, undefined>;
1090-
```
1091-
You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function.
1092-
```javascript
1093-
getCurrentCustomerOrders(dc: DataConnect): QueryPromise<GetCurrentCustomerOrdersData, undefined>;
1094-
1095-
getCurrentCustomerOrdersRef(dc: DataConnect): QueryRef<GetCurrentCustomerOrdersData, undefined>;
1096-
```
1097-
1098-
### Variables
1099-
The `GetCurrentCustomerOrders` query has no variables.
1100-
### Return Type
1101-
Recall that executing the `GetCurrentCustomerOrders` query returns a `QueryPromise` that resolves to an object with a `data` property.
1102-
1103-
The `data` property is an object of type `GetCurrentCustomerOrdersData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields:
1104-
```javascript
1105-
export interface GetCurrentCustomerOrdersData {
1106990
orders?: {
1107991
orders_on_customer: ({
1108992
id: UUIDString;
993+
customerId: string;
1109994
processedAt: DateString;
1110995
chargeId?: string | null;
1111996
paymentIntentId?: string | null;
@@ -1134,43 +1019,55 @@ export interface GetCurrentCustomerOrdersData {
11341019
};
11351020
}
11361021
```
1137-
### Using `GetCurrentCustomerOrders`'s action shortcut function
1022+
### Using `GetOrdersByCustomerId`'s action shortcut function
11381023

11391024
```javascript
11401025
import { getDataConnect, DataConnect } from 'firebase/data-connect';
1141-
import { connectorConfig, getCurrentCustomerOrders } from '@firebasegen/default-connector';
1026+
import { connectorConfig, getOrdersByCustomerId, GetOrdersByCustomerIdVariables } from '@firebasegen/default-connector';
11421027

1028+
// The `GetOrdersByCustomerId` query requires an argument of type `GetOrdersByCustomerIdVariables`:
1029+
const getOrdersByCustomerIdVars: GetOrdersByCustomerIdVariables = {
1030+
customerId: ...,
1031+
};
11431032

1144-
// Call the `getCurrentCustomerOrders()` function to execute the query.
1033+
// Call the `getOrdersByCustomerId()` function to execute the query.
11451034
// You can use the `await` keyword to wait for the promise to resolve.
1146-
const { data } = await getCurrentCustomerOrders();
1035+
const { data } = await getOrdersByCustomerId(getOrdersByCustomerIdVars);
1036+
// Variables can be defined inline as well.
1037+
const { data } = await getOrdersByCustomerId({ customerId: ..., });
11471038

11481039
// You can also pass in a `DataConnect` instance to the action shortcut function.
11491040
const dataConnect = getDataConnect(connectorConfig);
1150-
const { data } = await getCurrentCustomerOrders(dataConnect);
1041+
const { data } = await getOrdersByCustomerId(dataConnect, getOrdersByCustomerIdVars);
11511042

11521043
console.log(data.orders);
11531044

11541045
// Or, you can use the `Promise` API.
1155-
getCurrentCustomerOrders().then((response) => {
1046+
getOrdersByCustomerId(getOrdersByCustomerIdVars).then((response) => {
11561047
const data = response.data;
11571048
console.log(data.orders);
11581049
});
11591050
```
11601051

1161-
### Using `GetCurrentCustomerOrders`'s `QueryRef` function
1052+
### Using `GetOrdersByCustomerId`'s `QueryRef` function
11621053

11631054
```javascript
11641055
import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect';
1165-
import { connectorConfig, getCurrentCustomerOrdersRef } from '@firebasegen/default-connector';
1056+
import { connectorConfig, getOrdersByCustomerIdRef, GetOrdersByCustomerIdVariables } from '@firebasegen/default-connector';
11661057

1058+
// The `GetOrdersByCustomerId` query requires an argument of type `GetOrdersByCustomerIdVariables`:
1059+
const getOrdersByCustomerIdVars: GetOrdersByCustomerIdVariables = {
1060+
customerId: ...,
1061+
};
11671062

1168-
// Call the `getCurrentCustomerOrdersRef()` function to get a reference to the query.
1169-
const ref = getCurrentCustomerOrdersRef();
1063+
// Call the `getOrdersByCustomerIdRef()` function to get a reference to the query.
1064+
const ref = getOrdersByCustomerIdRef(getOrdersByCustomerIdVars);
1065+
// Variables can be defined inline as well.
1066+
const ref = getOrdersByCustomerIdRef({ customerId: ..., });
11701067

11711068
// You can also pass in a `DataConnect` instance to the `QueryRef` function.
11721069
const dataConnect = getDataConnect(connectorConfig);
1173-
const ref = getCurrentCustomerOrdersRef(dataConnect);
1070+
const ref = getOrdersByCustomerIdRef(dataConnect, getOrdersByCustomerIdVars);
11741071

11751072
// Call `executeQuery()` on the reference to execute the query.
11761073
// You can use the `await` keyword to wait for the promise to resolve.

starters/nextjs/firebase-ecommerce/dataconnect-generated/js/default-connector/esm/index.esm.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,16 +156,6 @@ export function getOrdersByCustomerId(dcOrVars, vars) {
156156
return executeQuery(getOrdersByCustomerIdRef(dcOrVars, vars));
157157
}
158158

159-
export function getCurrentCustomerOrdersRef(dc) {
160-
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
161-
dcInstance._useGeneratedSdk();
162-
return queryRef(dcInstance, 'GetCurrentCustomerOrders');
163-
}
164-
165-
export function getCurrentCustomerOrders(dc) {
166-
return executeQuery(getCurrentCustomerOrdersRef(dc));
167-
}
168-
169159
export function getOrderByIdRef(dcOrVars, vars) {
170160
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
171161
dcInstance._useGeneratedSdk();

0 commit comments

Comments
 (0)