How to listen for specific Firestore document creation event?

Viewed 922

I am implementing a command/response pattern where the user writes to a command collection by calling add with a payload under his own userId, and then gets the data from a similar response path.

However the code below doesn't work, because onSnapshot can not listen for a document that hasn't yet been created (document command.id in the /responses/{userId}/register collection). This would be easy to solve with an onCreate handler, which exists for cloud functions but not for the JS firebase client API it seems.

This is using redux-firestore and some of my app helper functions, but you'll get the idea. The command and response document structures use { payload, error} similar to FSA

Cloud Function

export const register = functions.firestore
  .document("commands/{userId}/register/{commandId}")
  .onCreate(async event => {
    const payload = event.data.get("payload");
    const { userId, commandId } = event.params;
    const response = db.document(`responses/${userId}/register/${commandId}`)

    // possibly something bad will happen
    try {

      // do something with payload...

      return response.set({
        payload: "ok" // or pass relevant response data
      })
    } catch(err) {
      return response.set({
        error: true
        payload: error
      })
    }
  });

Client

export async function register(fs: any, userId: string) {
  try {

    // issue a new command
    const command = await fs.add(
      { collection: `commands/${userId}/register` },
      { payload: fs.firestore.FieldValue.serverTimestamp() }
    );

    // wait for the response to be created
    fs.onSnapshot(
      { collection: `responses/${userId}/register`, doc: command.id },
      function onNext(doc) {
        const {error, payload} = doc.data()

        if (error) {
          return notify.error({ title: 'Failed to register', message: payload.message });
        }
        notify.json(payload);
      },
      function onError(err) {
        notify.error(err);
      }
    );
  } catch (err) {
    notify.error(err);
  }
}

Is there no such thing as onCreate for web clients?

The only scalable solution I can think of is to store the response data as a child in the command document, but I think it is not as nice, because I suspect you can not make the permissions as strict then.

I would like the user only to be able to write to the command, and only read from the response paths. If I place the response as a child of command, this would not be possible I think?

I'm wondering if I'm not overlooking some API...

0 Answers
Related