简体   繁体   English

`setDoc` 从 TypeScript 函数写入 Firestore 搞乱了 `npm run build` 上的目录结构

[英]`setDoc` write to Firestore from TypeScript Functions messes up directory structure on `npm run build`

Transpiling TypeScript creates a new, incorrect directory structure when a Firebase Function writes to Firestore with setDoc or updateDoc .当 Firebase 函数使用setDocupdateDoc写入 Firestore 时,转译 TypeScript 会创建一个新的、不正确的目录结构。

This code transpiles and runs correctly:此代码可以正确转译和运行:

index.ts索引.ts

import * as functions from "firebase-functions";
export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate((snap, context) => {
    try {
      const original = snap.data().original;
      const uppercase = original.toUpperCase();
      return snap.ref.set({ uppercase }, { merge: true }); // writes to the same document
    } catch (error) {
      console.error(error); // emulator always throws an "unhandled error": "Your function timed out after ~60s."
      return 0;
    }
  });

The first time the function is transpiled in a new directory the transpiler makes this directory structure:函数第一次在新目录中转译时,转译器会生成以下目录结构:

myproject
├── environments
│   └── environment.ts
├── functions
│   ├── lib
│   │   ├── index.js
│   │   ├── index.js.map
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── src
│   │   ├── index.ts
│   └── tsconfig.json

That directory structure is correct.该目录结构是正确的。 The main in package.json is package.json中的main

lib/index.js

Let's change the code a little and use setDoc to write to a different directory in Firestore:让我们稍微更改一下代码并使用setDoc写入 Firestore 中的不同目录:

index.ts索引.ts

import * as functions from "firebase-functions";
import { initializeApp } from "firebase/app";
import { getFirestore, setDoc, doc } from "firebase/firestore";
import { environment } from '../../environments/environment';
const firebaseApp = initializeApp(environment.firebase);
const firestore = getFirestore(firebaseApp);

export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate((snap, context) => {
    try {
      const original = snap.data().original;
      const uppercase = original.toUpperCase();

      return setDoc(
        doc(firestore, 'AnotherCollection', context.params.docId),
        { uppercase }, { merge: true }
      );

    } catch (error) {
      console.error(error); // emulator always throws an "unhandled error": "Your function timed out after ~60s."
      return 0;
    }
  });

I transpile the function with npm run build in the functions directory.我在functions目录中使用npm run build编译函数。 The directory structure changes to:目录结构更改为:

myproject
├── environments
│   └── environment.ts
├── functions
│   ├── lib
│   │   ├── environments
│   │   │   ├── environment.js
│   │   │   └── environment.js.map
│   │   ├── functions
│   │   │   └── src
│   │   │       ├── index.js
│   │   │       ├── index.js.map
│   │   ├── index.js
│   │   ├── index.js.map
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── src
│   │   ├── index.ts
│   └── tsconfig.json

The transpiler added three new directories and four new files.转译器添加了三个新目录和四个新文件。 It's exposing my apiKey and other credentials.它暴露了我的apiKey和其他凭据。 To make the new function run I changed main to为了使新功能运行,我将main更改为

lib/functions/src/index.js

Now the new code runs but it won't write to Firestore.现在新代码运行了,但它不会写入 Firestore。 I'm getting PERMISSION_DENIED: Missing or insufficient permissions.我收到PERMISSION_DENIED: Missing or insufficient permissions. errors.错误。 Here's my rules:这是我的规则:

firestore-rules Firestore 规则

rules_version = "2";
service cloud.firestore {
  match /databases/{database}/documents {
  
    match /{document=**} {
      allow read, write;
    }
  }
}

Don't worry, those rules are for the emulator, not for production.别担心,这些规则适用于模拟器,不适用于生产。

A couple more weird things.还有一些奇怪的事情。 Visual Studio Code shows a single directory functions/src , not two, nested directories. Visual Studio Code 显示单个目录functions/src ,而不是两个嵌套目录。 (MacOS shows two nested directories.) (MacOS 显示两个嵌套目录。)

I can deploy the new function to Cloud Functions with firebase deploy but gcloud functions deploy won't deploy the function.我可以使用 firebase deploy 将新函数部署到 Cloud Functions,但firebase deploy gcloud functions deploy不会部署该函数。 It throws an error that it can't find index.js :它抛出找不到index.js的错误:

lib/functions/src/index.js does not exist;

What is going on here???这里发生了什么??? To test this I spun up four new Firebase Functions directories.为了对此进行测试,我创建了四个新的 Firebase Functions 目录。 I tried different functions.我尝试了不同的功能。 It happens every time I use setDoc or updateDoc , and doesn't happen if the code doesn't include setDoc or updateDoc .每次我使用setDocupdateDoc时都会发生,如果代码不包含setDocupdateDoc则不会发生。

Here's my tsconfig.json :这是我的tsconfig.json

tsconfig.json tsconfig.json文件

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "es2017"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

Thanks, @Doug Stevenson!谢谢,@Doug Stevenson! What I'm reading in your comment is that Firebase Cloud Functions can't use the Firebase 9 syntax setDoc and updateDoc for Firestore, and uploadString etc. for Storage.我在您的评论中读到的是 Firebase Cloud Functions 不能将 Firebase 9 语法setDocupdateDoc用于 Firestore,以及uploadString等用于存储。 We have to use the old school Firebase syntax, like this:我们必须使用老式的 Firebase 语法,如下所示:

index.js索引.js

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate(async (snap: any, context: any) => {
    try {
        const original = snap.data().original;
        const uppercase = original.toUpperCase();
        await admin.firestore().collection('AnotherCollection').add({uppercase: uppercase});
        return uppercase;
    } catch (error) {
        console.error(error); // emulator always throws an "unhandled error": "Your function timed out after ~60s."
        return 0;
    }
});

That transpiled without creating new directories or files, and ran without a problem.在没有创建新目录或文件的情况下进行了编译,并且运行没有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM