denoland / deploy_feedback

For reporting issues with Deno Deploy
https://deno.com/deploy
74 stars 5 forks source link

Deploy failures from the firebase tutorial: https://deno.com/deploy/docs/tutorial-firebase/ #131

Open apex2060 opened 2 years ago

apex2060 commented 2 years ago

When utillizing the code and following the tutorial at: https://deno.com/deploy/docs/tutorial-firebase/ On first visit, the deploy fails.

0 TypeError: Cannot read properties of null (reading 'INTERNAL') at Ke (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2184:21) at new Ze (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2310:9) at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:3835:32 at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:8108:4
1 isolate start time: 9 milliseconds
2 TypeError: Cannot read properties of null (reading 'INTERNAL') at Ke (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2184:21) at new Ze (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2310:9) at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:3835:32 at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:8108:4
3 isolate start time: 14 milliseconds
4 TypeError: Cannot read properties of null (reading 'INTERNAL') at Ke (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2184:21) at new Ze (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2310:9) at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:3835:32 at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:8108:4
5 isolate start time: 12 milliseconds
6 TypeError: Cannot read properties of null (reading 'INTERNAL') at Ke (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2184:21) at new Ze (https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:2310:9) at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:3835:32 at https://cdn.skypack.dev/-/@firebase/auth@v0.16.8-zp4BWpLW0rBfBR0kDd0B/dist=es2019,mode=imports/optimized/@firebase/auth.js:8108:4
7 isolate start time: 265 milliseconds
bicarlsen commented 2 years ago

I am receiving similar errors on my local machine. I raised this as a question on StackOverfow. The issue seems to be with compatiblity between the current version of Deno and the @firebase/app module, not the @firebase/auth module, and occurs when initializing the app with initializeApp.

I dug through the firebase module source code, and found the aliases of the objects mentioned in the errors:

Alias Actual Reference
Ke #asNumber firebase-js-sdk/packages/firestore/src/model/transform_operation.ts
Ze IndexedDbPersistence#attachVisibilityHandler firebase-js-sdk/packages/firestore/src/local/indexeddb_persistence.ts
Vagabun commented 2 years ago

Getting the same error. Additionally, can't connect Firestore in Deno script to a local emulator.

ayame113 commented 2 years ago

By the way, importing from https://www.gstatic.com/firebasejs/9.6.0/firebase-app.js will work the firestore and realtime database.

// example

// @deno-types="https://cdn.esm.sh/v58/firebase@9.6.0/app/dist/app/index.d.ts"
import { deleteApp, FirebaseOptions, initializeApp } from "https://www.gstatic.com/firebasejs/9.6.0/firebase-app.js";
// @deno-types="https://cdn.esm.sh/v58/firebase@9.6.0/database/dist/database/index.d.ts"
import { getDatabase, ref, set } from "https://www.gstatic.com/firebasejs/9.6.0/firebase-database.js";

const app = initializeApp({...});
const db = getDatabase(app);
await set(ref(db), 1);

Related: https://github.com/firebase/firebase-js-sdk/issues/5783

bicarlsen commented 2 years ago

The solution from @ayame113 works for me, however when importing the Firestore library I can't use destructuring. E.g.

// does not work
import {
  getFirestore
} from "https://www.gstatic.com/firebasejs/9.6.0/firebase-firestore.js";
// error: Property 'getFirestore' does not exist on type 'typeof import("https://cdn.esm.sh/v58/firebase@9.6.0/database/dist/database/index.d.ts")'.

// works
import * as fs from "https://www.gstatic.com/firebasejs/9.6.0/firebase-firestore.js";
fs.getFirestore()
bgrins commented 2 years ago

I got it working using the gstatic URLs with the latest versions which required some API changes in the app - this gist is working for me https://gist.github.com/bgrins/e3f9ba9430da7b1c5a44241172779db0.

Diff:

 // Firebase uses XMLHttpRequest instead of `fetch()`, so we need to provide a
 // polyfill for it.
 import "https://deno.land/x/xhr@0.1.1/mod.ts";
