Skip to content

Commit a8ed7f6

Browse files
committed
first draft of streaming sample
1 parent 8ddb421 commit a8ed7f6

File tree

9 files changed

+758
-74
lines changed

9 files changed

+758
-74
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
firebase-debug.log*
8+
firebase-debug.*.log*
9+
10+
# Firebase cache
11+
.firebase/
12+
13+
# Firebase config
14+
15+
# Uncomment this if you'd like others to create their own Firebase project.
16+
# For a team working on the same Firebase project(s), it is recommended to leave
17+
# it commented so all members can deploy to the same project(s) in .firebaserc.
18+
# .firebaserc
19+
20+
# Runtime data
21+
pids
22+
*.pid
23+
*.seed
24+
*.pid.lock
25+
26+
# Directory for instrumented libs generated by jscoverage/JSCover
27+
lib-cov
28+
29+
# Coverage directory used by tools like istanbul
30+
coverage
31+
32+
# nyc test coverage
33+
.nyc_output
34+
35+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
36+
.grunt
37+
38+
# Bower dependency directory (https://bower.io/)
39+
bower_components
40+
41+
# node-waf configuration
42+
.lock-wscript
43+
44+
# Compiled binary addons (http://nodejs.org/api/addons.html)
45+
build/Release
46+
47+
# Dependency directories
48+
node_modules/
49+
50+
# Optional npm cache directory
51+
.npm
52+
53+
# Optional eslint cache
54+
.eslintcache
55+
56+
# Optional REPL history
57+
.node_repl_history
58+
59+
# Output of 'npm pack'
60+
*.tgz
61+
62+
# Yarn Integrity file
63+
.yarn-integrity
64+
65+
# dotenv environment variables file
66+
.env
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Firebase HTTPS Callable functions Quickstart
2+
================================================
3+
4+
The HTTPS Callable functions Quickstart demonstrates how to send requests to a server-side function and get a response back using one of the Client SDKs. It interoperates with the Web, iOS and Android quickstarts.
5+
6+
7+
[Read more about Cloud Functions for Firebase](https://firebase.google.com/docs/functions/)
8+
9+
10+
Getting Started
11+
---------------
12+
13+
1. Install dependencies with `npm install` and deploy with `firebase deploy --only functions`
14+
1. Set up a client (import the functions client SDK, initializeApp, init the functions sdk)
15+
2. Call the function
16+
17+
18+
License
19+
-------
20+
21+
© Google, 2022. Licensed under an [Apache-2](../../../LICENSE) license.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"functions": {
3+
"codebase": "callable-functions",
4+
"predeploy": [
5+
"npm --prefix \"$RESOURCE_DIR\" run lint"
6+
]
7+
},
8+
"hosting": {
9+
"public": "website"
10+
}
11+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
module.exports = {
18+
root: true,
19+
env: {
20+
es2020: true,
21+
node: true,
22+
},
23+
extends: [
24+
"eslint:recommended",
25+
"google",
26+
],
27+
rules: {
28+
quotes: ["error", "double"],
29+
},
30+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// [START imports]
18+
// Dependencies for callable functions.
19+
const {onCall, HttpsError} = require("firebase-functions/v2/https");
20+
const {logger} = require("firebase-functions/v2");
21+
// [END imports]
22+
23+
/**
24+
* Mock api for streaming response
25+
*/
26+
async function generateStream() {
27+
// simulate some latency for a remote API call
28+
await new Promise((resolve) => setTimeout(resolve, 100));
29+
30+
/**
31+
* Fake a few async responses
32+
*/
33+
async function* mockAsyncIterable() {
34+
const sentence = "Hello from Cloud Functions for Firebase!";
35+
36+
for (const word of sentence.split(" ")) {
37+
await new Promise((resolve) => setTimeout(resolve, Math.random() * 500));
38+
yield {text: () => " " + word};
39+
}
40+
}
41+
42+
return {
43+
metadata: {
44+
acceptsStreaming: true},
45+
stream: mockAsyncIterable,
46+
};
47+
}
48+
49+
exports.streamResponse = onCall(async (request, response) => {
50+
console.log("I was called!!!");
51+
console.log("data", request.data);
52+
const prompt = request.data.text || "hello";
53+
54+
const {metadata, stream} = await generateStream(prompt);
55+
56+
for await (const chunk of stream()) {
57+
console.log(chunk);
58+
if (metadata.acceptsStreaming) {
59+
response.sendChunk(chunk.text());
60+
}
61+
}
62+
return true;
63+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "callable-functions-streaming",
3+
"description": "Cloud Functions for Firebase",
4+
"scripts": {
5+
"lint": "eslint .",
6+
"lintfix": "eslint . --fix",
7+
"serve": "firebase emulators:start --only functions",
8+
"shell": "firebase functions:shell",
9+
"start": "npm run shell",
10+
"deploy": "firebase deploy --only functions",
11+
"logs": "firebase functions:log",
12+
"compile": "cp ../../../../tsconfig.template.json ./tsconfig-compile.json && tsc --project tsconfig-compile.json"
13+
},
14+
"engines": {
15+
"node": "18"
16+
},
17+
"main": "index.js",
18+
"dependencies": {
19+
"firebase-admin": "^13.0.2",
20+
"firebase-functions": "^6.2.0"
21+
},
22+
"devDependencies": {
23+
"eslint": "^8.40.0",
24+
"eslint-config-google": "^0.14.0",
25+
"firebase-functions-test": "^3.4.0"
26+
},
27+
"private": true
28+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>title</title>
6+
</head>
7+
<body>
8+
<button id="btn-call-func">Call function</button>
9+
<p id="p-result"></p>
10+
<script type="module">
11+
import { initializeApp } from "https://www.gstatic.com/firebasejs/11.2.0/firebase-app.js";
12+
import {
13+
getFunctions,
14+
httpsCallable,
15+
connectFunctionsEmulator,
16+
} from "https://www.gstatic.com/firebasejs/11.2.0/firebase-functions.js";
17+
18+
// set your firebase config object
19+
const firebaseConfig = undefined;
20+
if (!firebaseConfig) {
21+
throw new Error('You must set your Firebase config');
22+
}
23+
const app = initializeApp(firebaseConfig);
24+
const functions = getFunctions(app);
25+
connectFunctionsEmulator(functions, "127.0.0.1", 5001);
26+
const streamResponse = httpsCallable(functions, "streamResponse");
27+
28+
const callableButton = document.getElementById("btn-call-func");
29+
const resultElement = document.getElementById("p-result");
30+
callableButton.onclick = async () => {
31+
// reset result
32+
resultElement.innerHTML = "";
33+
34+
const resp = await streamResponse.stream({
35+
text: "What is your favorite Firebase service and why?",
36+
});
37+
38+
// append text each time
39+
for await (const message of resp.stream) {
40+
resultElement.innerHTML += message;
41+
}
42+
};
43+
</script>
44+
</body>
45+
</html>

0 commit comments

Comments
 (0)