grahamearley/FirestoreGoogleAppsScript

How to import typings for Typescript apps script development

Closed this issue · 4 comments

I see that since #87 this library was converted to Typescript. What's the correct way to import typescript definitions so that it can be used within VSCode?

Minimal Code to Reproduce the Problem

Explain the Problem in Detail

I've tried importing it as a reference:

/// <reference path="../node_modules/firestore_google-apps-script/typings/index.d.ts" />

But this only imports a FirestoreAPI which comes from typings/index.d.ts

It's unclear how I should use this to develop in a Typescript environment.

Thanks in advance!

Library Version: 33

I haven't used VSCode with this project yet, but I can't imagine it would be too difficult. Sorry I can't help further with this. But I pretty much used command line tools to integrate with GAS to update the library.

@davidbielik Any luck with this? I am interested in importing typescript types for local development as well.

@davidbielik @BarryMolina

Here's my firestore.ts file that's also used to import the other typings:

// This is required because it "imports" the typings (importing them breaks the runtime and tsconfig doesn't seem to detect them.)
/// <reference path="../../../node_modules/@types/google-apps-script/index.d.ts" />

// These are required because they "import" the FirestoreApp library.
/// <reference path="../../../node_modules/firestore_google-apps-script/typings/index.d.ts" />
/// <reference path="../../../node_modules/firestore_google-apps-script/Document.ts" />
/// <reference path="../../../node_modules/firestore_google-apps-script/Firestore.ts" />

/**
 * Documentation:
 * https://github.com/grahamearley/FirestoreGoogleAppsScript
 */
export const firestore = getFirestore();

// The libary is provided through this object, but the ts references above don't.
declare const FirestoreApp: {
  getFirestore(email: string, key: string, projectId: string, apiVersion?: Version): Firestore;
};

export function getFirestore() {
  const email = PropertiesService.getScriptProperties().getProperty("SERVICE_ACCOUNT_EMAIL");

  // replaceAll is necessary, because the property value doesn't allow newlines
  const key = PropertiesService.getScriptProperties().getProperty("SERVICE_ACCOUNT_KEY")?.replaceAll("\\n", "\n");
  const projectId = "die-ringe-bodyworkout-app";

  return FirestoreApp.getFirestore(email!, key!, projectId);
}

export function unwrapObject(obj: Document): ValueObject {
  return Object.entries(obj.fields || {}).reduce(
    (o: Record<string, Value>, [key, val]: [string, FirestoreAPI.Value]) => {
      o[key] = unwrapValue(val);
      return o;
    },
    {}
  );
}

function unwrapValue(obj: FirestoreAPI.Value): Value {
  // eslint-disable-next-line prefer-const
  let [type, val]: [string, any] = Object.entries(obj)[0];
  switch (type) {
    case "referenceValue":
    case "bytesValue":
    case "stringValue":
    case "booleanValue":
    case "geoPointValue":
      return val;
    case "doubleValue":
      return parseFloat(val as string);
    case "integerValue":
      return parseInt(val as string);
    case "mapValue":
      return unwrapObject(val as FirestoreAPI.MapValue);
    case "arrayValue":
      return unwrapArray(val.values);
    case "timestampValue":
      return unwrapDate(val as string);
    case "nullValue":
    default:
      return null;
  }
}

function unwrapArray(wrappedArray: FirestoreAPI.Value[] = []): Value[] {
  return wrappedArray.map(unwrapValue, this);
}

function unwrapDate(wrappedDate: string): Date {
  // Copied from Util_.regexDatePrecision
  const regex = /(\.\d{3})\d+/;

  // Trim out extra microsecond precision
  return new Date(wrappedDate.replace(regex, "$1"));
}

looks like a pretty hacky solution to me, but it seems to work pretty neatly so far.

I would like to also know how I can use this library outside of the web based editor. The above solution does not work in the context of my project!