@@ -8,12 +10,11 @@
 import { installGlobals } from "https://deno.land/x/virtualstorage@0.1.0/mod.ts";

 // Since Deploy is browser-like, we will use the Firebase web client libraries
-// importing in just what we need for this tutorial. We are using the Skypack
-// CDN which also provides modules as ES Modules.
-// @deno-types=https://cdn.skypack.dev/-/firebase@v8.7.0-MrU9zUCxcEMCl2U7Tuz6/dist=es2020,mode=types/index.d.ts
-import firebase from "https://cdn.skypack.dev/firebase@8.7.0/app";
-import "https://cdn.skypack.dev/firebase@8.7.0/auth";
-import "https://cdn.skypack.dev/firebase@8.7.0/firestore";
+// importing in just what we need for this tutorial. We are using the ESM
+// links from https://firebase.google.com/docs/web/setup.
+import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.6.10/firebase-app.js';
+import { getAuth, signInWithEmailAndPassword } from 'https://www.gstatic.com/firebasejs/9.6.10/firebase-auth.js';
+import { getFirestore, collection, addDoc, deleteDoc, getDocs, query, where } from 'https://www.gstatic.com/firebasejs/9.6.10/firebase-firestore.js';

 // For this tutorial, we are going to use the oak middleware framework to create
 // our APIs and integrate to Firebase.
@@ -32,9 +33,10 @@

 const firebaseConfig = JSON.parse(Deno.env.get("FIREBASE_CONFIG"));

-const firebaseApp = firebase.initializeApp(firebaseConfig, "example");
+const firebaseApp = initializeApp(firebaseConfig, "example");
+
+const auth = getAuth(firebaseApp);

-const auth = firebase.auth(firebaseApp);

 /** A map of users that we will log in.  While this tutorial only uses one user
  * retrieved from the environment variables. It demonstrates how this can be
@@ -43,7 +45,7 @@
  * @type {Map<string, firebase.User>} */
 const users = new Map();

-const db = firebase.firestore(firebaseApp);
+const db = getFirestore(firebaseApp);

 const router = new Router();

@@ -66,7 +68,8 @@

 // Returns any documents in the collection
 router.get("/songs", async (ctx) => {
-  const querySnapshot = await db.collection("songs").get();
+  const songsCol = collection(db, "songs");
+  const querySnapshot = await getDocs(songsCol);
   ctx.response.body = querySnapshot.docs.map((doc) => doc.data());
   ctx.response.type = "json";
 });
@@ -74,8 +77,8 @@
 // Returns the first document that matches the title
 router.get("/songs/:title", async (ctx) => {
   const { title } = ctx.params;
-  const querySnapshot = await db.collection("songs").where("title", "==", title)
-    .get();
+  const songsCol = query(collection(db, "songs"), where("title", "==", title));
+  const querySnapshot = await getDocs(songsCol);
   const song = querySnapshot.docs.map((doc) => doc.data())[0];
   if (!song) {
     ctx.response.status = 404;
@@ -97,13 +100,11 @@
   if (!isSong(song)) {
     ctx.throw(Status.BadRequest, "Payload was not well formed");
   }
-  const querySnapshot = await db
-    .collection("songs")
-    .where("title", "==", song.title)
-    .get();
-  await Promise.all(querySnapshot.docs.map((doc) => doc.ref.delete()));
-  const songsRef = db.collection("songs");
-  await songsRef.add(song);
+  const songsCol = query(collection(db, "songs"), where("title", "==", song.title));
+  const querySnapshot = await getDocs(songsCol);
+
+  await Promise.all(querySnapshot.docs.map((doc) => deleteDoc(doc.ref)));
+  addDoc(collection(db, "songs"), song)
   ctx.response.status = Status.NoContent;
 });

@@ -122,7 +123,7 @@
     // in a real application, this is where we would want to redirect the user
     // to a sign-in page for our application, instead of grabbing the
     // authentication details from the environment variables.
-    const creds = await auth.signInWithEmailAndPassword(
+    const creds = await signInWithEmailAndPassword(auth,
       Deno.env.get("FIREBASE_USERNAME"),
       Deno.env.get("FIREBASE_PASSWORD"),
     );