Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add examples of unwrapping firebase data #171

Open
tomchify opened this issue Mar 28, 2024 · 0 comments
Open

Add examples of unwrapping firebase data #171

tomchify opened this issue Mar 28, 2024 · 0 comments

Comments

@tomchify
Copy link

tomchify commented Mar 28, 2024

Is your feature request related to a problem?

I followed the Readme for getting some user data like this:

const firestore = FirestoreApp.getFirestore(email, key, projectId);
const userSnap = firestore.query("users").Where("email", "==", userEmail).Limit(1).Offset(0).Execute()?.[0];
const userDoc = userSnap?.["fields"] ?? {};

userDoc is rather verbose, and requires calls like:

userDoc["uid"].stringValue

I see in the library code there is a Document.ts class with a perfect unwrap static method to turn userSnap into a simple JSON object.

Describe the solution you'd like

Can you explain how to access this Document.unwrap method in an Apps Script?

I tried "const userData = new FirestoreApp.Document(userSnap);" among other things and just couldn't figure it out.

It would be a good idea to add this to the documentation, as it would save others a tremendous amount of time debugging and reinventing the wheel.

Describe alternatives you've considered

I got unwrapping working by copying the following methods into Code.gs in Apps Script:

function unwrapObject(obj) {
  return Object.entries(obj.fields || {}).reduce(
    (o, [key, val]) => {
      o[key] = unwrapValue(val);
      return o;
    },
    {}
  );
}

function unwrapValue(obj) {
    let [type, val] = Object.entries(obj)[0];
    switch (type) {
      case 'referenceValue':
      case 'bytesValue':
      case 'stringValue':
      case 'booleanValue':
      case 'geoPointValue':
        return val;
      case 'doubleValue':
        return parseFloat(val);
      case 'integerValue':
        return parseInt(val);
      case 'mapValue':
        return unwrapObject(val);
      case 'arrayValue':
        console.log("type === arrayValue:", val);
        return unwrapArray(val.values);
      case 'timestampValue':
        return this.unwrapDate(val);
      case 'nullValue':
      default:
        return null;
    }
  }

  function unwrapArray(wrappedArray) {
    console.log("unwrapArray", wrappedArray);
    return wrappedArray?.map(value => unwrapValue(value)) ?? [];
  }

  function unwrapDate(wrappedDate) {
    // Trim out extra microsecond precision
    return new Date(wrappedDate.replace(/(\.\d{3})\d+/, '$1'));
  }

Then you can call

const userData = unwrapObject(userSnap);

... to get JSON like usually returned from firebase npm for instance.

This solution seems not ideal as it duplicates code with the library. Let me know if there's a better way.

btw, thank you for this library :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant